<commit_before>use super::{child_properties, function, general, properties, signal, trait_impls};
use crate::{
    analysis::special_functions::Type,
    analysis::{
        self,
        rust_type::{rust_type, rust_type_full},
    },
    case::CaseExt,
    codegen::general::{version_condition_no_doc, version_condition_string},
    env::Env,
    library, nameutil,
    traits::IntoString,
};
use std::io::{Result, Write};

pub fn generate(
    w: &mut dyn Write,
    env: &Env,
    analysis: &analysis::object::Info,
    generate_display_trait: bool,
) -> Result<()> {
    general::start_comments(w, &env.config)?;
    general::uses(w, env, &analysis.imports, analysis.version)?;

    general::define_object_type(
        w,
        env,
        &analysis.name,
        &analysis.c_type,
        analysis.c_class_type.as_deref(),
        &analysis.get_type,
        analysis.is_interface,
        &analysis.supertypes,
    )?;

    if need_generate_inherent(analysis) {
        writeln!(w)?;
        write!(w, "impl {} {{", analysis.name)?;
        for func_analysis in &analysis.constructors() {
            function::generate(
                w,
                env,
                func_analysis,
                Some(&analysis.specials),
                analysis.version,
                false,
                false,
                1,
            )?;
        }

        if !need_generate_trait(analysis) {
            for func_analysis in &analysis.methods() {
                function::generate(
                    w,
                    env,
                    func_analysis,
                    Some(&analysis.specials),
                    analysis.version,
                    false,
                    false,
                    1,
                )?;
            }

            for property in &analysis.properties {
                properties::generate(w, env, property, false, false, 1)?;
            }

            for child_property in &analysis.child_properties {
                child_properties::generate(w, env, child_property, false, false, 1)?;
            }
        }

        for func_analysis in &analysis.functions() {
            function::generate(
                w,
                env,
                func_analysis,
                Some(&analysis.specials),
                analysis.version,
                false,
                false,
                1,
            )?;
        }

        if !need_generate_trait(analysis) {
            for signal_analysis in analysis
                .signals
                .iter()
                .chain(analysis.notify_signals.iter())
            {
                signal::generate(w, env, signal_analysis, false, false, 1)?;
            }
        }

        writeln!(w, "}}")?;

        general::declare_default_from_new(w, env, &analysis.name, &analysis.functions)?;
    }

    trait_impls::generate(
        w,
        env,
        &analysis.name,
        &analysis.functions,
        &analysis.specials,
        if need_generate_trait(analysis) {
            Some(&analysis.trait_name)
        } else {
            None
        },
        analysis.version,
    )?;

    if !analysis.builder_properties.is_empty() {
        writeln!(w)?;
        generate_builder(w, env, analysis)?;
    }

    if analysis.concurrency != library::Concurrency::None {
        writeln!(w)?;
    }

    match analysis.concurrency {
        library::Concurrency::Send | library::Concurrency::SendSync => {
            writeln!(w, "unsafe impl Send for {} {{}}", analysis.name)?;
        }
        library::Concurrency::SendUnique => {
            if env.namespaces.is_glib_crate {
                writeln!(w, "unsafe impl ::SendUnique for {} {{", analysis.name)?;
            } else {
                writeln!(w, "unsafe impl glib::SendUnique for {} {{", analysis.name)?;
            }

            writeln!(w, "    fn is_unique(&self) -> bool {{")?;
            writeln!(w, "        self.ref_count() == 1")?;
            writeln!(w, "    }}")?;

            writeln!(w, "}}")?;
        }
        _ => (),
    }

    if let library::Concurrency::SendSync = analysis.concurrency {
        writeln!(w, "unsafe impl Sync for {} {{}}", analysis.name)?;
    }

    if !analysis.final_type {
        writeln!(w)?;
        writeln!(
            w,
            "pub const NONE_{}: Option<&{}> = None;",
            analysis.name.to_snake().to_uppercase(),
            analysis.name
        )?;
    }

    if need_generate_trait(analysis) {
        writeln!(w)?;
        generate_trait(w, env, analysis)?;
    }

    if generate_display_trait && !analysis.specials.has_trait(Type::Display) {
        writeln!(w, "\nimpl fmt::Display for {} {{", analysis.name,)?;
        // Generate Display trait implementation.
        writeln!(
            w,
            "\tfn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {{\n\
             \t\tf.write_str(\"{}\")\n\
             \t}}\n\
             }}",
            analysis.name
        )?;
    }

    Ok(())
}

// TODO: instead create a Vec<> inside the Builder instead of Options.
fn generate_builder(w: &mut dyn Write, env: &Env, analysis: &analysis::object::Info) -> Result<()> {
    let mut methods = vec![];
    let mut properties = vec![];
    writeln!(w, "#[derive(Clone, Default)]")?;
    writeln!(w, "pub struct {}Builder {{", analysis.name)?;
    for property in &analysis.builder_properties {
        match rust_type(env, property.typ) {
            Ok(type_string) => {
                let type_string = match type_string.as_str() {
                    s if nameutil::is_gstring(s) => "String",
                    "Vec<GString>" | "Vec<glib::GString>" | "Vec<crate::GString>" => "Vec<String>",
                    typ => typ,
                };
                let mut param_type = rust_type_full(
                    env,
                    property.typ,
                    library::Nullable(false),
                    property.set_in_ref_mode,
                    library::ParameterScope::None,
                    library::Concurrency::None,
                )
                .into_string();
                let (param_type_override, bounds, conversion) = match &param_type[..] {
                    "&str" => (None, String::new(), ".to_string()"),
                    "&[&str]" => (Some("Vec<String>".to_string()), String::new(), ""),
                    _ if !property.bounds.is_empty() => {
                        let (bounds, _) = function::bounds(&property.bounds, &[], false, false);
                        let alias = property
                            .bounds
                            .get_parameter_alias_info(&property.name)
                            .map(|(alias, _)| format!("&{}", alias));
                        (alias, bounds, ".clone().upcast()")
                    }
                    typ if typ.starts_with('&') => (None, String::new(), ".clone()"),
                    _ => (None, String::new(), ""),
                };
                if let Some(param_type_override) = param_type_override {
                    param_type = param_type_override.to_string();
                }
                let name = nameutil::mangle_keywords(nameutil::signal_to_snake(&property.name));
                let version_condition_string =
                    version_condition_string(env, property.version, false, 1);
                if let Some(ref version_condition_string) = version_condition_string {
                    writeln!(w, "{}", version_condition_string)?;
                }
                writeln!(w, "    {}: Option<{}>,", name, type_string)?;
                let prefix = version_condition_string
                    .map(|version| format!("{}\n", version))
                    .unwrap_or_default();
                methods.push(format!(
                    "\n{prefix}    pub fn {name}{bounds}(mut self, {name}: {param_type}) -> Self {{
        self.{name} = Some({name}{conversion});
        self
    }}",
                    prefix = prefix,
                    param_type = param_type,
                    name = name,
                    conversion = conversion,
                    bounds = bounds
                ));
                properties.push(property);
            }
            Err(_) => writeln!(w, "    //{}: /*Unknown type*/,", property.name)?,
        }
    }
    writeln!(
        w,
        "}}

impl {}Builder {{
    pub fn new() -> Self {{
        Self::default()
    }}
",
        analysis.name
    )?;

    writeln!(
        w,
        "
    pub fn build(self) -> {} {{
        let mut properties: Vec<(&str, &dyn ToValue)> = vec![];",
        analysis.name
    )?;
    for property in &properties {
        let name = nameutil::mangle_keywords(nameutil::signal_to_snake(&property.name));
        version_condition_no_doc(w, env, property.version, false, 2)?;
        writeln!(
            w,
            "\
            if let Some(ref {field}) = self.{field} {{
                properties.push((\"{name}\", {field}));
            }}",
            name = property.name,
            field = name
        )?;
    }
    let glib_crate_name = if env.namespaces.is_glib_crate {
        "crate"
    } else {
        "glib"
    };

    // The split allows us to not have clippy::let_and_return lint disabled
    if let Some(code) = analysis.builder_postprocess.as_ref() {
        writeln!(
            w,
            r#"        let ret = {}::Object::new::<{}>(&properties)
                .expect("Failed to create an instance of {}"");"#,
            glib_crate_name, analysis.name, analysis.name,
        )?;
        writeln!(w, "        {{\n            {}\n        }}", code)?;
        writeln!(w, "    ret\n    }}")?;
    } else {
        writeln!(
            w,
            r#"        {}::Object::new::<{}>(&properties)
                .expect("Failed to create an instance of {}")"#,
            glib_crate_name, analysis.name, analysis.name,
        )?;
        writeln!(w, "\n    }}")?;
    }

    for method in methods {
        writeln!(w, "{}", method)?;
    }
    writeln!(w, "}}")
}

fn generate_trait(w: &mut dyn Write, env: &Env, analysis: &analysis::object::Info) -> Result<()> {
    write!(w, "pub trait {}: 'static {{", analysis.trait_name)?;

    for func_analysis in &analysis.methods() {
        function::generate(
            w,
            env,
            func_analysis,
            Some(&analysis.specials),
            analysis.version,
            true,
            true,
            1,
        )?;
    }
    for property in &analysis.properties {
        properties::generate(w, env, property, true, true, 1)?;
    }
    for child_property in &analysis.child_properties {
        child_properties::generate(w, env, child_property, true, true, 1)?;
    }
    for signal_analysis in analysis
        .signals
        .iter()
        .chain(analysis.notify_signals.iter())
    {
        signal::generate(w, env, signal_analysis, true, true, 1)?;
    }
    writeln!(w, "}}")?;

    writeln!(w)?;
    write!(
        w,
        "impl<O: IsA<{}>> {} for O {{",
        analysis.name, analysis.trait_name,
    )?;

    for func_analysis in &analysis.methods() {
        function::generate(
            w,
            env,
            func_analysis,
            Some(&analysis.specials),
            analysis.version,
            true,
            false,
            1,
        )?;
    }
    for property in &analysis.properties {
        properties::generate(w, env, property, true, false, 1)?;
    }
    for child_property in &analysis.child_properties {
        child_properties::generate(w, env, child_property, true, false, 1)?;
    }
    for signal_analysis in analysis
        .signals
        .iter()
        .chain(analysis.notify_signals.iter())
    {
        signal::generate(w, env, signal_analysis, true, false, 1)?;
    }
    writeln!(w, "}}")?;

    Ok(())
}

fn need_generate_inherent(analysis: &analysis::object::Info) -> bool {
    analysis.has_constructors || analysis.has_functions || !need_generate_trait(analysis)
}

fn need_generate_trait(analysis: &analysis::object::Info) -> bool {
    analysis.generate_trait
}

pub fn generate_reexports(
    env: &Env,
    analysis: &analysis::object::Info,
    module_name: &str,
    contents: &mut Vec<String>,
    traits: &mut Vec<String>,
) {
    let mut cfgs: Vec<String> = Vec::new();
    if let Some(cfg) = general::cfg_condition_string(&analysis.cfg_condition, false, 0) {
        cfgs.push(cfg);
    }
    if let Some(cfg) = general::version_condition_string(env, analysis.version, false, 0) {
        cfgs.push(cfg);
    }
    if let Some(cfg) = general::cfg_deprecated_string(env, analysis.deprecated_version, false, 0) {
        cfgs.push(cfg);
    }

    contents.push("".to_owned());
    contents.extend_from_slice(&cfgs);
    contents.push(format!("mod {};", module_name));
    contents.extend_from_slice(&cfgs);

    let none_type = if !analysis.final_type {
        format!(", NONE_{}", analysis.name.to_snake().to_uppercase())
    } else {
        String::new()
    };

    contents.push(format!(
        "pub use self::{}::{{{}{}}};",
        module_name, analysis.name, none_type
    ));
    if need_generate_trait(analysis) {
        for cfg in &cfgs {
            traits.push(format!("\t{}", cfg));
        }
        traits.push(format!(
            "\tpub use super::{}::{};",
            module_name, analysis.trait_name
        ));
    }

    if !analysis.builder_properties.is_empty() {
        contents.extend_from_slice(&cfgs);
        contents.push(format!(
            "pub use self::{}::{}Builder;",
            module_name, analysis.name
        ));
    }
}
<commit_msg>codegen: remove the double quote<commit_after>use super::{child_properties, function, general, properties, signal, trait_impls};
use crate::{
    analysis::special_functions::Type,
    analysis::{
        self,
        rust_type::{rust_type, rust_type_full},
    },
    case::CaseExt,
    codegen::general::{version_condition_no_doc, version_condition_string},
    env::Env,
    library, nameutil,
    traits::IntoString,
};
use std::io::{Result, Write};

pub fn generate(
    w: &mut dyn Write,
    env: &Env,
    analysis: &analysis::object::Info,
    generate_display_trait: bool,
) -> Result<()> {
    general::start_comments(w, &env.config)?;
    general::uses(w, env, &analysis.imports, analysis.version)?;

    general::define_object_type(
        w,
        env,
        &analysis.name,
        &analysis.c_type,
        analysis.c_class_type.as_deref(),
        &analysis.get_type,
        analysis.is_interface,
        &analysis.supertypes,
    )?;

    if need_generate_inherent(analysis) {
        writeln!(w)?;
        write!(w, "impl {} {{", analysis.name)?;
        for func_analysis in &analysis.constructors() {
            function::generate(
                w,
                env,
                func_analysis,
                Some(&analysis.specials),
                analysis.version,
                false,
                false,
                1,
            )?;
        }

        if !need_generate_trait(analysis) {
            for func_analysis in &analysis.methods() {
                function::generate(
                    w,
                    env,
                    func_analysis,
                    Some(&analysis.specials),
                    analysis.version,
                    false,
                    false,
                    1,
                )?;
            }

            for property in &analysis.properties {
                properties::generate(w, env, property, false, false, 1)?;
            }

            for child_property in &analysis.child_properties {
                child_properties::generate(w, env, child_property, false, false, 1)?;
            }
        }

        for func_analysis in &analysis.functions() {
            function::generate(
                w,
                env,
                func_analysis,
                Some(&analysis.specials),
                analysis.version,
                false,
                false,
                1,
            )?;
        }

        if !need_generate_trait(analysis) {
            for signal_analysis in analysis
                .signals
                .iter()
                .chain(analysis.notify_signals.iter())
            {
                signal::generate(w, env, signal_analysis, false, false, 1)?;
            }
        }

        writeln!(w, "}}")?;

        general::declare_default_from_new(w, env, &analysis.name, &analysis.functions)?;
    }

    trait_impls::generate(
        w,
        env,
        &analysis.name,
        &analysis.functions,
        &analysis.specials,
        if need_generate_trait(analysis) {
            Some(&analysis.trait_name)
        } else {
            None
        },
        analysis.version,
    )?;

    if !analysis.builder_properties.is_empty() {
        writeln!(w)?;
        generate_builder(w, env, analysis)?;
    }

    if analysis.concurrency != library::Concurrency::None {
        writeln!(w)?;
    }

    match analysis.concurrency {
        library::Concurrency::Send | library::Concurrency::SendSync => {
            writeln!(w, "unsafe impl Send for {} {{}}", analysis.name)?;
        }
        library::Concurrency::SendUnique => {
            if env.namespaces.is_glib_crate {
                writeln!(w, "unsafe impl ::SendUnique for {} {{", analysis.name)?;
            } else {
                writeln!(w, "unsafe impl glib::SendUnique for {} {{", analysis.name)?;
            }

            writeln!(w, "    fn is_unique(&self) -> bool {{")?;
            writeln!(w, "        self.ref_count() == 1")?;
            writeln!(w, "    }}")?;

            writeln!(w, "}}")?;
        }
        _ => (),
    }

    if let library::Concurrency::SendSync = analysis.concurrency {
        writeln!(w, "unsafe impl Sync for {} {{}}", analysis.name)?;
    }

    if !analysis.final_type {
        writeln!(w)?;
        writeln!(
            w,
            "pub const NONE_{}: Option<&{}> = None;",
            analysis.name.to_snake().to_uppercase(),
            analysis.name
        )?;
    }

    if need_generate_trait(analysis) {
        writeln!(w)?;
        generate_trait(w, env, analysis)?;
    }

    if generate_display_trait && !analysis.specials.has_trait(Type::Display) {
        writeln!(w, "\nimpl fmt::Display for {} {{", analysis.name,)?;
        // Generate Display trait implementation.
        writeln!(
            w,
            "\tfn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {{\n\
             \t\tf.write_str(\"{}\")\n\
             \t}}\n\
             }}",
            analysis.name
        )?;
    }

    Ok(())
}

// TODO: instead create a Vec<> inside the Builder instead of Options.
fn generate_builder(w: &mut dyn Write, env: &Env, analysis: &analysis::object::Info) -> Result<()> {
    let mut methods = vec![];
    let mut properties = vec![];
    writeln!(w, "#[derive(Clone, Default)]")?;
    writeln!(w, "pub struct {}Builder {{", analysis.name)?;
    for property in &analysis.builder_properties {
        match rust_type(env, property.typ) {
            Ok(type_string) => {
                let type_string = match type_string.as_str() {
                    s if nameutil::is_gstring(s) => "String",
                    "Vec<GString>" | "Vec<glib::GString>" | "Vec<crate::GString>" => "Vec<String>",
                    typ => typ,
                };
                let mut param_type = rust_type_full(
                    env,
                    property.typ,
                    library::Nullable(false),
                    property.set_in_ref_mode,
                    library::ParameterScope::None,
                    library::Concurrency::None,
                )
                .into_string();
                let (param_type_override, bounds, conversion) = match &param_type[..] {
                    "&str" => (None, String::new(), ".to_string()"),
                    "&[&str]" => (Some("Vec<String>".to_string()), String::new(), ""),
                    _ if !property.bounds.is_empty() => {
                        let (bounds, _) = function::bounds(&property.bounds, &[], false, false);
                        let alias = property
                            .bounds
                            .get_parameter_alias_info(&property.name)
                            .map(|(alias, _)| format!("&{}", alias));
                        (alias, bounds, ".clone().upcast()")
                    }
                    typ if typ.starts_with('&') => (None, String::new(), ".clone()"),
                    _ => (None, String::new(), ""),
                };
                if let Some(param_type_override) = param_type_override {
                    param_type = param_type_override.to_string();
                }
                let name = nameutil::mangle_keywords(nameutil::signal_to_snake(&property.name));
                let version_condition_string =
                    version_condition_string(env, property.version, false, 1);
                if let Some(ref version_condition_string) = version_condition_string {
                    writeln!(w, "{}", version_condition_string)?;
                }
                writeln!(w, "    {}: Option<{}>,", name, type_string)?;
                let prefix = version_condition_string
                    .map(|version| format!("{}\n", version))
                    .unwrap_or_default();
                methods.push(format!(
                    "\n{prefix}    pub fn {name}{bounds}(mut self, {name}: {param_type}) -> Self {{
        self.{name} = Some({name}{conversion});
        self
    }}",
                    prefix = prefix,
                    param_type = param_type,
                    name = name,
                    conversion = conversion,
                    bounds = bounds
                ));
                properties.push(property);
            }
            Err(_) => writeln!(w, "    //{}: /*Unknown type*/,", property.name)?,
        }
    }
    writeln!(
        w,
        "}}

impl {}Builder {{
    pub fn new() -> Self {{
        Self::default()
    }}
",
        analysis.name
    )?;

    writeln!(
        w,
        "
    pub fn build(self) -> {} {{
        let mut properties: Vec<(&str, &dyn ToValue)> = vec![];",
        analysis.name
    )?;
    for property in &properties {
        let name = nameutil::mangle_keywords(nameutil::signal_to_snake(&property.name));
        version_condition_no_doc(w, env, property.version, false, 2)?;
        writeln!(
            w,
            "\
            if let Some(ref {field}) = self.{field} {{
                properties.push((\"{name}\", {field}));
            }}",
            name = property.name,
            field = name
        )?;
    }
    let glib_crate_name = if env.namespaces.is_glib_crate {
        "crate"
    } else {
        "glib"
    };

    // The split allows us to not have clippy::let_and_return lint disabled
    if let Some(code) = analysis.builder_postprocess.as_ref() {
        writeln!(
            w,
            r#"        let ret = {}::Object::new::<{}>(&properties)
                .expect("Failed to create an instance of {}");"#,
            glib_crate_name, analysis.name, analysis.name,
        )?;
        writeln!(w, "        {{\n            {}\n        }}", code)?;
        writeln!(w, "    ret\n    }}")?;
    } else {
        writeln!(
            w,
            r#"        {}::Object::new::<{}>(&properties)
                .expect("Failed to create an instance of {}")"#,
            glib_crate_name, analysis.name, analysis.name,
        )?;
        writeln!(w, "\n    }}")?;
    }

    for method in methods {
        writeln!(w, "{}", method)?;
    }
    writeln!(w, "}}")
}

fn generate_trait(w: &mut dyn Write, env: &Env, analysis: &analysis::object::Info) -> Result<()> {
    write!(w, "pub trait {}: 'static {{", analysis.trait_name)?;

    for func_analysis in &analysis.methods() {
        function::generate(
            w,
            env,
            func_analysis,
            Some(&analysis.specials),
            analysis.version,
            true,
            true,
            1,
        )?;
    }
    for property in &analysis.properties {
        properties::generate(w, env, property, true, true, 1)?;
    }
    for child_property in &analysis.child_properties {
        child_properties::generate(w, env, child_property, true, true, 1)?;
    }
    for signal_analysis in analysis
        .signals
        .iter()
        .chain(analysis.notify_signals.iter())
    {
        signal::generate(w, env, signal_analysis, true, true, 1)?;
    }
    writeln!(w, "}}")?;

    writeln!(w)?;
    write!(
        w,
        "impl<O: IsA<{}>> {} for O {{",
        analysis.name, analysis.trait_name,
    )?;

    for func_analysis in &analysis.methods() {
        function::generate(
            w,
            env,
            func_analysis,
            Some(&analysis.specials),
            analysis.version,
            true,
            false,
            1,
        )?;
    }
    for property in &analysis.properties {
        properties::generate(w, env, property, true, false, 1)?;
    }
    for child_property in &analysis.child_properties {
        child_properties::generate(w, env, child_property, true, false, 1)?;
    }
    for signal_analysis in analysis
        .signals
        .iter()
        .chain(analysis.notify_signals.iter())
    {
        signal::generate(w, env, signal_analysis, true, false, 1)?;
    }
    writeln!(w, "}}")?;

    Ok(())
}

fn need_generate_inherent(analysis: &analysis::object::Info) -> bool {
    analysis.has_constructors || analysis.has_functions || !need_generate_trait(analysis)
}

fn need_generate_trait(analysis: &analysis::object::Info) -> bool {
    analysis.generate_trait
}

pub fn generate_reexports(
    env: &Env,
    analysis: &analysis::object::Info,
    module_name: &str,
    contents: &mut Vec<String>,
    traits: &mut Vec<String>,
) {
    let mut cfgs: Vec<String> = Vec::new();
    if let Some(cfg) = general::cfg_condition_string(&analysis.cfg_condition, false, 0) {
        cfgs.push(cfg);
    }
    if let Some(cfg) = general::version_condition_string(env, analysis.version, false, 0) {
        cfgs.push(cfg);
    }
    if let Some(cfg) = general::cfg_deprecated_string(env, analysis.deprecated_version, false, 0) {
        cfgs.push(cfg);
    }

    contents.push("".to_owned());
    contents.extend_from_slice(&cfgs);
    contents.push(format!("mod {};", module_name));
    contents.extend_from_slice(&cfgs);

    let none_type = if !analysis.final_type {
        format!(", NONE_{}", analysis.name.to_snake().to_uppercase())
    } else {
        String::new()
    };

    contents.push(format!(
        "pub use self::{}::{{{}{}}};",
        module_name, analysis.name, none_type
    ));
    if need_generate_trait(analysis) {
        for cfg in &cfgs {
            traits.push(format!("\t{}", cfg));
        }
        traits.push(format!(
            "\tpub use super::{}::{};",
            module_name, analysis.trait_name
        ));
    }

    if !analysis.builder_properties.is_empty() {
        contents.extend_from_slice(&cfgs);
        contents.push(format!(
            "pub use self::{}::{}Builder;",
            module_name, analysis.name
        ));
    }
}
<|endoftext|>


<commit_before>use std::fs;
use std::path::Path;
use util;

pub fn versions() {
    let groonga_versioned_dir = util::obtain_groonga_versioned_path();
    let paths = fs::read_dir(&Path::new(&groonga_versioned_dir)).unwrap();

    let names = paths.filter_map(|entry| {
            entry.ok().and_then(|e| {
                e.path()
                    .file_name()
                    .and_then(|n| n.to_str().map(|s| String::from(s)))
            })
        })
        .collect::<Vec<String>>();

    println!("Installed Groonga:");
    println!("\tsystem");
    for entry in names {
        println!("\t{}", entry);
    }
}
<commit_msg>command common: Define MaybeProxyUrl type and into_response trait<commit_after>use std::fs;
use std::path::Path;

use kuchiki::traits::*;
use hyper::{Client, Url};
use hyper::client::Response;
use hyper::Result as HyperResult;
use util;

pub fn versions() {
    let groonga_versioned_dir = util::obtain_groonga_versioned_path();
    let paths = fs::read_dir(&Path::new(&groonga_versioned_dir)).unwrap();

    let names = paths.filter_map(|entry| {
            entry.ok().and_then(|e| {
                e.path()
                    .file_name()
                    .and_then(|n| n.to_str().map(|s| String::from(s)))
            })
        })
        .collect::<Vec<String>>();

    println!("Installed Groonga:");
    println!("\tsystem");
    for entry in names {
        println!("\t{}", entry);
    }
}

pub struct MaybeProxyUrl {
    pub url: Url
}

impl<'a> IntoResponse for MaybeProxyUrl {
    fn into_response(self) -> HyperResult<Response> {
        extern crate env_proxy;
        let maybe_proxy = env_proxy::for_url(&self.url);

        let client = match maybe_proxy {
            None => Client::new(),
            Some(host_port) => Client::with_http_proxy(host_port.0, host_port.1),
        };
        client.get(self.url).send()
    }
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate glium;

#[macro_use]
extern crate lazy_static;

extern crate image;
extern crate gltile;

fn main() {
    use glium::{DisplayBuild, Surface};

    let screen_size = gltile::Size {
        width: 1536, // 96
        height: 1024, // 64
    };

    let display = glium::glutin::WindowBuilder::new()
        .with_dimensions(screen_size.width as u32, screen_size.height as u32)
        .build_glium()
        .unwrap();

    let vertex = gltile::read_file("shaders/vertex.glsl")
        .expect("could not find shaders/vertex.glsl");
    let fragment = gltile::read_file("shaders/fragment.glsl")
        .expect("could not find shaders/fragment.glsl");
    let program = glium::Program::from_source(&display, &vertex, &fragment, None).unwrap();

    let texture = {
        let tileset = gltile::read_png_to_texture(&include_bytes!("../assets/tileset.png")[..]);
        glium::texture::Texture2d::new(&display, tileset).unwrap()
    };

    let tileset = texture.sampled().magnify_filter(glium::uniforms::MagnifySamplerFilter::Nearest);

    // TODO hardcoded
    let size = gltile::Size::new((screen_size.width as f32 / 16.0) as i32,
                                 (screen_size.height as f32 / 16.0) as i32);

    let mat4_id = gltile::mat4_id();
    let ortho_projection = gltile::ortho_projection(screen_size);

    let mut camera = {
        let halve_pixels = (display.get_window().unwrap().hidpi_factor() - 2.0).abs() < 0.1;
        gltile::Camera::new(screen_size, gltile::Loc { x: 0, y: 63 }, 16, halve_pixels)
    };

    let indices = {
        use glium::index::PrimitiveType;

        let indices = gltile::indices((size.width * size.height) as usize);
        glium::IndexBuffer::new(&display, PrimitiveType::TrianglesList, &indices).unwrap()
    };

    let cam_uniforms = uniform! {
        mvp: gltile::model_view_projection(mat4_id, camera.as_mat(), ortho_projection),
        tileset: tileset
    };

    let vb = {
        let mut vb = gltile::VertexBuffer::new(size);

        let tile = {
            let mut tile = gltile::Tile::new();
            tile.fg = *gltile::colors::YELLOW;
            tile.pix = gltile::Pix::Dood;
            tile
        };

        vb.set(gltile::WindowLoc { x: 5, y: 5 }, tile);

        // TODO hide this as an implementation detail
        glium::VertexBuffer::new(&display, &vb.data()).unwrap()
    };

    // let mut console = gltile::Console::new(size);

    loop {
        let mut target = display.draw();
        target.clear_color(0.0, 0.0, 0.0, 1.0);
        target.draw(&vb, &indices, &program, &cam_uniforms, &Default::default()).unwrap();
        target.finish().unwrap();

        for ev in display.poll_events() {
            match ev {
                glium::glutin::Event::Closed => return,
                _ => (),
            }
        }
    }
}
<commit_msg>chore(examples): clean up variable scoping<commit_after>#[macro_use]
extern crate glium;

#[macro_use]
extern crate lazy_static;

extern crate image;
extern crate gltile;

fn main() {
    use glium::{DisplayBuild, Surface};

    let screen_size = gltile::Size {
        width: 1536, // 96
        height: 1024, // 64
    };

    let display = glium::glutin::WindowBuilder::new()
        .with_dimensions(screen_size.width as u32, screen_size.height as u32)
        .build_glium()
        .unwrap();

    let vertex = gltile::read_file("shaders/vertex.glsl")
        .expect("could not find shaders/vertex.glsl");
    let fragment = gltile::read_file("shaders/fragment.glsl")
        .expect("could not find shaders/fragment.glsl");
    let program = glium::Program::from_source(&display, &vertex, &fragment, None).unwrap();

    let texture = {
        let tileset = gltile::read_png_to_texture(&include_bytes!("../assets/tileset.png")[..]);
        glium::texture::Texture2d::new(&display, tileset).unwrap()
    };

    let tileset = texture.sampled().magnify_filter(glium::uniforms::MagnifySamplerFilter::Nearest);

    // TODO hardcoded
    let size = gltile::Size::new((screen_size.width as f32 / 16.0) as i32,
                                 (screen_size.height as f32 / 16.0) as i32);

    let mut camera = {
        let halve_pixels = (display.get_window().unwrap().hidpi_factor() - 2.0).abs() < 0.1;
        gltile::Camera::new(screen_size, gltile::Loc { x: 0, y: 63 }, 16, halve_pixels)
    };

    let indices = {
        use glium::index::PrimitiveType;

        let indices = gltile::indices((size.width * size.height) as usize);
        glium::IndexBuffer::new(&display, PrimitiveType::TrianglesList, &indices).unwrap()
    };

    let cam_uniforms = {
        let mat4_id = gltile::mat4_id();
        let ortho_projection = gltile::ortho_projection(screen_size);

        uniform! {
            mvp: gltile::model_view_projection(mat4_id, camera.as_mat(), ortho_projection),
            tileset: tileset
        }
    };

    let vb = {
        let mut vb = gltile::VertexBuffer::new(size);

        let tile = {
            let mut tile = gltile::Tile::new();
            tile.fg = *gltile::colors::YELLOW;
            tile.pix = gltile::Pix::Dood;
            tile
        };

        vb.set(gltile::WindowLoc { x: 5, y: 5 }, tile);

        // TODO hide this as an implementation detail
        glium::VertexBuffer::new(&display, &vb.data()).unwrap()
    };

    // let mut console = gltile::Console::new(size);

    loop {
        let mut target = display.draw();
        target.clear_color(0.0, 0.0, 0.0, 1.0);
        target.draw(&vb, &indices, &program, &cam_uniforms, &Default::default()).unwrap();
        target.finish().unwrap();

        for ev in display.poll_events() {
            match ev {
                glium::glutin::Event::Closed => return,
                _ => (),
            }
        }
    }
}
<|endoftext|>


<commit_before>extern crate base64;
extern crate crypto;
extern crate u2fhid;
use crypto::digest::Digest;
use crypto::sha2::Sha256;
use std::io;
use std::sync::mpsc::channel;
use u2fhid::U2FManager;

#[macro_use]
extern crate log;
extern crate env_logger;

fn u2f_get_key_handle_from_register_response(register_response: &Vec<u8>) -> io::Result<Vec<u8>> {
    if register_response[0] != 0x05 {
        return Err(io::Error::new(
            io::ErrorKind::InvalidData,
            "Reserved byte not set correctly",
        ));
    }

    let key_handle_len = register_response[66] as usize;
    let mut public_key = register_response.clone();
    let mut key_handle = public_key.split_off(67);
    let _attestation = key_handle.split_off(key_handle_len);

    Ok(key_handle)
}

fn main() {
    env_logger::init().expect("Cannot start logger");

    println!("Asking a security key to register now...");
    let challenge_str =
        format!("{}{}",
        r#"{"challenge": "1vQ9mxionq0ngCnjD-wTsv1zUSrGRtFqG2xP09SbZ70","#,
        r#" "version": "U2F_V2", "appId": "http://demo.yubico.com"}"#);
    let mut challenge = Sha256::new();
    challenge.input_str(&challenge_str);
    let mut chall_bytes: Vec<u8> = vec![0; challenge.output_bytes()];
    challenge.result(&mut chall_bytes);

    let mut application = Sha256::new();
    application.input_str("http://demo.yubico.com");
    let mut app_bytes: Vec<u8> = vec![0; application.output_bytes()];
    application.result(&mut app_bytes);

    let manager = U2FManager::new().unwrap();

    let (tx, rx) = channel();
    manager
        .register(15, chall_bytes.clone(), app_bytes.clone(), move |rv| {
            tx.send(rv.unwrap()).unwrap();
        })
        .unwrap();

    let register_data = rx.recv().unwrap();
    println!("Register result: {}", base64::encode(&register_data));
    println!("Asking a security key to sign now, with the data from the register...");
    let key_handle = u2f_get_key_handle_from_register_response(&register_data).unwrap();

    let (tx, rx) = channel();
    manager
        .sign(15, chall_bytes, app_bytes, vec![key_handle], move |rv| {
            tx.send(rv.unwrap()).unwrap();
        })
        .unwrap();

    let (_, sign_data) = rx.recv().unwrap();
    println!("Sign result: {}", base64::encode(&sign_data));
    println!("Done.");
}
<commit_msg>Give examples/main timeouts in milliseconds<commit_after>extern crate base64;
extern crate crypto;
extern crate u2fhid;
use crypto::digest::Digest;
use crypto::sha2::Sha256;
use std::io;
use std::sync::mpsc::channel;
use u2fhid::U2FManager;

#[macro_use]
extern crate log;
extern crate env_logger;

fn u2f_get_key_handle_from_register_response(register_response: &Vec<u8>) -> io::Result<Vec<u8>> {
    if register_response[0] != 0x05 {
        return Err(io::Error::new(
            io::ErrorKind::InvalidData,
            "Reserved byte not set correctly",
        ));
    }

    let key_handle_len = register_response[66] as usize;
    let mut public_key = register_response.clone();
    let mut key_handle = public_key.split_off(67);
    let _attestation = key_handle.split_off(key_handle_len);

    Ok(key_handle)
}

fn main() {
    env_logger::init().expect("Cannot start logger");

    println!("Asking a security key to register now...");
    let challenge_str =
        format!("{}{}",
        r#"{"challenge": "1vQ9mxionq0ngCnjD-wTsv1zUSrGRtFqG2xP09SbZ70","#,
        r#" "version": "U2F_V2", "appId": "http://demo.yubico.com"}"#);
    let mut challenge = Sha256::new();
    challenge.input_str(&challenge_str);
    let mut chall_bytes: Vec<u8> = vec![0; challenge.output_bytes()];
    challenge.result(&mut chall_bytes);

    let mut application = Sha256::new();
    application.input_str("http://demo.yubico.com");
    let mut app_bytes: Vec<u8> = vec![0; application.output_bytes()];
    application.result(&mut app_bytes);

    let manager = U2FManager::new().unwrap();

    let (tx, rx) = channel();
    manager
        .register(15000, chall_bytes.clone(), app_bytes.clone(), move |rv| {
            tx.send(rv.unwrap()).unwrap();
        })
        .unwrap();

    let register_data = rx.recv().unwrap();
    println!("Register result: {}", base64::encode(&register_data));
    println!("Asking a security key to sign now, with the data from the register...");
    let key_handle = u2f_get_key_handle_from_register_response(&register_data).unwrap();

    let (tx, rx) = channel();
    manager
        .sign(15000, chall_bytes, app_bytes, vec![key_handle], move |rv| {
            tx.send(rv.unwrap()).unwrap();
        })
        .unwrap();

    let (_, sign_data) = rx.recv().unwrap();
    println!("Sign result: {}", base64::encode(&sign_data));
    println!("Done.");
}
<|endoftext|>


<commit_before>extern crate turtle;

use turtle::Turtle;

fn main() {
    let mut turtle = Turtle::new();

    turtle.set_speed(10);
    turtle.set_fill_color("black");

    turtle.begin_fill();
    turtle.pen_up();
    turtle.forward(150.0);
    turtle.pen_down();

    gear(&mut turtle);
    turtle.end_fill();

    turtle.pen_up();
    turtle.forward(45.0);
    turtle.left(90.0);
    turtle.pen_down();

    inner_gear(&mut turtle);

    turtle.hide();
}

fn gear(turtle: &mut Turtle) {
    // Much of this code was figured out by guessing and checking
    let teeth = 32.0;
    let tooth_size = 20.0;
    let angle = 360.0 / teeth;
    turtle.right(180.0 - angle * 6.0 / 2.0);
    for _ in 0..teeth as u64 {
        turtle.forward(tooth_size);
        turtle.left(180.0 - angle * 7.0);
        turtle.forward(tooth_size);
        turtle.right(180.0 - angle * 6.0);
    }

    turtle.right(angle * 6.0 / 2.0);
}

fn inner_gear(turtle: &mut Turtle) {
    inner_circle(turtle);
    inner_teeth(turtle);
}

fn inner_circle(turtle: &mut Turtle) {
    turtle.set_fill_color("white");
    turtle.begin_fill();
    for _ in 0..360 {
        turtle.forward(1.5);
        turtle.right(1.0);
    }
    turtle.end_fill();
    turtle.set_fill_color("black");
}

fn inner_teeth(turtle: &mut Turtle) {
    let tooth_size = 40.0;
    turtle.pen_up();
    turtle.left(90.0);
    turtle.forward(10.0);
    turtle.right(90.0);
    turtle.pen_down();

    for _ in 0..5 {
        turtle.pen_up();
        turtle.forward(tooth_size / 2.0);
        turtle.pen_down();

        turtle.begin_fill();
        turtle.right(120.0);
        turtle.forward(tooth_size);
        turtle.right(120.0);
        turtle.forward(tooth_size);
        turtle.right(120.0);
        turtle.end_fill();

        turtle.pen_up();
        turtle.forward(tooth_size / 2.0);
        turtle.right(90.0);
        turtle.forward(5.0);
        turtle.left(90.0);
        turtle.pen_down();

        inner_tooth_circle(turtle);

        turtle.pen_up();
        turtle.left(90.0);
        turtle.forward(5.0);
        turtle.right(90.0);
        for _ in 0..360/5/2 {
            turtle.forward(3.41);
            turtle.right(2.0);
        }
        turtle.pen_down();
    }
}

fn inner_tooth_circle(turtle: &mut Turtle) {
    turtle.set_fill_color("white");
    turtle.begin_fill();
    for _ in 0..360/8 {
        turtle.forward(1.0);
        turtle.right(8.0);
    }
    turtle.end_fill();
    turtle.set_fill_color("black");
}
<commit_msg>Drawing a capital T in the middle of the rust logo to represent this library<commit_after>//! This example draws a crude version of the Rust logo.
//! The version is "crude" because it's all very approximate with plenty of guesswork.
//! If you can come up with a way to do this so that it exactly matches the logo, please
//! do submit it!
//! In any case, this is an excellent example of creatively using fills and some other
//! techniques to create a fairly complex drawing.

extern crate turtle;

use turtle::Turtle;

fn main() {
    let mut turtle = Turtle::new();

    turtle.set_speed(10);
    turtle.set_fill_color("black");

    turtle.begin_fill();
    turtle.pen_up();
    turtle.forward(130.0);
    turtle.pen_down();

    gear(&mut turtle);
    turtle.end_fill();

    turtle.pen_up();
    turtle.forward(45.0);
    turtle.left(90.0);
    turtle.pen_down();

    inner_gear(&mut turtle);

    letter(&mut turtle);

    turtle.hide();
}

fn gear(turtle: &mut Turtle) {
    // Much of this code was figured out by guessing and checking
    let teeth = 32.0;
    let tooth_size = 20.0;
    let angle = 360.0 / teeth;
    turtle.right(180.0 - angle * 6.0 / 2.0);
    for _ in 0..teeth as u64 {
        turtle.forward(tooth_size);
        turtle.left(180.0 - angle * 7.0);
        turtle.forward(tooth_size);
        turtle.right(180.0 - angle * 6.0);
    }

    turtle.right(angle * 6.0 / 2.0);
}

fn inner_gear(turtle: &mut Turtle) {
    inner_circle(turtle);
    inner_teeth(turtle);
}

fn inner_circle(turtle: &mut Turtle) {
    turtle.set_fill_color("white");
    turtle.begin_fill();
    for _ in 0..360 {
        turtle.forward(1.5);
        turtle.right(1.0);
    }
    turtle.end_fill();
    turtle.set_fill_color("black");
}

fn inner_teeth(turtle: &mut Turtle) {
    let tooth_size = 40.0;
    turtle.pen_up();
    turtle.left(90.0);
    turtle.forward(10.0);
    turtle.right(90.0);
    turtle.pen_down();

    for _ in 0..5 {
        turtle.pen_up();
        turtle.forward(tooth_size / 2.0);
        turtle.pen_down();

        turtle.begin_fill();
        turtle.right(120.0);
        turtle.forward(tooth_size);
        turtle.right(120.0);
        turtle.forward(tooth_size);
        turtle.right(120.0);
        turtle.end_fill();

        turtle.pen_up();
        turtle.forward(tooth_size / 2.0);
        turtle.right(90.0);
        turtle.forward(5.0);
        turtle.left(90.0);
        turtle.pen_down();

        inner_tooth_circle(turtle);

        turtle.pen_up();
        turtle.left(90.0);
        turtle.forward(5.0);
        turtle.right(90.0);
        for _ in 0..360/5/2 {
            turtle.forward(3.41);
            turtle.right(2.0);
        }
        turtle.pen_down();
    }
}

fn inner_tooth_circle(turtle: &mut Turtle) {
    turtle.set_fill_color("white");
    turtle.begin_fill();
    for _ in 0..360/8 {
        turtle.forward(1.0);
        turtle.right(8.0);
    }
    turtle.end_fill();
    turtle.set_fill_color("black");
}

fn letter(turtle: &mut Turtle) {
    turtle.pen_up();
    turtle.right(180.0);
    turtle.pen_down();
    for _ in 0..(360/5 - 7)/2 {
        turtle.forward(3.41);
        turtle.left(2.0);
    }
    // Trick for making the turtle face to the right
    let heading = turtle.heading();
    turtle.right(heading);

    turtle.set_pen_size(10.0);
    turtle.forward(180.0);
    turtle.backward(90.0);

    turtle.right(90.0);
    turtle.forward(100.0);
}
<|endoftext|>


<commit_before>extern crate piston;
extern crate shader_version;
extern crate sdl2;
extern crate sdl2_window;
extern crate gfx;
extern crate camera_controllers;
extern crate vecmath;
extern crate env_logger;
extern crate gfx_debug_draw;
extern crate gfx_device_gl;
extern crate piston_window;

use gfx_debug_draw::DebugRenderer;

use std::cell::RefCell;
use std::rc::Rc;

use piston::window::WindowSettings;

use piston::event::{
    RenderEvent,
    ResizeEvent,
};

use vecmath::mat4_id;

use sdl2_window::Sdl2Window;

use camera_controllers::{
    OrbitZoomCamera,
    OrbitZoomCameraSettings,
    CameraPerspective,
    model_view_projection
};

use gfx::traits::*;

fn main() {

    env_logger::init().unwrap();

    let (win_width, win_height) = (640, 480);

    let window = Rc::new(RefCell::new(Sdl2Window::new(
        shader_version::OpenGL::_3_2,
        WindowSettings::new(
            "Debug Render Test".to_string(),
            piston::window::Size { width: 640, height: 480 },
        ).exit_on_esc(true)
    )));

    let piston_window = piston_window::PistonWindow::new(window, piston_window::empty_app());

    let mut debug_renderer = DebugRenderer::from_canvas(
        &mut piston_window.canvas.borrow_mut(),
        [win_width as u32, win_height as u32],
        64,
        None,
        None,
    ).ok().unwrap();

    let model = mat4_id();
    let mut projection = CameraPerspective {
        fov: 90.0f32,
        near_clip: 0.1,
        far_clip: 1000.0,
        aspect_ratio: (win_width as f32) / (win_height as f32)
    }.projection();

    let mut orbit_zoom_camera: OrbitZoomCamera<f32> = OrbitZoomCamera::new(
        [0.0, 0.0, 0.0],
        OrbitZoomCameraSettings::default()
    );

    // Start event loop

    for e in piston_window {

        e.resize(|width, height| {
            debug_renderer.resize(width, height);

            // Update projection matrix
            projection = CameraPerspective {
                fov: 90.0f32,
                near_clip: 0.1,
                far_clip: 1000.0,
                aspect_ratio: (width as f32) / (height as f32)
            }.projection();
        });

        orbit_zoom_camera.event(&e);

        e.draw_3d(|canvas| {

            let args = e.render_args().unwrap();

            canvas.renderer.clear(
                gfx::ClearData {
                    color: [0.3, 0.3, 0.3, 1.0],
                    depth: 1.0,
                    stencil: 0,
                },
                gfx::COLOR | gfx::DEPTH,
                &canvas.output
            );

            let camera_projection = model_view_projection(
                model,
                orbit_zoom_camera.camera(args.ext_dt).orthogonal(),
                projection
            );

            // Draw axes
            debug_renderer.draw_line([0.0, 0.0, 0.0], [5.0, 0.0, 0.0], [1.0, 0.0, 0.0, 1.0]);
            debug_renderer.draw_line([0.0, 0.0, 0.0], [0.0, 5.0, 0.0], [0.0, 1.0, 0.0, 1.0]);
            debug_renderer.draw_line([0.0, 0.0, 0.0], [0.0, 0.0, 5.0], [0.0, 0.0, 1.0, 1.0]);

            debug_renderer.draw_text_at_position(
                "X",
                [6.0, 0.0, 0.0],
                [1.0, 0.0, 0.0, 1.0],
            );

            debug_renderer.draw_text_at_position(
                "Y",
                [0.0, 6.0, 0.0],
                [0.0, 1.0, 0.0, 1.0],
            );

            debug_renderer.draw_text_at_position(
                "Z",
                [0.0, 0.0, 6.0],
                [0.0, 0.0, 1.0, 1.0],
            );

            debug_renderer.render_canvas(canvas, camera_projection);
            canvas.device.submit(canvas.renderer.as_buffer());
            canvas.renderer.reset();
        });
    }
}
<commit_msg>Removed stuff now handled by PistonWindow<commit_after>extern crate piston;
extern crate shader_version;
extern crate sdl2;
extern crate sdl2_window;
extern crate gfx;
extern crate camera_controllers;
extern crate vecmath;
extern crate env_logger;
extern crate gfx_debug_draw;
extern crate gfx_device_gl;
extern crate piston_window;

use gfx_debug_draw::DebugRenderer;

use std::cell::RefCell;
use std::rc::Rc;

use piston::window::WindowSettings;

use piston::event::{
    RenderEvent,
    ResizeEvent,
};

use vecmath::mat4_id;

use sdl2_window::Sdl2Window;

use camera_controllers::{
    OrbitZoomCamera,
    OrbitZoomCameraSettings,
    CameraPerspective,
    model_view_projection
};

fn main() {

    env_logger::init().unwrap();

    let (win_width, win_height) = (640, 480);

    let window = Rc::new(RefCell::new(Sdl2Window::new(
        shader_version::OpenGL::_3_2,
        WindowSettings::new(
            "Debug Render Test".to_string(),
            piston::window::Size { width: 640, height: 480 },
        ).exit_on_esc(true)
    )));

    let piston_window = piston_window::PistonWindow::new(window, piston_window::empty_app());

    let mut debug_renderer = DebugRenderer::from_canvas(
        &mut piston_window.canvas.borrow_mut(),
        [win_width as u32, win_height as u32],
        64,
        None,
        None,
    ).ok().unwrap();

    let model = mat4_id();
    let mut projection = CameraPerspective {
        fov: 90.0f32,
        near_clip: 0.1,
        far_clip: 1000.0,
        aspect_ratio: (win_width as f32) / (win_height as f32)
    }.projection();

    let mut orbit_zoom_camera: OrbitZoomCamera<f32> = OrbitZoomCamera::new(
        [0.0, 0.0, 0.0],
        OrbitZoomCameraSettings::default()
    );

    // Start event loop

    for e in piston_window {

        e.resize(|width, height| {
            debug_renderer.resize(width, height);

            // Update projection matrix
            projection = CameraPerspective {
                fov: 90.0f32,
                near_clip: 0.1,
                far_clip: 1000.0,
                aspect_ratio: (width as f32) / (height as f32)
            }.projection();
        });

        orbit_zoom_camera.event(&e);

        e.draw_3d(|canvas| {

            let args = e.render_args().unwrap();

            canvas.renderer.clear(
                gfx::ClearData {
                    color: [0.3, 0.3, 0.3, 1.0],
                    depth: 1.0,
                    stencil: 0,
                },
                gfx::COLOR | gfx::DEPTH,
                &canvas.output
            );

            let camera_projection = model_view_projection(
                model,
                orbit_zoom_camera.camera(args.ext_dt).orthogonal(),
                projection
            );

            // Draw axes
            debug_renderer.draw_line([0.0, 0.0, 0.0], [5.0, 0.0, 0.0], [1.0, 0.0, 0.0, 1.0]);
            debug_renderer.draw_line([0.0, 0.0, 0.0], [0.0, 5.0, 0.0], [0.0, 1.0, 0.0, 1.0]);
            debug_renderer.draw_line([0.0, 0.0, 0.0], [0.0, 0.0, 5.0], [0.0, 0.0, 1.0, 1.0]);

            debug_renderer.draw_text_at_position(
                "X",
                [6.0, 0.0, 0.0],
                [1.0, 0.0, 0.0, 1.0],
            );

            debug_renderer.draw_text_at_position(
                "Y",
                [0.0, 6.0, 0.0],
                [0.0, 1.0, 0.0, 1.0],
            );

            debug_renderer.draw_text_at_position(
                "Z",
                [0.0, 0.0, 6.0],
                [0.0, 0.0, 1.0, 1.0],
            );

            debug_renderer.render_canvas(canvas, camera_projection);
        });
    }
}
<|endoftext|>


<commit_before>use serde_json::from_str;
use std::collections::HashMap;
use std::io::Read;
use std::fs::File;
use std::sync::mpsc;
use std::thread;
use std::result::Result;
use std::time::Duration;
use std::sync::Arc;

use {Message, Response};
use config::ContextConfig;
use condition::Condition;
use context::ContextMap;
use dispatcher::request::Request;
use dispatcher::reactor::RequestReactor;
use dispatcher::{ResponseSender, ResponseHandle};
use dispatcher::demux::Demultiplexer;
use dispatcher::handlers;
pub use self::error::Error;
use reactor::{Event, Reactor, EventHandler};
use timer::Timer;

use self::exit_handler::ExitHandler;

const TIMER_STEP_MS: u64 = 100;

pub mod error;
mod exit_handler;
#[cfg(test)]
mod test;

pub struct Correlator {
    dispatcher_input_channel: mpsc::Sender<Request>,
    dispatcher_output_channel: mpsc::Receiver<Response>,
    dispatcher_thread_handle: thread::JoinHandle<()>,
    handlers: HashMap<ResponseHandle, Box<EventHandler<Response, mpsc::Sender<Request>>>>,
}

impl Correlator {
    pub fn from_path(path: &str) -> Result<Correlator, Error> {
        let mut file = try!(File::open(path));
        let mut buffer = String::new();
        try!(file.read_to_string(&mut buffer));
        let contexts = try!(from_str::<Vec<ContextConfig>>(&buffer));
        trace!("Correlator: loading contexts from file; len={}",
               contexts.len());
        Ok(Correlator::new(contexts))
    }

    pub fn new(contexts: Vec<ContextConfig>) -> Correlator {
        let context_map = ContextMap::from_configs(contexts);
        let (dispatcher_input_channel, rx) = mpsc::channel();
        let (dispatcher_output_channel_tx, dispatcher_output_channel_rx) = mpsc::channel();
        let _ = Timer::from_chan(Duration::from_millis(TIMER_STEP_MS),
                                 dispatcher_input_channel.clone());

        let handle = thread::spawn(move || {
            let exit_condition = Condition::new(false);
            let dmux = Demultiplexer::new(rx, exit_condition.clone());
            let response_sender = Box::new(ResponseSender::new(dispatcher_output_channel_tx));

            let exit_handler = Box::new(handlers::exit::ExitEventHandler::new(exit_condition));
            let timer_event_handler = Box::new(handlers::timer::TimerEventHandler::new());
            let message_event_handler = Box::new(handlers::message::MessageEventHandler::new());

            let mut reactor = RequestReactor::new(dmux, context_map, response_sender);
            reactor.register_handler(exit_handler);
            reactor.register_handler(timer_event_handler);
            reactor.register_handler(message_event_handler);
            reactor.handle_events();
            trace!("Correlator: dispatcher thread exited");
        });

        Correlator {
            dispatcher_input_channel: dispatcher_input_channel,
            dispatcher_output_channel: dispatcher_output_channel_rx,
            dispatcher_thread_handle: handle,
            handlers: HashMap::new(),
        }
    }

    pub fn register_handler(&mut self,
                            handler: Box<EventHandler<Response, mpsc::Sender<Request>>>) {
        self.handlers.insert(handler.handle(), handler);
    }

    pub fn push_message(&mut self, message: Message) -> Result<(), mpsc::SendError<Request>> {
        self.handle_events();
        self.dispatcher_input_channel.send(Request::Message(Arc::new(message)))
    }

    fn handle_event(&mut self, event: Response) {
        if let Some(handler) = self.handlers.get_mut(&event.handle()) {
            handler.handle_event(event, &mut self.dispatcher_input_channel);
        } else {
            trace!("no event handler found for handling a Response");
        }
    }

    pub fn handle_events(&mut self) {
        for i in self.dispatcher_output_channel.try_recv() {
            self.handle_event(i);
        }
    }

    pub fn stop(mut self) -> thread::Result<()> {
        self.handle_events();
        self.stop_dispatcher();
        self.dispatcher_thread_handle.join()
    }

    fn stop_dispatcher(&mut self) {
        let exit_condition = Condition::new(false);
        let exit_handler = Box::new(ExitHandler::new(exit_condition.clone()));
        self.register_handler(exit_handler);
        let _ = self.dispatcher_input_channel.send(Request::Exit);
        while !exit_condition.is_active() {
            if let Ok(event) = self.dispatcher_output_channel.recv() {
                self.handle_event(event);
            }
        }
    }
}
<commit_msg>correlator: use the handler types<commit_after>use serde_json::from_str;
use std::collections::HashMap;
use std::io::Read;
use std::fs::File;
use std::sync::mpsc;
use std::thread;
use std::result::Result;
use std::time::Duration;
use std::sync::Arc;

use {Message, Response};
use config::ContextConfig;
use condition::Condition;
use context::ContextMap;
use dispatcher::request::Request;
use dispatcher::reactor::RequestReactor;
use dispatcher::{ResponseSender, ResponseHandle};
use dispatcher::demux::Demultiplexer;
use dispatcher::handlers::exit::ExitEventHandler;
use dispatcher::handlers::timer::TimerEventHandler;
use dispatcher::handlers::message::MessageEventHandler;
pub use self::error::Error;
use reactor::{Event, Reactor, EventHandler};
use timer::Timer;

use self::exit_handler::ExitHandler;

const TIMER_STEP_MS: u64 = 100;

pub mod error;
mod exit_handler;
#[cfg(test)]
mod test;

pub struct Correlator {
    dispatcher_input_channel: mpsc::Sender<Request>,
    dispatcher_output_channel: mpsc::Receiver<Response>,
    dispatcher_thread_handle: thread::JoinHandle<()>,
    handlers: HashMap<ResponseHandle, Box<EventHandler<Response, mpsc::Sender<Request>>>>,
}

impl Correlator {
    pub fn from_path(path: &str) -> Result<Correlator, Error> {
        let mut file = try!(File::open(path));
        let mut buffer = String::new();
        try!(file.read_to_string(&mut buffer));
        let contexts = try!(from_str::<Vec<ContextConfig>>(&buffer));
        trace!("Correlator: loading contexts from file; len={}",
               contexts.len());
        Ok(Correlator::new(contexts))
    }

    pub fn new(contexts: Vec<ContextConfig>) -> Correlator {
        let context_map = ContextMap::from_configs(contexts);
        let (dispatcher_input_channel, rx) = mpsc::channel();
        let (dispatcher_output_channel_tx, dispatcher_output_channel_rx) = mpsc::channel();
        let _ = Timer::from_chan(Duration::from_millis(TIMER_STEP_MS),
                                 dispatcher_input_channel.clone());

        let handle = thread::spawn(move || {
            let exit_condition = Condition::new(false);
            let dmux = Demultiplexer::new(rx, exit_condition.clone());
            let response_sender = Box::new(ResponseSender::new(dispatcher_output_channel_tx));

            let exit_handler = Box::new(ExitEventHandler::new(exit_condition));
            let timer_event_handler = Box::new(TimerEventHandler::new());
            let message_event_handler = Box::new(MessageEventHandler::new());

            let mut reactor = RequestReactor::new(dmux, context_map, response_sender);
            reactor.register_handler(exit_handler);
            reactor.register_handler(timer_event_handler);
            reactor.register_handler(message_event_handler);
            reactor.handle_events();
            trace!("Correlator: dispatcher thread exited");
        });

        Correlator {
            dispatcher_input_channel: dispatcher_input_channel,
            dispatcher_output_channel: dispatcher_output_channel_rx,
            dispatcher_thread_handle: handle,
            handlers: HashMap::new(),
        }
    }

    pub fn register_handler(&mut self,
                            handler: Box<EventHandler<Response, mpsc::Sender<Request>>>) {
        self.handlers.insert(handler.handle(), handler);
    }

    pub fn push_message(&mut self, message: Message) -> Result<(), mpsc::SendError<Request>> {
        self.handle_events();
        self.dispatcher_input_channel.send(Request::Message(Arc::new(message)))
    }

    fn handle_event(&mut self, event: Response) {
        if let Some(handler) = self.handlers.get_mut(&event.handle()) {
            handler.handle_event(event, &mut self.dispatcher_input_channel);
        } else {
            trace!("no event handler found for handling a Response");
        }
    }

    pub fn handle_events(&mut self) {
        for i in self.dispatcher_output_channel.try_recv() {
            self.handle_event(i);
        }
    }

    pub fn stop(mut self) -> thread::Result<()> {
        self.handle_events();
        self.stop_dispatcher();
        self.dispatcher_thread_handle.join()
    }

    fn stop_dispatcher(&mut self) {
        let exit_condition = Condition::new(false);
        let exit_handler = Box::new(ExitHandler::new(exit_condition.clone()));
        self.register_handler(exit_handler);
        let _ = self.dispatcher_input_channel.send(Request::Exit);
        while !exit_condition.is_active() {
            if let Ok(event) = self.dispatcher_output_channel.recv() {
                self.handle_event(event);
            }
        }
    }
}
<|endoftext|>


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

use PanicStrategy;
use target::TargetOptions;
use std::default::Default;

pub fn opts() -> TargetOptions {
    TargetOptions {
        pre_link_args: vec![
            // We want to be able to strip as much executable code as possible
            // from the linker command line, and this flag indicates to the
            // linker that it can avoid linking in dynamic libraries that don't
            // actually satisfy any symbols up to that point (as with many other
            // resolutions the linker does). This option only applies to all
            // following libraries so we're sure to pass it as one of the first
            // arguments.
            "-Wl,--as-needed".to_string(),

            // Always enable NX protection when it is available
            "-Wl,-z,noexecstack".to_string(),

            // Do not link libc
            "-nostdlib".to_string(),

            // Static link
            "-static".to_string()
        ],
        executables: true,
        relocation_model: "static".to_string(),
        disable_redzone: true,
        eliminate_frame_pointer: false,
        target_family: Some("redox".to_string()),
        linker_is_gnu: true,
        no_default_libraries: true,
        lib_allocation_crate: "ralloc".to_string(),
        exe_allocation_crate: "ralloc".to_string(),
        has_elf_tls: true,
        panic_strategy: PanicStrategy::Abort,
        .. Default::default()
    }
}
<commit_msg>Add openlibm to redox<commit_after>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use PanicStrategy;
use target::TargetOptions;
use std::default::Default;

pub fn opts() -> TargetOptions {
    TargetOptions {
        pre_link_args: vec![
            // We want to be able to strip as much executable code as possible
            // from the linker command line, and this flag indicates to the
            // linker that it can avoid linking in dynamic libraries that don't
            // actually satisfy any symbols up to that point (as with many other
            // resolutions the linker does). This option only applies to all
            // following libraries so we're sure to pass it as one of the first
            // arguments.
            "-Wl,--as-needed".to_string(),

            // Always enable NX protection when it is available
            "-Wl,-z,noexecstack".to_string(),

            // Do not link libc
            "-nostdlib".to_string(),

            // Static link
            "-static".to_string()
        ],
        late_link_args: vec![
            // Link to openlibm for math functions
            "-lopenlibm".to_string()
        ],
        executables: true,
        relocation_model: "static".to_string(),
        disable_redzone: true,
        eliminate_frame_pointer: false,
        target_family: Some("redox".to_string()),
        linker_is_gnu: true,
        no_default_libraries: true,
        lib_allocation_crate: "ralloc".to_string(),
        exe_allocation_crate: "ralloc".to_string(),
        has_elf_tls: true,
        panic_strategy: PanicStrategy::Abort,
        .. Default::default()
    }
}
<|endoftext|>


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

#![allow(non_camel_case_types)]

use convert::TryInto;
use io;
use os::raw::c_char;
use u64;

use libc::{c_int, c_void};

pub type mx_handle_t = i32;
pub type mx_vaddr_t = usize;
pub type mx_rights_t = u32;
pub type mx_status_t = i32;

pub type mx_size_t = usize;

pub const MX_HANDLE_INVALID: mx_handle_t = 0;

pub type mx_time_t = u64;
pub const MX_TIME_INFINITE : mx_time_t = u64::MAX;

pub type mx_signals_t = u32;

pub const MX_OBJECT_SIGNAL_3         : mx_signals_t = 1 << 3;

pub const MX_TASK_TERMINATED        : mx_signals_t = MX_OBJECT_SIGNAL_3;

pub const MX_RIGHT_SAME_RIGHTS  : mx_rights_t = 1 << 31;

pub type mx_object_info_topic_t = u32;

pub const MX_INFO_PROCESS         : mx_object_info_topic_t = 3;

pub fn mx_cvt<T>(t: T) -> io::Result<T> where T: TryInto<mx_status_t>+Copy {
    if let Ok(status) = TryInto::try_into(t) {
        if status < 0 {
            Err(io::Error::from_raw_os_error(status))
        } else {
            Ok(t)
        }
    } else {
        Err(io::Error::last_os_error())
    }
}

// Safe wrapper around mx_handle_t
pub struct Handle {
    raw: mx_handle_t,
}

impl Handle {
    pub fn new(raw: mx_handle_t) -> Handle {
        Handle {
            raw: raw,
        }
    }

    pub fn raw(&self) -> mx_handle_t {
        self.raw
    }
}

impl Drop for Handle {
    fn drop(&mut self) {
        unsafe { mx_cvt(mx_handle_close(self.raw)).expect("Failed to close mx_handle_t"); }
    }
}

// Common MX_INFO header
#[derive(Default)]
#[repr(C)]
pub struct mx_info_header_t {
    pub topic: u32,              // identifies the info struct
    pub avail_topic_size: u16,   // “native” size of the struct
    pub topic_size: u16,         // size of the returned struct (<=topic_size)
    pub avail_count: u32,        // number of records the kernel has
    pub count: u32,              // number of records returned (limited by buffer size)
}

#[derive(Default)]
#[repr(C)]
pub struct mx_record_process_t {
    pub return_code: c_int,
}

// Returned for topic MX_INFO_PROCESS
#[derive(Default)]
#[repr(C)]
pub struct mx_info_process_t {
    pub hdr: mx_info_header_t,
    pub rec: mx_record_process_t,
}

extern {
    static __magenta_job_default: mx_handle_t;

    pub fn mx_task_kill(handle: mx_handle_t) -> mx_status_t;

    pub fn mx_handle_close(handle: mx_handle_t) -> mx_status_t;

    pub fn mx_handle_duplicate(handle: mx_handle_t, rights: mx_rights_t,
                               out: *const mx_handle_t) -> mx_handle_t;

    pub fn mx_object_wait_one(handle: mx_handle_t, signals: mx_signals_t, timeout: mx_time_t,
                              pending: *mut mx_signals_t) -> mx_status_t;

    pub fn mx_object_get_info(handle: mx_handle_t, topic: u32, buffer: *mut c_void,
                              buffer_size: mx_size_t, actual_size: *mut mx_size_t,
                              avail: *mut mx_size_t) -> mx_status_t;
}

pub fn mx_job_default() -> mx_handle_t {
    unsafe { return __magenta_job_default; }
}

// From `enum special_handles` in system/ulib/launchpad/launchpad.c
// HND_LOADER_SVC = 0
// HND_EXEC_VMO = 1
pub const HND_SPECIAL_COUNT: usize = 2;

#[repr(C)]
pub struct launchpad_t {
    argc: u32,
    envc: u32,
    args: *const c_char,
    args_len: usize,
    env: *const c_char,
    env_len: usize,

    handles: *mut mx_handle_t,
    handles_info: *mut u32,
    handle_count: usize,
    handle_alloc: usize,

    entry: mx_vaddr_t,
    base: mx_vaddr_t,
    vdso_base: mx_vaddr_t,

    stack_size: usize,

    special_handles: [mx_handle_t; HND_SPECIAL_COUNT],
    loader_message: bool,
}

extern {
    pub fn launchpad_create(job: mx_handle_t, name: *const c_char,
                            lp: *mut *mut launchpad_t) -> mx_status_t;

    pub fn launchpad_go(lp: *mut launchpad_t,
                        proc_handle: *mut mx_handle_t,
                        err_msg: *mut *const c_char) -> mx_status_t;

    pub fn launchpad_destroy(lp: *mut launchpad_t);

    pub fn launchpad_set_args(lp: *mut launchpad_t, argc: c_int,
                               argv: *const *const c_char) -> mx_status_t;

    pub fn launchpad_set_environ(lp: *mut launchpad_t, envp: *const *const c_char) -> mx_status_t;

    pub fn launchpad_clone(lp: *mut launchpad_t, what: u32) -> mx_status_t;

    pub fn launchpad_clone_fd(lp: *mut launchpad_t, fd: c_int, target_fd: c_int) -> mx_status_t;

    pub fn launchpad_transfer_fd(lp: *mut launchpad_t, fd: c_int, target_fd: c_int) -> mx_status_t;

    pub fn launchpad_elf_load(lp: *mut launchpad_t, vmo: mx_handle_t) -> mx_status_t;

    pub fn launchpad_add_vdso_vmo(lp: *mut launchpad_t) -> mx_status_t;

    pub fn launchpad_load_vdso(lp: *mut launchpad_t, vmo: mx_handle_t) -> mx_status_t;

    pub fn launchpad_vmo_from_file(filename: *const c_char) -> mx_handle_t;
}

// Launchpad clone constants

pub const LP_CLONE_MXIO_ROOT: u32 = 0x0001;
pub const LP_CLONE_MXIO_CWD: u32 = 0x0002;
// LP_CLONE_MXIO_STDIO = 0x0004
// LP_CLONE_MXIO_ALL = 0x00FF
// LP_CLONE_ENVIRON = 0x0100
// LP_CLONE_DEFAULT_JOB = 0x0200
// LP_CLONE_ALL = 0xFFFF

// Errors

#[allow(unused)] pub const ERR_INTERNAL: mx_status_t = -1;

// ERR_NOT_SUPPORTED: The operation is not implemented, supported,
// or enabled.
#[allow(unused)] pub const ERR_NOT_SUPPORTED: mx_status_t = -2;

// ERR_NO_RESOURCES: The system was not able to allocate some resource
// needed for the operation.
#[allow(unused)] pub const ERR_NO_RESOURCES: mx_status_t = -3;

// ERR_NO_MEMORY: The system was not able to allocate memory needed
// for the operation.
#[allow(unused)] pub const ERR_NO_MEMORY: mx_status_t = -4;

// ERR_CALL_FAILED: The second phase of mx_channel_call(; did not complete
// successfully.
#[allow(unused)] pub const ERR_CALL_FAILED: mx_status_t = -5;

// ERR_INTERRUPTED_RETRY: The system call was interrupted, but should be
// retried.  This should not be seen outside of the VDSO.
#[allow(unused)] pub const ERR_INTERRUPTED_RETRY: mx_status_t = -6;

// ======= Parameter errors =======
// ERR_INVALID_ARGS: an argument is invalid, ex. null pointer
#[allow(unused)] pub const ERR_INVALID_ARGS: mx_status_t = -10;

// ERR_BAD_HANDLE: A specified handle value does not refer to a handle.
#[allow(unused)] pub const ERR_BAD_HANDLE: mx_status_t = -11;

// ERR_WRONG_TYPE: The subject of the operation is the wrong type to
// perform the operation.
// Example: Attempting a message_read on a thread handle.
#[allow(unused)] pub const ERR_WRONG_TYPE: mx_status_t = -12;

// ERR_BAD_SYSCALL: The specified syscall number is invalid.
#[allow(unused)] pub const ERR_BAD_SYSCALL: mx_status_t = -13;

// ERR_OUT_OF_RANGE: An argument is outside the valid range for this
// operation.
#[allow(unused)] pub const ERR_OUT_OF_RANGE: mx_status_t = -14;

// ERR_BUFFER_TOO_SMALL: A caller provided buffer is too small for
// this operation.
#[allow(unused)] pub const ERR_BUFFER_TOO_SMALL: mx_status_t = -15;

// ======= Precondition or state errors =======
// ERR_BAD_STATE: operation failed because the current state of the
// object does not allow it, or a precondition of the operation is
// not satisfied
#[allow(unused)] pub const ERR_BAD_STATE: mx_status_t = -20;

// ERR_TIMED_OUT: The time limit for the operation elapsed before
// the operation completed.
#[allow(unused)] pub const ERR_TIMED_OUT: mx_status_t = -21;

// ERR_SHOULD_WAIT: The operation cannot be performed currently but
// potentially could succeed if the caller waits for a prerequisite
// to be satisfied, for example waiting for a handle to be readable
// or writable.
// Example: Attempting to read from a message pipe that has no
// messages waiting but has an open remote will return ERR_SHOULD_WAIT.
// Attempting to read from a message pipe that has no messages waiting
// and has a closed remote end will return ERR_REMOTE_CLOSED.
#[allow(unused)] pub const ERR_SHOULD_WAIT: mx_status_t = -22;

// ERR_CANCELED: The in-progress operation (e.g. a wait) has been
// // canceled.
#[allow(unused)] pub const ERR_CANCELED: mx_status_t = -23;

// ERR_PEER_CLOSED: The operation failed because the remote end
// of the subject of the operation was closed.
#[allow(unused)] pub const ERR_PEER_CLOSED: mx_status_t = -24;

// ERR_NOT_FOUND: The requested entity is not found.
#[allow(unused)] pub const ERR_NOT_FOUND: mx_status_t = -25;

// ERR_ALREADY_EXISTS: An object with the specified identifier
// already exists.
// Example: Attempting to create a file when a file already exists
// with that name.
#[allow(unused)] pub const ERR_ALREADY_EXISTS: mx_status_t = -26;

// ERR_ALREADY_BOUND: The operation failed because the named entity
// is already owned or controlled by another entity. The operation
// could succeed later if the current owner releases the entity.
#[allow(unused)] pub const ERR_ALREADY_BOUND: mx_status_t = -27;

// ERR_UNAVAILABLE: The subject of the operation is currently unable
// to perform the operation.
// Note: This is used when there's no direct way for the caller to
// observe when the subject will be able to perform the operation
// and should thus retry.
#[allow(unused)] pub const ERR_UNAVAILABLE: mx_status_t = -28;

// ======= Permission check errors =======
// ERR_ACCESS_DENIED: The caller did not have permission to perform
// the specified operation.
#[allow(unused)] pub const ERR_ACCESS_DENIED: mx_status_t = -30;

// ======= Input-output errors =======
// ERR_IO: Otherwise unspecified error occurred during I/O.
#[allow(unused)] pub const ERR_IO: mx_status_t = -40;

// ERR_REFUSED: The entity the I/O operation is being performed on
// rejected the operation.
// Example: an I2C device NAK'ing a transaction or a disk controller
// rejecting an invalid command.
#[allow(unused)] pub const ERR_IO_REFUSED: mx_status_t = -41;

// ERR_IO_DATA_INTEGRITY: The data in the operation failed an integrity
// check and is possibly corrupted.
// Example: CRC or Parity error.
#[allow(unused)] pub const ERR_IO_DATA_INTEGRITY: mx_status_t = -42;

// ERR_IO_DATA_LOSS: The data in the operation is currently unavailable
// and may be permanently lost.
// Example: A disk block is irrecoverably damaged.
#[allow(unused)] pub const ERR_IO_DATA_LOSS: mx_status_t = -43;

// Filesystem specific errors
#[allow(unused)] pub const ERR_BAD_PATH: mx_status_t = -50;
#[allow(unused)] pub const ERR_NOT_DIR: mx_status_t = -51;
#[allow(unused)] pub const ERR_NOT_FILE: mx_status_t = -52;
// ERR_FILE_BIG: A file exceeds a filesystem-specific size limit.
#[allow(unused)] pub const ERR_FILE_BIG: mx_status_t = -53;
// ERR_NO_SPACE: Filesystem or device space is exhausted.
#[allow(unused)] pub const ERR_NO_SPACE: mx_status_t = -54;
<commit_msg>Auto merge of #42452 - raphlinus:mx_job_default, r=alexcrichton<commit_after>// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![allow(non_camel_case_types)]

use convert::TryInto;
use io;
use os::raw::c_char;
use u64;

use libc::{c_int, c_void};

pub type mx_handle_t = i32;
pub type mx_vaddr_t = usize;
pub type mx_rights_t = u32;
pub type mx_status_t = i32;

pub type mx_size_t = usize;

pub const MX_HANDLE_INVALID: mx_handle_t = 0;

pub type mx_time_t = u64;
pub const MX_TIME_INFINITE : mx_time_t = u64::MAX;

pub type mx_signals_t = u32;

pub const MX_OBJECT_SIGNAL_3         : mx_signals_t = 1 << 3;

pub const MX_TASK_TERMINATED        : mx_signals_t = MX_OBJECT_SIGNAL_3;

pub const MX_RIGHT_SAME_RIGHTS  : mx_rights_t = 1 << 31;

pub type mx_object_info_topic_t = u32;

pub const MX_INFO_PROCESS         : mx_object_info_topic_t = 3;

pub fn mx_cvt<T>(t: T) -> io::Result<T> where T: TryInto<mx_status_t>+Copy {
    if let Ok(status) = TryInto::try_into(t) {
        if status < 0 {
            Err(io::Error::from_raw_os_error(status))
        } else {
            Ok(t)
        }
    } else {
        Err(io::Error::last_os_error())
    }
}

// Safe wrapper around mx_handle_t
pub struct Handle {
    raw: mx_handle_t,
}

impl Handle {
    pub fn new(raw: mx_handle_t) -> Handle {
        Handle {
            raw: raw,
        }
    }

    pub fn raw(&self) -> mx_handle_t {
        self.raw
    }
}

impl Drop for Handle {
    fn drop(&mut self) {
        unsafe { mx_cvt(mx_handle_close(self.raw)).expect("Failed to close mx_handle_t"); }
    }
}

// Common MX_INFO header
#[derive(Default)]
#[repr(C)]
pub struct mx_info_header_t {
    pub topic: u32,              // identifies the info struct
    pub avail_topic_size: u16,   // “native” size of the struct
    pub topic_size: u16,         // size of the returned struct (<=topic_size)
    pub avail_count: u32,        // number of records the kernel has
    pub count: u32,              // number of records returned (limited by buffer size)
}

#[derive(Default)]
#[repr(C)]
pub struct mx_record_process_t {
    pub return_code: c_int,
}

// Returned for topic MX_INFO_PROCESS
#[derive(Default)]
#[repr(C)]
pub struct mx_info_process_t {
    pub hdr: mx_info_header_t,
    pub rec: mx_record_process_t,
}

extern {
    pub fn mx_job_default() -> mx_handle_t;

    pub fn mx_task_kill(handle: mx_handle_t) -> mx_status_t;

    pub fn mx_handle_close(handle: mx_handle_t) -> mx_status_t;

    pub fn mx_handle_duplicate(handle: mx_handle_t, rights: mx_rights_t,
                               out: *const mx_handle_t) -> mx_handle_t;

    pub fn mx_object_wait_one(handle: mx_handle_t, signals: mx_signals_t, timeout: mx_time_t,
                              pending: *mut mx_signals_t) -> mx_status_t;

    pub fn mx_object_get_info(handle: mx_handle_t, topic: u32, buffer: *mut c_void,
                              buffer_size: mx_size_t, actual_size: *mut mx_size_t,
                              avail: *mut mx_size_t) -> mx_status_t;
}

// From `enum special_handles` in system/ulib/launchpad/launchpad.c
// HND_LOADER_SVC = 0
// HND_EXEC_VMO = 1
pub const HND_SPECIAL_COUNT: usize = 2;

#[repr(C)]
pub struct launchpad_t {
    argc: u32,
    envc: u32,
    args: *const c_char,
    args_len: usize,
    env: *const c_char,
    env_len: usize,

    handles: *mut mx_handle_t,
    handles_info: *mut u32,
    handle_count: usize,
    handle_alloc: usize,

    entry: mx_vaddr_t,
    base: mx_vaddr_t,
    vdso_base: mx_vaddr_t,

    stack_size: usize,

    special_handles: [mx_handle_t; HND_SPECIAL_COUNT],
    loader_message: bool,
}

extern {
    pub fn launchpad_create(job: mx_handle_t, name: *const c_char,
                            lp: *mut *mut launchpad_t) -> mx_status_t;

    pub fn launchpad_go(lp: *mut launchpad_t,
                        proc_handle: *mut mx_handle_t,
                        err_msg: *mut *const c_char) -> mx_status_t;

    pub fn launchpad_destroy(lp: *mut launchpad_t);

    pub fn launchpad_set_args(lp: *mut launchpad_t, argc: c_int,
                               argv: *const *const c_char) -> mx_status_t;

    pub fn launchpad_set_environ(lp: *mut launchpad_t, envp: *const *const c_char) -> mx_status_t;

    pub fn launchpad_clone(lp: *mut launchpad_t, what: u32) -> mx_status_t;

    pub fn launchpad_clone_fd(lp: *mut launchpad_t, fd: c_int, target_fd: c_int) -> mx_status_t;

    pub fn launchpad_transfer_fd(lp: *mut launchpad_t, fd: c_int, target_fd: c_int) -> mx_status_t;

    pub fn launchpad_elf_load(lp: *mut launchpad_t, vmo: mx_handle_t) -> mx_status_t;

    pub fn launchpad_add_vdso_vmo(lp: *mut launchpad_t) -> mx_status_t;

    pub fn launchpad_load_vdso(lp: *mut launchpad_t, vmo: mx_handle_t) -> mx_status_t;

    pub fn launchpad_vmo_from_file(filename: *const c_char) -> mx_handle_t;
}

// Launchpad clone constants

pub const LP_CLONE_MXIO_ROOT: u32 = 0x0001;
pub const LP_CLONE_MXIO_CWD: u32 = 0x0002;
// LP_CLONE_MXIO_STDIO = 0x0004
// LP_CLONE_MXIO_ALL = 0x00FF
// LP_CLONE_ENVIRON = 0x0100
// LP_CLONE_DEFAULT_JOB = 0x0200
// LP_CLONE_ALL = 0xFFFF

// Errors

#[allow(unused)] pub const ERR_INTERNAL: mx_status_t = -1;

// ERR_NOT_SUPPORTED: The operation is not implemented, supported,
// or enabled.
#[allow(unused)] pub const ERR_NOT_SUPPORTED: mx_status_t = -2;

// ERR_NO_RESOURCES: The system was not able to allocate some resource
// needed for the operation.
#[allow(unused)] pub const ERR_NO_RESOURCES: mx_status_t = -3;

// ERR_NO_MEMORY: The system was not able to allocate memory needed
// for the operation.
#[allow(unused)] pub const ERR_NO_MEMORY: mx_status_t = -4;

// ERR_CALL_FAILED: The second phase of mx_channel_call(; did not complete
// successfully.
#[allow(unused)] pub const ERR_CALL_FAILED: mx_status_t = -5;

// ERR_INTERRUPTED_RETRY: The system call was interrupted, but should be
// retried.  This should not be seen outside of the VDSO.
#[allow(unused)] pub const ERR_INTERRUPTED_RETRY: mx_status_t = -6;

// ======= Parameter errors =======
// ERR_INVALID_ARGS: an argument is invalid, ex. null pointer
#[allow(unused)] pub const ERR_INVALID_ARGS: mx_status_t = -10;

// ERR_BAD_HANDLE: A specified handle value does not refer to a handle.
#[allow(unused)] pub const ERR_BAD_HANDLE: mx_status_t = -11;

// ERR_WRONG_TYPE: The subject of the operation is the wrong type to
// perform the operation.
// Example: Attempting a message_read on a thread handle.
#[allow(unused)] pub const ERR_WRONG_TYPE: mx_status_t = -12;

// ERR_BAD_SYSCALL: The specified syscall number is invalid.
#[allow(unused)] pub const ERR_BAD_SYSCALL: mx_status_t = -13;

// ERR_OUT_OF_RANGE: An argument is outside the valid range for this
// operation.
#[allow(unused)] pub const ERR_OUT_OF_RANGE: mx_status_t = -14;

// ERR_BUFFER_TOO_SMALL: A caller provided buffer is too small for
// this operation.
#[allow(unused)] pub const ERR_BUFFER_TOO_SMALL: mx_status_t = -15;

// ======= Precondition or state errors =======
// ERR_BAD_STATE: operation failed because the current state of the
// object does not allow it, or a precondition of the operation is
// not satisfied
#[allow(unused)] pub const ERR_BAD_STATE: mx_status_t = -20;

// ERR_TIMED_OUT: The time limit for the operation elapsed before
// the operation completed.
#[allow(unused)] pub const ERR_TIMED_OUT: mx_status_t = -21;

// ERR_SHOULD_WAIT: The operation cannot be performed currently but
// potentially could succeed if the caller waits for a prerequisite
// to be satisfied, for example waiting for a handle to be readable
// or writable.
// Example: Attempting to read from a message pipe that has no
// messages waiting but has an open remote will return ERR_SHOULD_WAIT.
// Attempting to read from a message pipe that has no messages waiting
// and has a closed remote end will return ERR_REMOTE_CLOSED.
#[allow(unused)] pub const ERR_SHOULD_WAIT: mx_status_t = -22;

// ERR_CANCELED: The in-progress operation (e.g. a wait) has been
// // canceled.
#[allow(unused)] pub const ERR_CANCELED: mx_status_t = -23;

// ERR_PEER_CLOSED: The operation failed because the remote end
// of the subject of the operation was closed.
#[allow(unused)] pub const ERR_PEER_CLOSED: mx_status_t = -24;

// ERR_NOT_FOUND: The requested entity is not found.
#[allow(unused)] pub const ERR_NOT_FOUND: mx_status_t = -25;

// ERR_ALREADY_EXISTS: An object with the specified identifier
// already exists.
// Example: Attempting to create a file when a file already exists
// with that name.
#[allow(unused)] pub const ERR_ALREADY_EXISTS: mx_status_t = -26;

// ERR_ALREADY_BOUND: The operation failed because the named entity
// is already owned or controlled by another entity. The operation
// could succeed later if the current owner releases the entity.
#[allow(unused)] pub const ERR_ALREADY_BOUND: mx_status_t = -27;

// ERR_UNAVAILABLE: The subject of the operation is currently unable
// to perform the operation.
// Note: This is used when there's no direct way for the caller to
// observe when the subject will be able to perform the operation
// and should thus retry.
#[allow(unused)] pub const ERR_UNAVAILABLE: mx_status_t = -28;

// ======= Permission check errors =======
// ERR_ACCESS_DENIED: The caller did not have permission to perform
// the specified operation.
#[allow(unused)] pub const ERR_ACCESS_DENIED: mx_status_t = -30;

// ======= Input-output errors =======
// ERR_IO: Otherwise unspecified error occurred during I/O.
#[allow(unused)] pub const ERR_IO: mx_status_t = -40;

// ERR_REFUSED: The entity the I/O operation is being performed on
// rejected the operation.
// Example: an I2C device NAK'ing a transaction or a disk controller
// rejecting an invalid command.
#[allow(unused)] pub const ERR_IO_REFUSED: mx_status_t = -41;

// ERR_IO_DATA_INTEGRITY: The data in the operation failed an integrity
// check and is possibly corrupted.
// Example: CRC or Parity error.
#[allow(unused)] pub const ERR_IO_DATA_INTEGRITY: mx_status_t = -42;

// ERR_IO_DATA_LOSS: The data in the operation is currently unavailable
// and may be permanently lost.
// Example: A disk block is irrecoverably damaged.
#[allow(unused)] pub const ERR_IO_DATA_LOSS: mx_status_t = -43;

// Filesystem specific errors
#[allow(unused)] pub const ERR_BAD_PATH: mx_status_t = -50;
#[allow(unused)] pub const ERR_NOT_DIR: mx_status_t = -51;
#[allow(unused)] pub const ERR_NOT_FILE: mx_status_t = -52;
// ERR_FILE_BIG: A file exceeds a filesystem-specific size limit.
#[allow(unused)] pub const ERR_FILE_BIG: mx_status_t = -53;
// ERR_NO_SPACE: Filesystem or device space is exhausted.
#[allow(unused)] pub const ERR_NO_SPACE: mx_status_t = -54;
<|endoftext|>