<commit_before>use std::io::{Result, Write};

use analysis::rust_type::bounds_rust_type;
use case::CaseExt;
use analysis;
use library;
use env::Env;
use nameutil;
use super::child_properties;
use super::function;
use super::general;
use super::properties;
use super::signal;
use super::trait_impls;
use super::trampoline;

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

    try!(general::define_object_type(
        w,
        env,
        &analysis.name,
        &analysis.c_type,
        &analysis.c_class_type.as_ref().map(|s| &s[..]),
        &analysis.rust_class_type.as_ref().map(|s| &s[..]),
        &analysis.get_type,
        analysis.is_interface,
        &analysis.supertypes,
    ));

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

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

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

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

        for func_analysis in &analysis.functions() {
            try!(function::generate(w, env, func_analysis, false, false, 1));
        }

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

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

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

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

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

    if analysis.properties.iter().any(|property| property.construct || property.construct_only) {
        let mut methods = vec![];
        let mut properties = vec![];
        writeln!(w, "#[cfg(any(feature = \"builders\", feature = \"dox\"))]")?;
        writeln!(w, "pub struct {}Builder {{", analysis.name)?;
        for property in &analysis.properties {
            if (!property.is_get && property.construct) || property.construct_only {
                match bounds_rust_type(env, property.typ) {
                    Ok(type_string) => {
                        let attribute_type =
                            match type_string.as_str() {
                                "str" => "String",
                                _ => &type_string,
                            };
                        let name = nameutil::mangle_keywords(nameutil::signal_to_snake(&property.name));
                        if let Some(version) = property.version {
                            writeln!(w, "    #[cfg(any(feature = \"{}\", feature = \"dox\"))]", version.to_feature())?;
                        }
                        writeln!(w, "    {}: Option<{}>,", name, attribute_type)?;
                        let prefix =
                            if let Some(version) = property.version {
                                format!("    #[cfg(any(feature = \"{}\", feature = \"dox\"))]\n", version.to_feature())
                            }
                            else {
                                String::new()
                            };
                        let (type_string, conversion) =
                            match type_string.as_str() {
                                "str" => ("&str", ".to_string()"),
                                _ => (&*type_string, ""),
                            };
                        methods.push(format!("{}    pub fn {name}(mut self, {name}: {}) -> Self {{
        self.{name} = Some({name}{});
        self
    }}", prefix, type_string, conversion, name=name));
                        properties.push(property);
                    },
                    Err(_) => writeln!(w, "    //{}: /*Unknown type*/,", property.name)?,
                }
            }
        }
        writeln!(w, "}}\n")?;
        writeln!(w, "#[cfg(any(feature = \"builders\", feature = \"dox\"))]")?;
        writeln!(w, "impl {}Builder {{", analysis.name)?;
        writeln!(w, "    pub fn new() -> Self {{")?;
        writeln!(w, "        Self {{")?;
        for property in &properties {
            if let Some(version) = property.version {
                writeln!(w, "            #[cfg(any(feature = \"{}\", feature = \"dox\"))]", version.to_feature())?;
            }
            let name = nameutil::mangle_keywords(nameutil::signal_to_snake(&property.name));
            writeln!(w, "            {}: None,", name)?;
        }
        writeln!(w, "        }}")?;
        writeln!(w, "    }}")?;
        writeln!(w, "    pub fn build(self) -> {} {{", analysis.name)?;
        writeln!(w, "        let mut n_properties = 0;")?;
        writeln!(w, "        let mut property_names: Vec<CString> = vec![];")?;
        writeln!(w, "        let mut names = vec![];")?;
        writeln!(w, "        let mut values = vec![];")?;
        for property in &properties {
            let name = nameutil::mangle_keywords(nameutil::signal_to_snake(&property.name));
            if let Some(version) = property.version {
                writeln!(w, "        #[cfg(any(feature = \"{}\", feature = \"dox\"))]", version.to_feature())?;
                writeln!(w, "        {{")?;
            }
            writeln!(w, "        if let Some({property}) = self.{property} {{", property=name)?;
            writeln!(w, "            property_names.push(CString::new(\"{}\").unwrap());", property.name)?;
            writeln!(w, "            names.push(property_names[property_names.len() - 1].as_ptr());")?;
            writeln!(w, "            let property = {}.to_value();", name)?;
            writeln!(w, "            values.push(property.into_raw());")?;
            writeln!(w, "            n_properties += 1;")?;
            writeln!(w, "        }}")?;
            if property.version.is_some() {
                writeln!(w, "        }}")?;
            }
        }
        writeln!(w, "        unsafe {{")?;
        writeln!(w, "            crate::Object::from_glib_none(gobject_sys::g_object_new_with_properties(")?;
        writeln!(w, "                {}::static_type().to_glib(), n_properties, names.as_mut_ptr(), values.as_ptr())",
            analysis.name)?;
        writeln!(w, "            as *mut _).downcast().expect(\"downcast\")")?;
        writeln!(w, "        }}")?;
        writeln!(w, "    }}")?;
        for method in methods {
            writeln!(w, "{}", method)?;
        }
        writeln!(w, "}}")?;
    }

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

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

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

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

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

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

    if !analysis.trampolines.is_empty() {
        for trampoline in &analysis.trampolines {
            try!(trampoline::generate(
                w,
                env,
                trampoline,
                need_generate_trait(analysis),
                &analysis.name,
            ));
        }
    }

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

    Ok(())
}

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

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

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

    for func_analysis in &analysis.methods() {
        try!(function::generate(w, env, func_analysis, true, false, 1));
    }
    for property in &analysis.properties {
        try!(properties::generate(w, env, property, true, false, 1));
    }
    for child_property in &analysis.child_properties {
        try!(child_properties::generate(
            w,
            env,
            child_property,
            true,
            false,
            1,
        ));
    }
    for signal_analysis in analysis
        .signals
        .iter()
        .chain(analysis.notify_signals.iter())
    {
        try!(signal::generate(
            w,
            env,
            signal_analysis,
            &analysis.trampolines,
            true,
            false,
            1,
        ));
    }
    try!(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);
    }
    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()
    };

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

    let mut generate_builder = false;
    for property in &analysis.properties {
        if (!property.is_get && property.construct) || property.construct_only {
            generate_builder = true;
            break;
        }
    }
    if generate_builder {
        contents.extend_from_slice(&cfgs);
        contents.push(format!("#[cfg(any(feature = \"builders\", feature = \"dox\"))]
pub use self::{}::{}Builder;", module_name, analysis.name));
    }
}
<commit_msg>Fix formatting<commit_after>use std::io::{Result, Write};

use analysis::rust_type::bounds_rust_type;
use case::CaseExt;
use analysis;
use library;
use env::Env;
use nameutil;
use super::child_properties;
use super::function;
use super::general;
use super::properties;
use super::signal;
use super::trait_impls;
use super::trampoline;

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

    try!(general::define_object_type(
        w,
        env,
        &analysis.name,
        &analysis.c_type,
        &analysis.c_class_type.as_ref().map(|s| &s[..]),
        &analysis.rust_class_type.as_ref().map(|s| &s[..]),
        &analysis.get_type,
        analysis.is_interface,
        &analysis.supertypes,
    ));

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

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

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

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

        for func_analysis in &analysis.functions() {
            try!(function::generate(w, env, func_analysis, false, false, 1));
        }

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

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

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

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

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

    if analysis.properties.iter().any(|property| property.construct || property.construct_only) {
        let mut methods = vec![];
        let mut properties = vec![];
        writeln!(w, "#[cfg(any(feature = \"builders\", feature = \"dox\"))]
pub struct {}Builder {{", analysis.name)?;
        for property in &analysis.properties {
            if (!property.is_get && property.construct) || property.construct_only {
                match bounds_rust_type(env, property.typ) {
                    Ok(type_string) => {
                        let attribute_type =
                            match type_string.as_str() {
                                "str" => "String",
                                _ => &type_string,
                            };
                        let name = nameutil::mangle_keywords(nameutil::signal_to_snake(&property.name));
                        if let Some(version) = property.version {
                            writeln!(w, "    #[cfg(any(feature = \"{}\", feature = \"dox\"))]", version.to_feature())?;
                        }
                        writeln!(w, "    {}: Option<{}>,", name, attribute_type)?;
                        let prefix =
                            if let Some(version) = property.version {
                                format!("    #[cfg(any(feature = \"{}\", feature = \"dox\"))]\n", version.to_feature())
                            }
                            else {
                                String::new()
                            };
                        let (type_string, conversion) =
                            match type_string.as_str() {
                                "str" => ("&str", ".to_string()"),
                                _ => (&*type_string, ""),
                            };
                        methods.push(format!("\n{}    pub fn {name}(mut self, {name}: {}) -> Self {{
        self.{name} = Some({name}{});
        self
    }}", prefix, type_string, conversion, name=name));
                        properties.push(property);
                    },
                    Err(_) => writeln!(w, "    //{}: /*Unknown type*/,", property.name)?,
                }
            }
        }
        writeln!(w, "}}\n

#[cfg(any(feature = \"builders\", feature = \"dox\"))]
impl {}Builder {{
    pub fn new() -> Self {{
        Self {{", analysis.name)?;
        for property in &properties {
            if let Some(version) = property.version {
                writeln!(w, "            #[cfg(any(feature = \"{}\", feature = \"dox\"))]", version.to_feature())?;
            }
            let name = nameutil::mangle_keywords(nameutil::signal_to_snake(&property.name));
            writeln!(w, "            {}: None,", name)?;
        }
        writeln!(w, "        }}
    }}

    pub fn build(self) -> {} {{
        let mut n_properties = 0;
        let mut property_names: Vec<CString> = vec![];
        let mut names = vec![];
        let mut values = vec![];", analysis.name)?;
        for property in &properties {
            let name = nameutil::mangle_keywords(nameutil::signal_to_snake(&property.name));
            if let Some(version) = property.version {
                writeln!(w,
"        #[cfg(any(feature = \"{}\", feature = \"dox\"))]
        {{", version.to_feature())?;
            }
            writeln!(w,
"        if let Some({property}) = self.{property} {{
            property_names.push(CString::new(\"{}\").unwrap());
            names.push(property_names[property_names.len() - 1].as_ptr());
            let property = {property}.to_value();
            values.push(property.into_raw());
            n_properties += 1;
        }}", property.name, property=name)?;
            if property.version.is_some() {
                writeln!(w, "        }}")?;
            }
        }
        writeln!(w,
"        unsafe {{
            crate::Object::from_glib_none(gobject_sys::g_object_new_with_properties(
                {}::static_type().to_glib(), n_properties, names.as_mut_ptr(), values.as_ptr())
            as *mut _).downcast().expect(\"downcast\")
        }}
    }}", analysis.name)?;
        for method in methods {
            writeln!(w, "{}", method)?;
        }
        writeln!(w, "}}")?;
    }

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

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

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

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

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

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

    if !analysis.trampolines.is_empty() {
        for trampoline in &analysis.trampolines {
            try!(trampoline::generate(
                w,
                env,
                trampoline,
                need_generate_trait(analysis),
                &analysis.name,
            ));
        }
    }

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

    Ok(())
}

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

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

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

    for func_analysis in &analysis.methods() {
        try!(function::generate(w, env, func_analysis, true, false, 1));
    }
    for property in &analysis.properties {
        try!(properties::generate(w, env, property, true, false, 1));
    }
    for child_property in &analysis.child_properties {
        try!(child_properties::generate(
            w,
            env,
            child_property,
            true,
            false,
            1,
        ));
    }
    for signal_analysis in analysis
        .signals
        .iter()
        .chain(analysis.notify_signals.iter())
    {
        try!(signal::generate(
            w,
            env,
            signal_analysis,
            &analysis.trampolines,
            true,
            false,
            1,
        ));
    }
    try!(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);
    }
    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()
    };

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

    let mut generate_builder = false;
    for property in &analysis.properties {
        if (!property.is_get && property.construct) || property.construct_only {
            generate_builder = true;
            break;
        }
    }
    if generate_builder {
        contents.extend_from_slice(&cfgs);
        contents.push(format!("#[cfg(any(feature = \"builders\", feature = \"dox\"))]
pub use self::{}::{}Builder;", module_name, analysis.name));
    }
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate serde_derive;
extern crate serde_xml_rs;

#[derive(Debug, Deserialize)]
struct Mass {
    pub value: f64,
}

#[derive(Debug, Deserialize)]
struct Inertia {
    pub ixx: f64,
    pub ixy: f64,
    pub ixz: f64,
    pub iyy: f64,
    pub iyz: f64,
    pub izz: f64,
}

fn default_pose() -> Pose {
    Pose {
        xyz: empty_vec3(),
        rpy: empty_vec3(),
    }
}

fn default_mass() -> Mass {
    Mass { value: 0.0 }
}

fn default_inertia() -> Inertia {
    Inertia {
        ixx: 0.0,
        ixy: 0.0,
        ixz: 0.0,
        iyy: 0.0,
        iyz: 0.0,
        izz: 0.0,
    }
}

fn default_inertial() -> Inertial {
    Inertial {
        origin: default_pose(),
        mass: default_mass(),
        inertia: default_inertia(),
    }
}

#[derive(Debug, Deserialize)]
struct Inertial {
    #[serde(default = "default_pose")]
    pub origin: Pose,
    pub mass: Mass,
    pub inertia: Inertia,
}

#[derive(Debug, Deserialize)]
pub enum Geometry {
    #[serde(rename = "box")]
    Box { size: String },
    #[serde(rename = "cylinder")]
    Cylinder { radius: f64, length: f64 },
    #[serde(rename = "sphere")]
    Sphere { radius: f64 },
    #[serde(rename = "mesh")]
    Mesh { filename: String, scale: f64 },
}

#[derive(Debug, Deserialize)]
struct Color {
    #[serde(default)]
    rgba: String,
}

#[derive(Debug, Deserialize)]
struct Texture {
    #[serde(default)]
    filename: String,
}

#[derive(Debug, Deserialize)]
struct Material {
    #[serde(default)]
    pub name: String,
    #[serde(default = "default_color")]
    pub color: Color,
    #[serde(default = "default_texture")]
    pub texture: Texture,
}

fn default_geometry() -> Geometry {
    Geometry::Box { size: "0 0 0".to_string() }
}

fn default_visual() -> Visual {
    Visual {
        name: "".to_string(),
        origin: default_pose(),
        geometry: default_geometry(),
        material: default_material(),
    }
}

fn default_texture() -> Texture {
    Texture { filename: "".to_string() }
}

fn default_color() -> Color {
    Color { rgba: "0 0 0 0".to_string() }
}

fn default_material() -> Material {
    Material {
        name: "".to_string(),
        color: default_color(),
        texture: default_texture(),
    }
}

#[derive(Debug, Deserialize)]
struct Visual {
    #[serde(default)]
    pub name: String,
    #[serde(default = "default_pose")]
    pub origin: Pose,
    pub geometry: Geometry,
    #[serde(default = "default_material")]
    pub material: Material,
}

fn default_collision() -> Collision {
    Collision {
        name: "".to_string(),
        origin: default_pose(),
        geometry: default_geometry(),
    }
}

#[derive(Debug, Deserialize)]
struct Collision {
    #[serde(default)]
    pub name: String,
    pub origin: Pose,
    pub geometry: Geometry,
}

#[derive(Debug, Deserialize)]
struct Link {
    pub name: String,
    #[serde(default = "default_inertial")]
    pub inertial: Inertial,
    #[serde(default = "default_visual")]
    pub visual: Visual,
    #[serde(default = "default_collision")]
    pub collision: Collision,
}

#[derive(Debug, Deserialize)]
pub struct Axis {
    pub xyz: String,
}

fn default_axis() -> Axis {
    Axis { xyz: "1 0 0".to_string() }
}

fn empty_vec3() -> String {
    "0 0 0".to_string()
}

#[derive(Debug, Deserialize)]
struct Pose {
    #[serde(default = "empty_vec3")]
    pub xyz: String,
    #[serde(default = "empty_vec3")]
    pub rpy: String,
}

#[derive(Debug, Deserialize)]
struct LinkName {
    pub link: String,
}

#[derive(Debug, Deserialize)]
struct Joint {
    pub name: String,
    #[serde(rename = "type")]
    pub joint_type: String,
    #[serde(default = "default_pose")]
    pub origin: Pose,
    pub parent: LinkName,
    pub child: LinkName,
    #[serde(default = "default_axis")]
    pub axis: Axis,
}

#[derive(Debug, Deserialize)]
struct Robot {
    pub name: String,

    #[serde(rename = "link", default)]
    pub links: Vec<Link>,

    #[serde(rename = "joint", default)]
    pub joints: Vec<Joint>,
}

#[test]
fn it_works() {
    use serde_xml_rs::deserialize;
    let s = r##"
        <robot name="robo">
            <link name="shoulder1">
   <inertial>
     <origin xyz="0 0 0.5" rpy="0 0 0"/>
     <mass value="1"/>
     <inertia ixx="100"  ixy="0"  ixz="0" iyy="100" iyz="0" izz="100" />
   </inertial>

   <visual>
     <origin xyz="0 0 0" rpy="0 0 0" />
     <geometry>
       <box size="1 1 1" />
     </geometry>
     <material name="Cyan">
       <color rgba="0 1.0 1.0 1.0"/>
     </material>
   </visual>

   <collision>
     <origin xyz="0 0 0" rpy="0 0 0"/>
     <geometry>
       <cylinder radius="1" length="0.5"/>
     </geometry>
   </collision>
            </link>
            <link name="elbow1" />
            <link name="wrist1" />
            <joint name="shoulder_pitch" type="revolute">
                <origin xyz="0.0 0.0 0.1" />
                <parent link="shoulder1" />
                <child link="elbow1" />
                <axis xyz="0 1 0" />
            </joint>
            <joint name="shoulder_pitch" type="revolute">
                <origin xyz="0.0, 0.0, 0.0" />
                <parent link="elbow1" />
                <child link="wrist1" />
                <axis xyz="0 1 0" />
            </joint>
        </robot>
    "##;
    let robo: Robot = deserialize(s.as_bytes()).unwrap();
    assert_eq!(robo.name, "robo");
    assert_eq!(robo.links.len(), 3);
    assert_eq!(robo.joints.len(), 2);
    assert_eq!(robo.joints[0].name, "shoulder_pitch");
    assert_eq!(robo.joints[0].axis.xyz, "0 1 0");
    assert_eq!(robo.joints[0].origin.xyz, "0.0 0.0 0.1");
}
<commit_msg>Added as_array functions to convert to array<commit_after>#[macro_use]
extern crate serde_derive;
extern crate serde_xml_rs;

#[derive(Debug, Deserialize)]
pub struct Mass {
    pub value: f64,
}

#[derive(Debug, Deserialize)]
pub struct Inertia {
    pub ixx: f64,
    pub ixy: f64,
    pub ixz: f64,
    pub iyy: f64,
    pub iyz: f64,
    pub izz: f64,
}

fn default_pose() -> Pose {
    Pose {
        xyz: empty_vec3(),
        rpy: empty_vec3(),
    }
}

fn default_mass() -> Mass {
    Mass { value: 0.0 }
}

fn default_inertia() -> Inertia {
    Inertia {
        ixx: 0.0,
        ixy: 0.0,
        ixz: 0.0,
        iyy: 0.0,
        iyz: 0.0,
        izz: 0.0,
    }
}

fn default_inertial() -> Inertial {
    Inertial {
        origin: default_pose(),
        mass: default_mass(),
        inertia: default_inertia(),
    }
}

#[derive(Debug, Deserialize)]
pub struct Inertial {
    #[serde(default = "default_pose")]
    pub origin: Pose,
    pub mass: Mass,
    pub inertia: Inertia,
}

#[derive(Debug, Deserialize)]
pub enum Geometry {
    #[serde(rename = "box")]
    Box { size: String },
    #[serde(rename = "cylinder")]
    Cylinder { radius: f64, length: f64 },
    #[serde(rename = "sphere")]
    Sphere { radius: f64 },
    #[serde(rename = "mesh")]
    Mesh { filename: String, scale: f64 },
}

#[derive(Debug, Deserialize)]
pub struct Color {
    #[serde(default)]
    pub rgba: String,
}

#[derive(Debug, Deserialize)]
pub struct Texture {
    #[serde(default)]
    pub filename: String,
}

#[derive(Debug, Deserialize)]
pub struct Material {
    #[serde(default)]
    pub name: String,
    #[serde(default = "default_color")]
    pub color: Color,
    #[serde(default = "default_texture")]
    pub texture: Texture,
}

fn default_geometry() -> Geometry {
    Geometry::Box { size: "0 0 0".to_string() }
}

fn default_visual() -> Visual {
    Visual {
        name: "".to_string(),
        origin: default_pose(),
        geometry: default_geometry(),
        material: default_material(),
    }
}

fn default_texture() -> Texture {
    Texture { filename: "".to_string() }
}

fn default_color() -> Color {
    Color { rgba: "0 0 0 0".to_string() }
}

fn default_material() -> Material {
    Material {
        name: "".to_string(),
        color: default_color(),
        texture: default_texture(),
    }
}

#[derive(Debug, Deserialize)]
pub struct Visual {
    #[serde(default)]
    pub name: String,
    #[serde(default = "default_pose")]
    pub origin: Pose,
    pub geometry: Geometry,
    #[serde(default = "default_material")]
    pub material: Material,
}

fn default_collision() -> Collision {
    Collision {
        name: "".to_string(),
        origin: default_pose(),
        geometry: default_geometry(),
    }
}

#[derive(Debug, Deserialize)]
pub struct Collision {
    #[serde(default)]
    pub name: String,
    pub origin: Pose,
    pub geometry: Geometry,
}

#[derive(Debug, Deserialize)]
pub struct Link {
    pub name: String,
    #[serde(default = "default_inertial")]
    pub inertial: Inertial,
    #[serde(default = "default_visual")]
    pub visual: Visual,
    #[serde(default = "default_collision")]
    pub collision: Collision,
}

#[derive(Debug, Deserialize)]
pub struct Axis {
    pub xyz: String,
}

fn parse_array_from_string(string: &str) -> [f64; 3] {
    let vec = string.split(" ").filter_map(|x| x.parse::<f64>().ok()).collect::<Vec<_>>();
    let mut arr = [0.0f64; 3];
    for i in 0..3 {
        arr[i] = vec[i];
    }
    arr
}

impl Axis {
    pub fn xyz_as_array(&self) -> [f64; 3] {
        parse_array_from_string(&self.xyz)
    }
}

fn default_axis() -> Axis {
    Axis { xyz: "1 0 0".to_string() }
}

fn empty_vec3() -> String {
    "0 0 0".to_string()
}

#[derive(Debug, Deserialize)]
pub struct Pose {
    #[serde(default = "empty_vec3")]
    pub xyz: String,
    #[serde(default = "empty_vec3")]
    pub rpy: String,
}

impl Pose {
    pub fn xyz_as_array(&self) -> [f64; 3] {
        parse_array_from_string(&self.xyz)
    }
    pub fn rpy_as_array(&self) -> [f64; 3] {
        parse_array_from_string(&self.rpy)
    }
}

#[derive(Debug, Deserialize)]
pub struct LinkName {
    pub link: String,
}

#[derive(Debug, Deserialize)]
pub struct Joint {
    pub name: String,
    #[serde(rename = "type")]
    pub joint_type: String,
    #[serde(default = "default_pose")]
    pub origin: Pose,
    pub parent: LinkName,
    pub child: LinkName,
    #[serde(default = "default_axis")]
    pub axis: Axis,
}

#[derive(Debug, Deserialize)]
pub struct Robot {
    pub name: String,

    #[serde(rename = "link", default)]
    pub links: Vec<Link>,

    #[serde(rename = "joint", default)]
    pub joints: Vec<Joint>,
}

#[test]
fn it_works() {
    use serde_xml_rs::deserialize;
    let s = r##"
        <robot name="robo">
            <link name="shoulder1">
                <inertial>
                    <origin xyz="0 0 0.5" rpy="0 0 0"/>
                    <mass value="1"/>
                    <inertia ixx="100"  ixy="0"  ixz="0" iyy="100" iyz="0" izz="100" />
                </inertial>
                <visual>
                    <origin xyz="0.1 0.2 0.3" rpy="-0.1 -0.2  -0.3" />
                    <geometry>
                        <box size="1 1 1" />
                    </geometry>
                    <material name="Cyan">
                        <color rgba="0 1.0 1.0 1.0"/>
                    </material>
                </visual>
                <collision>
                    <origin xyz="0 0 0" rpy="0 0 0"/>
                    <geometry>
                        <cylinder radius="1" length="0.5"/>
                    </geometry>
                </collision>
            </link>
            <link name="elbow1" />
            <link name="wrist1" />
            <joint name="shoulder_pitch" type="revolute">
                <origin xyz="0.0 0.0 0.1" />
                <parent link="shoulder1" />
                <child link="elbow1" />
                <axis xyz="0 1 -1" />
            </joint>
            <joint name="shoulder_pitch" type="revolute">
                <origin xyz="0.0, 0.0, 0.0" />
                <parent link="elbow1" />
                <child link="wrist1" />
                <axis xyz="0 1 0" />
            </joint>
        </robot>
    "##;
    let robo: Robot = deserialize(s.as_bytes()).unwrap();
    assert_eq!(robo.name, "robo");
    assert_eq!(robo.links.len(), 3);
    assert_eq!(robo.joints.len(), 2);
    assert_eq!(robo.links[0].visual.origin.xyz_as_array()[0], 0.1);
    assert_eq!(robo.links[0].visual.origin.xyz_as_array()[1], 0.2);
    assert_eq!(robo.links[0].visual.origin.xyz_as_array()[2], 0.3);
    assert_eq!(robo.links[0].visual.origin.rpy_as_array()[0], -0.1);
    assert_eq!(robo.links[0].visual.origin.rpy_as_array()[1], -0.2);
    assert_eq!(robo.links[0].visual.origin.rpy_as_array()[2], -0.3);

    assert_eq!(robo.joints[0].name, "shoulder_pitch");
    assert_eq!(robo.joints[0].axis.xyz, "0 1 -1");
    assert_eq!(robo.joints[0].axis.xyz_as_array()[0], 0.0f64);
    assert_eq!(robo.joints[0].axis.xyz_as_array()[1], 1.0f64);
    assert_eq!(robo.joints[0].axis.xyz_as_array()[2], -1.0f64);
    assert_eq!(robo.joints[0].origin.xyz, "0.0 0.0 0.1");
}
<|endoftext|>


<commit_before>// Copyright 2015 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.

//! Utilities related to FFI bindings.
//!
//! This module provides utilities to handle data across non-Rust
//! interfaces, like other programming languages and the underlying
//! operating system. It is mainly of use for FFI (Foreign Function
//! Interface) bindings and code that needs to exchange C-like strings
//! with other languages.
//!
//! # Overview
//!
//! Rust represents owned strings with the [`String`] type, and
//! borrowed slices of strings with the [`str`] primitive. Both are
//! always in UTF-8 encoding, and may contain nul bytes in the middle,
//! i.e. if you look at the bytes that make up the string, there may
//! be a `\0` among them. Both `String` and `str` store their length
//! explicitly; there are no nul terminators at the end of strings
//! like in C.
//!
//! C strings are different from Rust strings:
//!
//! * **Encodings** - Rust strings are UTF-8, but C strings may use
//! other encodings. If you are using a string from C, you should
//! check its encoding explicitly, rather than just assuming that it
//! is UTF-8 like you can do in Rust.
//!
//! * **Character size** - C strings may use `char` or `wchar_t`-sized
//! characters; please **note** that C's `char` is different from Rust's.
//! The C standard leaves the actual sizes of those types open to
//! interpretation, but defines different APIs for strings made up of
//! each character type. Rust strings are always UTF-8, so different
//! Unicode characters will be encoded in a variable number of bytes
//! each. The Rust type [`char`] represents a '[Unicode scalar
//! value]', which is similar to, but not the same as, a '[Unicode
//! code point]'.
//!
//! * **Nul terminators and implicit string lengths** - Often, C
//! strings are nul-terminated, i.e. they have a `\0` character at the
//! end. The length of a string buffer is not stored, but has to be
//! calculated; to compute the length of a string, C code must
//! manually call a function like `strlen()` for `char`-based strings,
//! or `wcslen()` for `wchar_t`-based ones. Those functions return
//! the number of characters in the string excluding the nul
//! terminator, so the buffer length is really `len+1` characters.
//! Rust strings don't have a nul terminator; their length is always
//! stored and does not need to be calculated. While in Rust
//! accessing a string's length is a O(1) operation (because the
//! length is stored); in C it is an O(length) operation because the
//! length needs to be computed by scanning the string for the nul
//! terminator.
//!
//! * **Internal nul characters** - When C strings have a nul
//! terminator character, this usually means that they cannot have nul
//! characters in the middle — a nul character would essentially
//! truncate the string. Rust strings *can* have nul characters in
//! the middle, because nul does not have to mark the end of the
//! string in Rust.
//!
//! # Representations of non-Rust strings
//!
//! [`CString`] and [`CStr`] are useful when you need to transfer
//! UTF-8 strings to and from languages with a C ABI, like Python.
//!
//! * **From Rust to C:** [`CString`] represents an owned, C-friendly
//! string: it is nul-terminated, and has no internal nul characters.
//! Rust code can create a `CString` out of a normal string (provided
//! that the string doesn't have nul characters in the middle), and
//! then use a variety of methods to obtain a raw `*mut u8` that can
//! then be passed as an argument to functions which use the C
//! conventions for strings.
//!
//! * **From C to Rust:** [`CStr`] represents a borrowed C string; it
//! is what you would use to wrap a raw `*const u8` that you got from
//! a C function. A `CStr` is guaranteed to be a nul-terminated array
//! of bytes. Once you have a `CStr`, you can convert it to a Rust
//! `&str` if it's valid UTF-8, or lossily convert it by adding
//! replacement characters.
//!
//! [`OsString`] and [`OsStr`] are useful when you need to transfer
//! strings to and from the operating system itself, or when capturing
//! the output of external commands. Conversions between `OsString`,
//! `OsStr` and Rust strings work similarly to those for [`CString`]
//! and [`CStr`].
//!
//! * [`OsString`] represents an owned string in whatever
//! representation the operating system prefers. In the Rust standard
//! library, various APIs that transfer strings to/from the operating
//! system use `OsString` instead of plain strings. For example,
//! [`env::var_os()`] is used to query environment variables; it
//! returns an `Option<OsString>`. If the environment variable exists
//! you will get a `Some(os_string)`, which you can *then* try to
//! convert to a Rust string. This yields a [`Result<>`], so that
//! your code can detect errors in case the environment variable did
//! not in fact contain valid Unicode data.
//!
//! * [`OsStr`] represents a borrowed reference to a string in a
//! format that can be passed to the operating system. It can be
//! converted into an UTF-8 Rust string slice in a similar way to
//! `OsString`.
//!
//! # Conversions
//!
//! ## On Unix
//!
//! On Unix, [`OsStr`] implements the
//! `std::os::unix:ffi::`[`OsStrExt`][unix.OsStrExt] trait, which
//! augments it with two methods, [`from_bytes`] and [`as_bytes`].
//! These do inexpensive conversions from and to UTF-8 byte slices.
//!
//! Additionally, on Unix [`OsString`] implements the
//! `std::os::unix:ffi::`[`OsStringExt`][unix.OsStringExt] trait,
//! which provides [`from_vec`] and [`into_vec`] methods that consume
//! their arguments, and take or produce vectors of [`u8`].
//!
//! ## On Windows
//!
//! On Windows, [`OsStr`] implements the
//! `std::os::windows::ffi::`[`OsStrExt`][windows.OsStrExt] trait,
//! which provides an [`encode_wide`] method. This provides an
//! iterator that can be [`collect`]ed into a vector of [`u16`].
//!
//! Additionally, on Windows [`OsString`] implements the
//! `std::os::windows:ffi::`[`OsStringExt`][windows.OsStringExt]
//! trait, which provides a [`from_wide`] method. The result of this
//! method is an `OsString` which can be round-tripped to a Windows
//! string losslessly.
//!
//! [`String`]: ../string/struct.String.html
//! [`str`]: ../primitive.str.html
//! [`char`]: ../primitive.char.html
//! [`u8`]: ../primitive.u8.html
//! [`u16`]: ../primitive.u16.html
//! [Unicode scalar value]: http://www.unicode.org/glossary/#unicode_scalar_value
//! [Unicode code point]: http://www.unicode.org/glossary/#code_point
//! [`CString`]: struct.CString.html
//! [`CStr`]: struct.CStr.html
//! [`OsString`]: struct.OsString.html
//! [`OsStr`]: struct.OsStr.html
//! [`env::set_var()`]: ../env/fn.set_var.html
//! [`env::var_os()`]: ../env/fn.var_os.html
//! [`Result<>`]: ../result/enum.Result.html
//! [unix.OsStringExt]: ../os/unix/ffi/trait.OsStringExt.html
//! [`from_vec`]: ../os/unix/ffi/trait.OsStringExt.html#tymethod.from_vec
//! [`into_vec`]: ../os/unix/ffi/trait.OsStringExt.html#tymethod.into_vec
//! [unix.OsStrExt]: ../os/unix/ffi/trait.OsStrExt.html
//! [`from_bytes`]: ../os/unix/ffi/trait.OsStrExt.html#tymethod.from_bytes
//! [`as_bytes`]: ../os/unix/ffi/trait.OsStrExt.html#tymethod.as_bytes
//! [`OsStrExt`]: ../os/unix/ffi/trait.OsStrExt.html
//! [windows.OsStrExt]: ../os/windows/ffi/trait.OsStrExt.html
//! [`encode_wide`]: ../os/windows/ffi/trait.OsStrExt.html#tymethod.encode_wide
//! [`collect`]: ../iter/trait.Iterator.html#method.collect
//! [windows.OsStringExt]: ../os/windows/ffi/trait.OsStringExt.html
//! [`from_wide`]: ../os/windows/ffi/trait.OsStringExt.html#tymethod.from_wide

#![stable(feature = "rust1", since = "1.0.0")]

#[stable(feature = "rust1", since = "1.0.0")]
pub use self::c_str::{CString, CStr, NulError, IntoStringError};
#[stable(feature = "cstr_from_bytes", since = "1.10.0")]
pub use self::c_str::{FromBytesWithNulError};

#[stable(feature = "rust1", since = "1.0.0")]
pub use self::os_str::{OsString, OsStr};

#[stable(feature = "raw_os", since = "1.1.0")]
pub use core::ffi::c_void;

mod c_str;
mod os_str;
<commit_msg>Rollup merge of #56294 - polyfloyd:fix-typo-ffi-doc, r=sfackler<commit_after>// Copyright 2015 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.

//! Utilities related to FFI bindings.
//!
//! This module provides utilities to handle data across non-Rust
//! interfaces, like other programming languages and the underlying
//! operating system. It is mainly of use for FFI (Foreign Function
//! Interface) bindings and code that needs to exchange C-like strings
//! with other languages.
//!
//! # Overview
//!
//! Rust represents owned strings with the [`String`] type, and
//! borrowed slices of strings with the [`str`] primitive. Both are
//! always in UTF-8 encoding, and may contain nul bytes in the middle,
//! i.e. if you look at the bytes that make up the string, there may
//! be a `\0` among them. Both `String` and `str` store their length
//! explicitly; there are no nul terminators at the end of strings
//! like in C.
//!
//! C strings are different from Rust strings:
//!
//! * **Encodings** - Rust strings are UTF-8, but C strings may use
//! other encodings. If you are using a string from C, you should
//! check its encoding explicitly, rather than just assuming that it
//! is UTF-8 like you can do in Rust.
//!
//! * **Character size** - C strings may use `char` or `wchar_t`-sized
//! characters; please **note** that C's `char` is different from Rust's.
//! The C standard leaves the actual sizes of those types open to
//! interpretation, but defines different APIs for strings made up of
//! each character type. Rust strings are always UTF-8, so different
//! Unicode characters will be encoded in a variable number of bytes
//! each. The Rust type [`char`] represents a '[Unicode scalar
//! value]', which is similar to, but not the same as, a '[Unicode
//! code point]'.
//!
//! * **Nul terminators and implicit string lengths** - Often, C
//! strings are nul-terminated, i.e. they have a `\0` character at the
//! end. The length of a string buffer is not stored, but has to be
//! calculated; to compute the length of a string, C code must
//! manually call a function like `strlen()` for `char`-based strings,
//! or `wcslen()` for `wchar_t`-based ones. Those functions return
//! the number of characters in the string excluding the nul
//! terminator, so the buffer length is really `len+1` characters.
//! Rust strings don't have a nul terminator; their length is always
//! stored and does not need to be calculated. While in Rust
//! accessing a string's length is a O(1) operation (because the
//! length is stored); in C it is an O(length) operation because the
//! length needs to be computed by scanning the string for the nul
//! terminator.
//!
//! * **Internal nul characters** - When C strings have a nul
//! terminator character, this usually means that they cannot have nul
//! characters in the middle — a nul character would essentially
//! truncate the string. Rust strings *can* have nul characters in
//! the middle, because nul does not have to mark the end of the
//! string in Rust.
//!
//! # Representations of non-Rust strings
//!
//! [`CString`] and [`CStr`] are useful when you need to transfer
//! UTF-8 strings to and from languages with a C ABI, like Python.
//!
//! * **From Rust to C:** [`CString`] represents an owned, C-friendly
//! string: it is nul-terminated, and has no internal nul characters.
//! Rust code can create a `CString` out of a normal string (provided
//! that the string doesn't have nul characters in the middle), and
//! then use a variety of methods to obtain a raw `*mut u8` that can
//! then be passed as an argument to functions which use the C
//! conventions for strings.
//!
//! * **From C to Rust:** [`CStr`] represents a borrowed C string; it
//! is what you would use to wrap a raw `*const u8` that you got from
//! a C function. A `CStr` is guaranteed to be a nul-terminated array
//! of bytes. Once you have a `CStr`, you can convert it to a Rust
//! `&str` if it's valid UTF-8, or lossily convert it by adding
//! replacement characters.
//!
//! [`OsString`] and [`OsStr`] are useful when you need to transfer
//! strings to and from the operating system itself, or when capturing
//! the output of external commands. Conversions between `OsString`,
//! `OsStr` and Rust strings work similarly to those for [`CString`]
//! and [`CStr`].
//!
//! * [`OsString`] represents an owned string in whatever
//! representation the operating system prefers. In the Rust standard
//! library, various APIs that transfer strings to/from the operating
//! system use `OsString` instead of plain strings. For example,
//! [`env::var_os()`] is used to query environment variables; it
//! returns an `Option<OsString>`. If the environment variable exists
//! you will get a `Some(os_string)`, which you can *then* try to
//! convert to a Rust string. This yields a [`Result<>`], so that
//! your code can detect errors in case the environment variable did
//! not in fact contain valid Unicode data.
//!
//! * [`OsStr`] represents a borrowed reference to a string in a
//! format that can be passed to the operating system. It can be
//! converted into an UTF-8 Rust string slice in a similar way to
//! `OsString`.
//!
//! # Conversions
//!
//! ## On Unix
//!
//! On Unix, [`OsStr`] implements the
//! `std::os::unix::ffi::`[`OsStrExt`][unix.OsStrExt] trait, which
//! augments it with two methods, [`from_bytes`] and [`as_bytes`].
//! These do inexpensive conversions from and to UTF-8 byte slices.
//!
//! Additionally, on Unix [`OsString`] implements the
//! `std::os::unix::ffi::`[`OsStringExt`][unix.OsStringExt] trait,
//! which provides [`from_vec`] and [`into_vec`] methods that consume
//! their arguments, and take or produce vectors of [`u8`].
//!
//! ## On Windows
//!
//! On Windows, [`OsStr`] implements the
//! `std::os::windows::ffi::`[`OsStrExt`][windows.OsStrExt] trait,
//! which provides an [`encode_wide`] method. This provides an
//! iterator that can be [`collect`]ed into a vector of [`u16`].
//!
//! Additionally, on Windows [`OsString`] implements the
//! `std::os::windows:ffi::`[`OsStringExt`][windows.OsStringExt]
//! trait, which provides a [`from_wide`] method. The result of this
//! method is an `OsString` which can be round-tripped to a Windows
//! string losslessly.
//!
//! [`String`]: ../string/struct.String.html
//! [`str`]: ../primitive.str.html
//! [`char`]: ../primitive.char.html
//! [`u8`]: ../primitive.u8.html
//! [`u16`]: ../primitive.u16.html
//! [Unicode scalar value]: http://www.unicode.org/glossary/#unicode_scalar_value
//! [Unicode code point]: http://www.unicode.org/glossary/#code_point
//! [`CString`]: struct.CString.html
//! [`CStr`]: struct.CStr.html
//! [`OsString`]: struct.OsString.html
//! [`OsStr`]: struct.OsStr.html
//! [`env::set_var()`]: ../env/fn.set_var.html
//! [`env::var_os()`]: ../env/fn.var_os.html
//! [`Result<>`]: ../result/enum.Result.html
//! [unix.OsStringExt]: ../os/unix/ffi/trait.OsStringExt.html
//! [`from_vec`]: ../os/unix/ffi/trait.OsStringExt.html#tymethod.from_vec
//! [`into_vec`]: ../os/unix/ffi/trait.OsStringExt.html#tymethod.into_vec
//! [unix.OsStrExt]: ../os/unix/ffi/trait.OsStrExt.html
//! [`from_bytes`]: ../os/unix/ffi/trait.OsStrExt.html#tymethod.from_bytes
//! [`as_bytes`]: ../os/unix/ffi/trait.OsStrExt.html#tymethod.as_bytes
//! [`OsStrExt`]: ../os/unix/ffi/trait.OsStrExt.html
//! [windows.OsStrExt]: ../os/windows/ffi/trait.OsStrExt.html
//! [`encode_wide`]: ../os/windows/ffi/trait.OsStrExt.html#tymethod.encode_wide
//! [`collect`]: ../iter/trait.Iterator.html#method.collect
//! [windows.OsStringExt]: ../os/windows/ffi/trait.OsStringExt.html
//! [`from_wide`]: ../os/windows/ffi/trait.OsStringExt.html#tymethod.from_wide

#![stable(feature = "rust1", since = "1.0.0")]

#[stable(feature = "rust1", since = "1.0.0")]
pub use self::c_str::{CString, CStr, NulError, IntoStringError};
#[stable(feature = "cstr_from_bytes", since = "1.10.0")]
pub use self::c_str::{FromBytesWithNulError};

#[stable(feature = "rust1", since = "1.0.0")]
pub use self::os_str::{OsString, OsStr};

#[stable(feature = "raw_os", since = "1.1.0")]
pub use core::ffi::c_void;

mod c_str;
mod os_str;
<|endoftext|>


<commit_before>use error::{Result, ErrorKind};
use std::result::Result as StdResult;
use read::{WadReadFrom, WadRead};
use rustc_serialize::{Encoder, Encodable, Decoder, Decodable};
use std::ascii::AsciiExt;
use std::fmt;
use std::fmt::Debug;
use std::fmt::Display;
use std::io::Read;
use std::str::{self, FromStr};
use std::error::Error;
use std::ops::Deref;
use std::borrow::Borrow;

#[derive(Clone, Copy, PartialEq, PartialOrd, Ord, Eq, Hash)]
pub struct WadName([u8; 8]);

impl Deref for WadName {
    type Target = [u8; 8];
    fn deref(&self) -> &[u8; 8] {
        &self.0
    }
}

impl WadName {
    pub fn from_bytes(value: &[u8]) -> Result<WadName> {
        let mut name = [0u8; 8];
        let mut nulled = false;
        for (dest, src) in name.iter_mut().zip(value.iter()) {
            if !src.is_ascii() {
                debug!("Bailed on non-ascii {}", src);
                return Err(ErrorKind::BadWadName(value.iter().cloned().collect()).into());
            }

            let new_byte = match src.to_ascii_uppercase() {
                b@b'A'...b'Z' |
                b@b'0'...b'9' |
                b@b'_' |
                b@b'-' |
                b@b'[' |
                b@b']' |
                b@b'\\' => b,
                b'\0' => { nulled = true; break },
                b => {
                    debug!("Bailed on ascii {}", b);
                    return Err(ErrorKind::BadWadName(value.iter().cloned().collect()).into());
                }
            };
            *dest = new_byte;
        }
        if !nulled && value.len() > 8 {
            debug!("Bailed on '{:?}' {} {}", str::from_utf8(value), value.len(), !nulled);
            Err(ErrorKind::BadWadName(value.iter().cloned().collect()).into())
        } else {
            Ok(WadName(name))
        }
    }
}

impl FromStr for WadName {
    type Err = super::error::Error;
    fn from_str(value: &str) -> Result<WadName> {
        WadName::from_bytes(value.as_bytes())
    }
}

impl Display for WadName {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        write!(formatter, "{}", str::from_utf8(&self[..]).unwrap())
    }
}
impl Debug for WadName {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        write!(formatter, "WadName({:?})", str::from_utf8(&self[..]).unwrap())
    }
}
impl Encodable for WadName {
    fn encode<S: Encoder>(&self, encoder: &mut S) -> StdResult<(), <S as Encoder>::Error> {
        str::from_utf8(&self[..]).unwrap().encode(encoder)
    }
}

impl Decodable for WadName {
    fn decode<S: Decoder>(decoder: &mut S)
            -> StdResult<WadName, <S as Decoder>::Error> {
        decoder.read_str()
               .and_then(|s| {
                   WadName::from_str(&s).map_err(|_| decoder.error("Could not decode WadName."))
               })
    }
}

impl WadReadFrom for WadName {
    fn wad_read_from<R: Read>(reader: &mut R) -> Result<Self> {
        let bytes = try!(reader.wad_read::<u64>());
        WadName::from_bytes(&[( bytes        & 0xff) as u8, ((bytes >>  8) & 0xff) as u8,
                              ((bytes >> 16) & 0xff) as u8, ((bytes >> 24) & 0xff) as u8,
                              ((bytes >> 32) & 0xff) as u8, ((bytes >> 40) & 0xff) as u8,
                              ((bytes >> 48) & 0xff) as u8, ((bytes >> 56) & 0xff) as u8])
    }
}

impl PartialEq<[u8; 8]> for WadName {
    fn eq(&self, rhs: &[u8; 8]) -> bool {
        self.deref() == rhs
    }
}

impl Borrow<[u8; 8]> for WadName {
    fn borrow(&self) -> &[u8; 8] {
        self.deref()
    }
}

impl AsRef<str> for WadName {
    fn as_ref(&self) -> &str {
        str::from_utf8(self.deref()).ok().expect("wad name is not valid utf-8")
    }
}

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

    #[test]
    fn test_wad_name() {
        assert_eq!(&WadName::from_str("").unwrap(), b"\0\0\0\0\0\0\0\0");
        assert_eq!(&WadName::from_str("\0").unwrap(), b"\0\0\0\0\0\0\0\0");
        assert_eq!(&WadName::from_str("\01234567").unwrap(), b"\0\0\0\0\0\0\0\0");
        assert_eq!(&WadName::from_str("A").unwrap(), b"A\0\0\0\0\0\0\0");
        assert_eq!(&WadName::from_str("1234567").unwrap(), b"1234567\0");
        assert_eq!(&WadName::from_str("12345678").unwrap(), b"12345678");
        assert_eq!(&WadName::from_str("123\05678").unwrap(), b"123\0\0\0\0\0");
        assert_eq!(&WadName::from_str("SKY1").unwrap(), b"SKY1\0\0\0\0");
        assert_eq!(&WadName::from_str("-").unwrap(), b"-\0\0\0\0\0\0\0");
        assert_eq!(&WadName::from_str("_").unwrap(), b"_\0\0\0\0\0\0\0");

        assert!(WadName::from_bytes(b"123456789").is_err());
        assert!(WadName::from_bytes(b"1234\xfb").is_err());
        assert!(WadName::from_bytes(b"\xff123").is_err());
        assert!(WadName::from_bytes(b"$$ASDF_").is_err());
        assert!(WadName::from_bytes(b"123456789\0").is_err());
    }
}
<commit_msg>remove trailing whitespace<commit_after>use error::{Result, ErrorKind};
use std::result::Result as StdResult;
use read::{WadReadFrom, WadRead};
use rustc_serialize::{Encoder, Encodable, Decoder, Decodable};
use std::ascii::AsciiExt;
use std::fmt;
use std::fmt::Debug;
use std::fmt::Display;
use std::io::Read;
use std::str::{self, FromStr};
use std::error::Error;
use std::ops::Deref;
use std::borrow::Borrow;

#[derive(Clone, Copy, PartialEq, PartialOrd, Ord, Eq, Hash)]
pub struct WadName([u8; 8]);

impl Deref for WadName {
    type Target = [u8; 8];
    fn deref(&self) -> &[u8; 8] {
        &self.0
    }
}

impl WadName {
    pub fn from_bytes(value: &[u8]) -> Result<WadName> {
        let mut name = [0u8; 8];
        let mut nulled = false;
        for (dest, src) in name.iter_mut().zip(value.iter()) {
            if !src.is_ascii() {
                debug!("Bailed on non-ascii {}", src);
                return Err(ErrorKind::BadWadName(value.iter().cloned().collect()).into());
            }

            let new_byte = match src.to_ascii_uppercase() {
                b@b'A'...b'Z' |
                b@b'0'...b'9' |
                b@b'_' |
                b@b'-' |
                b@b'[' |
                b@b']' |
                b@b'\\' => b,
                b'\0' => { nulled = true; break },
                b => {
                    debug!("Bailed on ascii {}", b);
                    return Err(ErrorKind::BadWadName(value.iter().cloned().collect()).into());
                }
            };
            *dest = new_byte;
        }
        if !nulled && value.len() > 8 {
            debug!("Bailed on '{:?}' {} {}", str::from_utf8(value), value.len(), !nulled);
            Err(ErrorKind::BadWadName(value.iter().cloned().collect()).into())
        } else {
            Ok(WadName(name))
        }
    }
}

impl FromStr for WadName {
    type Err = super::error::Error;
    fn from_str(value: &str) -> Result<WadName> {
        WadName::from_bytes(value.as_bytes())
    }
}

impl Display for WadName {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        write!(formatter, "{}", str::from_utf8(&self[..]).unwrap())
    }
}
impl Debug for WadName {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        write!(formatter, "WadName({:?})", str::from_utf8(&self[..]).unwrap())
    }
}
impl Encodable for WadName {
    fn encode<S: Encoder>(&self, encoder: &mut S) -> StdResult<(), <S as Encoder>::Error> {
        str::from_utf8(&self[..]).unwrap().encode(encoder)
    }
}

impl Decodable for WadName {
    fn decode<S: Decoder>(decoder: &mut S)
            -> StdResult<WadName, <S as Decoder>::Error> {
        decoder.read_str()
               .and_then(|s| {
                   WadName::from_str(&s).map_err(|_| decoder.error("Could not decode WadName."))
               })
    }
}

impl WadReadFrom for WadName {
    fn wad_read_from<R: Read>(reader: &mut R) -> Result<Self> {
        let bytes = try!(reader.wad_read::<u64>());
        WadName::from_bytes(&[( bytes        & 0xff) as u8, ((bytes >>  8) & 0xff) as u8,
                              ((bytes >> 16) & 0xff) as u8, ((bytes >> 24) & 0xff) as u8,
                              ((bytes >> 32) & 0xff) as u8, ((bytes >> 40) & 0xff) as u8,
                              ((bytes >> 48) & 0xff) as u8, ((bytes >> 56) & 0xff) as u8])
    }
}

impl PartialEq<[u8; 8]> for WadName {
    fn eq(&self, rhs: &[u8; 8]) -> bool {
        self.deref() == rhs
    }
}

impl Borrow<[u8; 8]> for WadName {
    fn borrow(&self) -> &[u8; 8] {
        self.deref()
    }
}

impl AsRef<str> for WadName {
    fn as_ref(&self) -> &str {
        str::from_utf8(self.deref()).ok().expect("wad name is not valid utf-8")
    }
}

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

    #[test]
    fn test_wad_name() {
        assert_eq!(&WadName::from_str("").unwrap(), b"\0\0\0\0\0\0\0\0");
        assert_eq!(&WadName::from_str("\0").unwrap(), b"\0\0\0\0\0\0\0\0");
        assert_eq!(&WadName::from_str("\01234567").unwrap(), b"\0\0\0\0\0\0\0\0");
        assert_eq!(&WadName::from_str("A").unwrap(), b"A\0\0\0\0\0\0\0");
        assert_eq!(&WadName::from_str("1234567").unwrap(), b"1234567\0");
        assert_eq!(&WadName::from_str("12345678").unwrap(), b"12345678");
        assert_eq!(&WadName::from_str("123\05678").unwrap(), b"123\0\0\0\0\0");
        assert_eq!(&WadName::from_str("SKY1").unwrap(), b"SKY1\0\0\0\0");
        assert_eq!(&WadName::from_str("-").unwrap(), b"-\0\0\0\0\0\0\0");
        assert_eq!(&WadName::from_str("_").unwrap(), b"_\0\0\0\0\0\0\0");

        assert!(WadName::from_bytes(b"123456789").is_err());
        assert!(WadName::from_bytes(b"1234\xfb").is_err());
        assert!(WadName::from_bytes(b"\xff123").is_err());
        assert!(WadName::from_bytes(b"$$ASDF_").is_err());
        assert!(WadName::from_bytes(b"123456789\0").is_err());
    }
}
<|endoftext|>


<commit_before>use super::abi::usercalls::{alloc, raw::ByteBuffer};
use crate::ffi::OsString;
use crate::slice;
use crate::sync::atomic::{AtomicUsize, Ordering};
use crate::sys::os_str::Buf;
use crate::sys_common::FromInner;

#[cfg_attr(test, linkage = "available_externally")]
#[export_name = "_ZN16__rust_internals3std3sys3sgx4args4ARGSE"]
static ARGS: AtomicUsize = AtomicUsize::new(0);
type ArgsStore = Vec<OsString>;

#[cfg_attr(test, allow(dead_code))]
pub unsafe fn init(argc: isize, argv: *const *const u8) {
    if argc != 0 {
        let args = alloc::User::<[ByteBuffer]>::from_raw_parts(argv as _, argc as _);
        let args = args
            .iter()
            .map(|a| OsString::from_inner(Buf { inner: a.copy_user_buffer() }))
            .collect::<ArgsStore>();
        ARGS.store(Box::into_raw(Box::new(args)) as _, Ordering::Relaxed);
    }
}

pub unsafe fn cleanup() {
    let args = ARGS.swap(0, Ordering::Relaxed);
    if args != 0 {
        drop(Box::<ArgsStore>::from_raw(args as _))
    }
}

pub fn args() -> Args {
    let args = unsafe { (ARGS.load(Ordering::Relaxed) as *const ArgsStore).as_ref() };
    if let Some(args) = args { Args(args.iter()) } else { Args([].iter()) }
}

pub struct Args(slice::Iter<'static, OsString>);

impl Args {
    pub fn inner_debug(&self) -> &[OsString] {
        self.0.as_slice()
    }
}

impl Iterator for Args {
    type Item = OsString;
    fn next(&mut self) -> Option<OsString> {
        self.0.next().cloned()
    }
    fn size_hint(&self) -> (usize, Option<usize>) {
        self.0.size_hint()
    }
}

impl ExactSizeIterator for Args {
    fn len(&self) -> usize {
        self.0.len()
    }
}

impl DoubleEndedIterator for Args {
    fn next_back(&mut self) -> Option<OsString> {
        self.0.next_back().cloned()
    }
}
<commit_msg>make the sgx arg cleanup implementation a no op<commit_after>use super::abi::usercalls::{alloc, raw::ByteBuffer};
use crate::ffi::OsString;
use crate::slice;
use crate::sync::atomic::{AtomicUsize, Ordering};
use crate::sys::os_str::Buf;
use crate::sys_common::FromInner;

#[cfg_attr(test, linkage = "available_externally")]
#[export_name = "_ZN16__rust_internals3std3sys3sgx4args4ARGSE"]
static ARGS: AtomicUsize = AtomicUsize::new(0);
type ArgsStore = Vec<OsString>;

#[cfg_attr(test, allow(dead_code))]
pub unsafe fn init(argc: isize, argv: *const *const u8) {
    if argc != 0 {
        let args = alloc::User::<[ByteBuffer]>::from_raw_parts(argv as _, argc as _);
        let args = args
            .iter()
            .map(|a| OsString::from_inner(Buf { inner: a.copy_user_buffer() }))
            .collect::<ArgsStore>();
        ARGS.store(Box::into_raw(Box::new(args)) as _, Ordering::Relaxed);
    }
}

pub unsafe fn cleanup() {}

pub fn args() -> Args {
    let args = unsafe { (ARGS.load(Ordering::Relaxed) as *const ArgsStore).as_ref() };
    if let Some(args) = args { Args(args.iter()) } else { Args([].iter()) }
}

pub struct Args(slice::Iter<'static, OsString>);

impl Args {
    pub fn inner_debug(&self) -> &[OsString] {
        self.0.as_slice()
    }
}

impl Iterator for Args {
    type Item = OsString;
    fn next(&mut self) -> Option<OsString> {
        self.0.next().cloned()
    }
    fn size_hint(&self) -> (usize, Option<usize>) {
        self.0.size_hint()
    }
}

impl ExactSizeIterator for Args {
    fn len(&self) -> usize {
        self.0.len()
    }
}

impl DoubleEndedIterator for Args {
    fn next_back(&mut self) -> Option<OsString> {
        self.0.next_back().cloned()
    }
}
<|endoftext|>


<commit_before>use super::ActivationFunction;
use fixedbitset::FixedBitSet;

pub enum CppnNodeType {
    Bias,
    Input,
    Output,
    Hidden,
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
struct CppnNodeIndex(usize);

impl CppnNodeIndex {
    fn index(&self) -> usize {
        self.0
    }
}

struct CppnLink {
    node_idx: CppnNodeIndex,
    weight: f64,
}

struct CppnNode {
    node_type: CppnNodeType,
    activation_function: Box<ActivationFunction>,
    input_links: Vec<CppnLink>,
    output_links: Vec<CppnLink>,
}

struct CppnGraph {
    nodes: Vec<CppnNode>,
}

impl CppnGraph {
    fn new() -> CppnGraph {
        CppnGraph { nodes: Vec::new() }
    }

    fn add_node(&mut self,
                node_type: CppnNodeType,
                activation_function: Box<ActivationFunction>)
                -> CppnNodeIndex {
        let idx = CppnNodeIndex(self.nodes.len());
        self.nodes.push(CppnNode {
            node_type: node_type,
            activation_function: activation_function,
            input_links: Vec::new(),
            output_links: Vec::new(),
        });
        return idx;
    }

    // Returns true if the introduction of this directed link would lead towards a cycle.
    fn would_cycle(&self, source_node_idx: CppnNodeIndex, target_node_idx: CppnNodeIndex) -> bool {
        if source_node_idx == target_node_idx {
            return true;
        }

        let mut seen_nodes = FixedBitSet::with_capacity(self.nodes.len());
        let mut nodes_to_visit = Vec::new();

        // We start at the target node and iterate all paths from there. If we hit the source node,
        // we found a cycle. Otherwise not.
        let start = target_node_idx.index();

        // We are looking for a path to this node.
        let path_to = source_node_idx.index();

        nodes_to_visit.push(start);
        seen_nodes.insert(start);

        while let Some(visit_node) = nodes_to_visit.pop() {
            for out_link in &self.nodes[visit_node].output_links {
                let next_node = out_link.node_idx.index();
                if !seen_nodes.contains(next_node) {
                    if next_node == path_to {
                        // We found a path to `path_to`. We have found a cycle.
                        return true;
                    }

                    seen_nodes.insert(next_node);
                    nodes_to_visit.push(next_node)
                }
            }
        }

        // We haven't found a cycle.
        return false;
    }

    // Note: Doesn't check for cycles (except in the simple reflexive case).
    fn add_link(&mut self,
                source_node_idx: CppnNodeIndex,
                target_node_idx: CppnNodeIndex,
                weight: f64) {
        if source_node_idx == target_node_idx {
            panic!("Loops are not allowed");
        }

        {
            let mut source_node = &mut self.nodes[source_node_idx.index()];
            if let CppnNodeType::Output = source_node.node_type {
                panic!("Cannot have an outgoing connection from Output node");
            }
            source_node.output_links.push(CppnLink {
                node_idx: target_node_idx,
                weight: weight,
            });
        }

        {
            let mut target_node = &mut self.nodes[target_node_idx.index()];
            if let CppnNodeType::Input = target_node.node_type {
                panic!("Cannot have an incoming connection to Input node");
            }

            if let CppnNodeType::Bias = target_node.node_type {
                panic!("Cannot have an incoming connection to Bias node");
            }

            target_node.input_links.push(CppnLink {
                node_idx: source_node_idx,
                weight: weight,
            });
        }
    }
}

/// Represents the output value of a CppnNode.
#[derive(Debug, Copy, Clone)]
enum CppnNodeValue {
    None,
    InCalculation,
    Cached(f64),
}

struct CppnState {
    values: Vec<CppnNodeValue>,
}

impl CppnState {
    fn reset(&mut self) {
        for value in self.values.iter_mut() {
            *value = CppnNodeValue::None;
        }
    }

    /// Calculates the output of node `node_idx`, recursively calculating
    /// the outputs of all dependent nodes.
    /// Panics if it hits a cycle.
    /// XXX: Implement a non-recursive version.
    fn calculate_output_of_node(&mut self, graph: &CppnGraph, node_idx: CppnNodeIndex) -> f64 {
        match self.values[node_idx.index()] {
            CppnNodeValue::InCalculation => {
                panic!("Cycle detected");
            }
            CppnNodeValue::Cached(value) => {
                // Return the cached value.
                return value;
            }
            CppnNodeValue::None => {
                // fall through.
            }
        }
        let node = &graph.nodes[node_idx.index()];

        // Sum the input links
        let input_sum: f64 = match node.node_type {
            CppnNodeType::Bias => 1.0,
            CppnNodeType::Input => {
                debug_assert!(node.input_links.is_empty());
                panic!("No input set for Input node");
            }
            CppnNodeType::Output | CppnNodeType::Hidden => {
                // Mark this node as being processes. If we hit such a node during a recursive call
                // we have a cycle.
                self.values[node_idx.index()] = CppnNodeValue::InCalculation;
                let mut sum: f64 = 0.0;
                for in_link in &node.input_links {
                    sum += in_link.weight * self.calculate_output_of_node(graph, in_link.node_idx);
                }
                sum
            }
        };

        // apply activation function on `input_sum`.
        let output = node.activation_function.calculate(input_sum);

        // cache the value. this also resets the InCalculation state.
        self.values[node_idx.index()] = CppnNodeValue::Cached(output);

        output
    }
}

/// Represents a Compositional Pattern Producing Network (CPPN)
pub struct Cppn;

impl Cppn {}
<commit_msg>Add method valid_link(). Add test cases.<commit_after>use super::ActivationFunction;
use fixedbitset::FixedBitSet;

pub enum CppnNodeType {
    Bias,
    Input,
    Output,
    Hidden,
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
struct CppnNodeIndex(usize);

impl CppnNodeIndex {
    fn index(&self) -> usize {
        self.0
    }
}

struct CppnLink {
    node_idx: CppnNodeIndex,
    weight: f64,
}

struct CppnNode {
    node_type: CppnNodeType,
    activation_function: Box<ActivationFunction>,
    input_links: Vec<CppnLink>,
    output_links: Vec<CppnLink>,
}

struct CppnGraph {
    nodes: Vec<CppnNode>,
}

impl CppnGraph {
    fn new() -> CppnGraph {
        CppnGraph { nodes: Vec::new() }
    }

    fn add_node(&mut self,
                node_type: CppnNodeType,
                activation_function: Box<ActivationFunction>)
                -> CppnNodeIndex {
        let idx = CppnNodeIndex(self.nodes.len());
        self.nodes.push(CppnNode {
            node_type: node_type,
            activation_function: activation_function,
            input_links: Vec::new(),
            output_links: Vec::new(),
        });
        return idx;
    }

    // Returns true if the introduction of this directed link would lead towards a cycle.
    fn would_cycle(&self, source_node_idx: CppnNodeIndex, target_node_idx: CppnNodeIndex) -> bool {
        if source_node_idx == target_node_idx {
            return true;
        }

        let mut seen_nodes = FixedBitSet::with_capacity(self.nodes.len());
        let mut nodes_to_visit = Vec::new();

        // We start at the target node and iterate all paths from there. If we hit the source node,
        // we found a cycle. Otherwise not.
        let start = target_node_idx.index();

        // We are looking for a path to this node.
        let path_to = source_node_idx.index();

        nodes_to_visit.push(start);
        seen_nodes.insert(start);

        while let Some(visit_node) = nodes_to_visit.pop() {
            for out_link in &self.nodes[visit_node].output_links {
                let next_node = out_link.node_idx.index();
                if !seen_nodes.contains(next_node) {
                    if next_node == path_to {
                        // We found a path to `path_to`. We have found a cycle.
                        return true;
                    }

                    seen_nodes.insert(next_node);
                    nodes_to_visit.push(next_node)
                }
            }
        }

        // We haven't found a cycle.
        return false;
    }

    // Check if the link is valid. Doesn't check for cycles.
    fn valid_link(&self,
                  source_node_idx: CppnNodeIndex,
                  target_node_idx: CppnNodeIndex)
                  -> Result<(), &'static str> {
        if source_node_idx == target_node_idx {
            return Err("Loops are not allowed");
        }

        let source_node = &self.nodes[source_node_idx.index()];
        if let CppnNodeType::Output = source_node.node_type {
            return Err("Cannot have an outgoing connection from Output node");
        }

        let target_node = &self.nodes[target_node_idx.index()];
        if let CppnNodeType::Input = target_node.node_type {
            return Err("Cannot have an incoming connection to Input node");
        }

        if let CppnNodeType::Bias = target_node.node_type {
            return Err("Cannot have an incoming connection to Bias node");
        }

        Ok(())
    }

    // Note: Doesn't check for cycles (except in the simple reflexive case).
    fn add_link(&mut self,
                source_node_idx: CppnNodeIndex,
                target_node_idx: CppnNodeIndex,
                weight: f64) {
        if let Err(err) = self.valid_link(source_node_idx, target_node_idx) {
            panic!(err);
        }

        self.nodes[source_node_idx.index()].output_links.push(CppnLink {
            node_idx: target_node_idx,
            weight: weight,
        });

        self.nodes[target_node_idx.index()].input_links.push(CppnLink {
            node_idx: source_node_idx,
            weight: weight,
        });
    }
}

/// Represents the output value of a CppnNode.
#[derive(Debug, Copy, Clone)]
enum CppnNodeValue {
    None,
    InCalculation,
    Cached(f64),
}

struct CppnState {
    values: Vec<CppnNodeValue>,
}

impl CppnState {
    fn reset(&mut self) {
        for value in self.values.iter_mut() {
            *value = CppnNodeValue::None;
        }
    }

    /// Calculates the output of node `node_idx`, recursively calculating
    /// the outputs of all dependent nodes.
    /// Panics if it hits a cycle.
    /// XXX: Implement a non-recursive version.
    fn calculate_output_of_node(&mut self, graph: &CppnGraph, node_idx: CppnNodeIndex) -> f64 {
        match self.values[node_idx.index()] {
            CppnNodeValue::InCalculation => {
                panic!("Cycle detected");
            }
            CppnNodeValue::Cached(value) => {
                // Return the cached value.
                return value;
            }
            CppnNodeValue::None => {
                // fall through.
            }
        }
        let node = &graph.nodes[node_idx.index()];

        // Sum the input links
        let input_sum: f64 = match node.node_type {
            CppnNodeType::Bias => 1.0,
            CppnNodeType::Input => {
                debug_assert!(node.input_links.is_empty());
                panic!("No input set for Input node");
            }
            CppnNodeType::Output | CppnNodeType::Hidden => {
                // Mark this node as being processes. If we hit such a node during a recursive call
                // we have a cycle.
                self.values[node_idx.index()] = CppnNodeValue::InCalculation;
                let mut sum: f64 = 0.0;
                for in_link in &node.input_links {
                    sum += in_link.weight * self.calculate_output_of_node(graph, in_link.node_idx);
                }
                sum
            }
        };

        // apply activation function on `input_sum`.
        let output = node.activation_function.calculate(input_sum);

        // cache the value. this also resets the InCalculation state.
        self.values[node_idx.index()] = CppnNodeValue::Cached(output);

        output
    }
}

/// Represents a Compositional Pattern Producing Network (CPPN)
pub struct Cppn;

impl Cppn {}

#[test]
fn test_cycle() {
    use super::Identity;
    let mut g = CppnGraph::new();
    let i1 = g.add_node(CppnNodeType::Input, Box::new(Identity));
    let h1 = g.add_node(CppnNodeType::Hidden, Box::new(Identity));
    let h2 = g.add_node(CppnNodeType::Hidden, Box::new(Identity));
    assert_eq!(true, g.valid_link(i1, i1).is_err());
    assert_eq!(true, g.valid_link(h1, h1).is_err());

    assert_eq!(true, g.valid_link(h1, i1).is_err());
    assert_eq!(Ok(()), g.valid_link(i1, h1));
    assert_eq!(Ok(()), g.valid_link(i1, h2));
    assert_eq!(Ok(()), g.valid_link(h1, h2));

    g.add_link(i1, h1, 0.0);
    assert_eq!(true, g.would_cycle(h1, i1));
    assert_eq!(false, g.would_cycle(i1, h1));
    assert_eq!(false, g.would_cycle(i1, h2));
    assert_eq!(true, g.would_cycle(i1, i1));
    assert_eq!(false, g.would_cycle(h1, h2));
    assert_eq!(false, g.would_cycle(h2, h1));
    assert_eq!(false, g.would_cycle(h2, i1));

    g.add_link(h1, h2, 0.0);
    assert_eq!(true, g.would_cycle(h2, i1));
    assert_eq!(true, g.would_cycle(h1, i1));
    assert_eq!(true, g.would_cycle(h2, h1));
    assert_eq!(false, g.would_cycle(i1, h2));
}
<|endoftext|>


<commit_before>// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License.  You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.  See the License for the
// specific language governing permissions and limitations
// under the License.

#![feature(test)]
extern crate test;
extern crate parquet_rs;
use test::Bencher;

use std::rc::Rc;
use parquet_rs::basic::*;
use parquet_rs::data_type::*;
use parquet_rs::encodings::encoding::*;
use parquet_rs::schema::types::{Type as SchemaType, ColumnDescriptor, ColumnPath};
use parquet_rs::util::memory::MemTracker;

const BATCH_SIZE: usize = 1024;

#[bench]
fn plain_encoding_bool(bench: &mut Bencher) {
  plain_encoding::<BoolType>(bench, vec![false; BATCH_SIZE], 1, Type::BOOLEAN);
}

#[bench]
fn plain_encoding_i32(bench: &mut Bencher) {
  plain_encoding::<Int32Type>(bench, vec![0; BATCH_SIZE], 8, Type::INT64);
}

#[bench]
fn plain_encoding_i64(bench: &mut Bencher) {
  plain_encoding::<Int64Type>(bench, vec![0; BATCH_SIZE], 8, Type::INT64);
}

fn plain_encoding<T: DataType>(bench: &mut Bencher, data: Vec<T::T>, type_length: i32, primitive_ty: Type) {
  let mem_tracker = MemTracker::new_ptr(None).expect("");
  let mut encoder = PlainEncoder::<T>::new(
    Rc::new(col_desc(type_length, primitive_ty)), mem_tracker, vec!());
  bench.iter(|| {
    let _ = encoder.put(&data[..], BATCH_SIZE);
  })
}

fn col_desc(type_length: i32, primitive_ty: Type) -> ColumnDescriptor {
  let ty = SchemaType::new_primitive_type(
    "col", Repetition::OPTIONAL, primitive_ty, LogicalType::NONE, type_length, 0, 0, None).unwrap();
  ColumnDescriptor::new(Rc::new(ty), None, 0, 0, ColumnPath::new(vec!()))
}
<commit_msg>Fix micro benchmark for encoding<commit_after>// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License.  You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.  See the License for the
// specific language governing permissions and limitations
// under the License.

#![feature(test)]
extern crate test;
extern crate parquet;
use test::Bencher;

use std::rc::Rc;
use parquet::basic::*;
use parquet::data_type::*;
use parquet::encodings::encoding::*;
use parquet::schema::types::{Type as SchemaType, ColumnDescriptor, ColumnPath};
use parquet::util::memory::MemTracker;

const BATCH_SIZE: usize = 1024;

#[bench]
fn plain_encoding_bool(bench: &mut Bencher) {
  plain_encoding::<BoolType>(bench, vec![false; BATCH_SIZE], 1, Type::BOOLEAN);
}

#[bench]
fn plain_encoding_i32(bench: &mut Bencher) {
  plain_encoding::<Int32Type>(bench, vec![0; BATCH_SIZE], 4, Type::INT32);
}

#[bench]
fn plain_encoding_i64(bench: &mut Bencher) {
  plain_encoding::<Int64Type>(bench, vec![0; BATCH_SIZE], 8, Type::INT64);
}

fn plain_encoding<T: DataType>(bench: &mut Bencher, data: Vec<T::T>, type_length: i32, primitive_ty: Type) {
  let mem_tracker = MemTracker::new_ptr(None).expect("");
  let mut encoder = PlainEncoder::<T>::new(
    Rc::new(col_desc(type_length, primitive_ty)), mem_tracker, vec!());
  bench.iter(|| {
    let _ = encoder.put(&data[..]);
  })
}

fn col_desc(type_length: i32, primitive_ty: Type) -> ColumnDescriptor {
  let ty = SchemaType::new_primitive_type(
    "col", Repetition::OPTIONAL, primitive_ty, LogicalType::NONE, type_length, 0, 0, None).unwrap();
  ColumnDescriptor::new(Rc::new(ty), None, 0, 0, ColumnPath::new(vec!()))
}
<|endoftext|>


<commit_before>pub struct Node {
    pub left: Link,
    pub right: Link,
    pub value: u32
}

pub enum Link {
    Child(Box<Node>),
    Nil
}

fn is_valid_range(node: &Node, min: Option<u32>, max: Option<u32>) -> bool {
    if let Some(m) = min {
        if node.value < m {
            return false;
        }
    }

    if let Some(m) = max {
        if node.value > m {
            return false;
        }
    }

    if let Link::Child(ref left) = node.left {
        if !is_valid_range(&left, min, Some(node.value)) {
            return false;
        }
    }
    if let Link::Child(ref right) = node.right {
        if !is_valid_range(&right, Some(node.value), max) {
            return false;
        }
    }
    true
}

/// Return true if the given binary search tree is valid.
///
/// # Examples
///
/// ```
/// use validbtree::*;
///
/// let n3 = Node { left: Link::Nil, right: Link::Nil, value: 3};
/// let n7 = Node { left: Link::Nil, right: Link::Nil, value: 7};
///
/// let n5 = Node { left: Link::Child(Box::new(n7)),
///                 right: Link::Child(Box::new(n3)),
///                 value: 5};
/// assert!(!is_valid(&n5));
/// ```
pub fn is_valid(node: &Node) -> bool {
    is_valid_range(node, None, None)
}

#[test]
fn root_only() {
    assert!(is_valid(&Node { left: Link::Nil, right: Link::Nil, value: 25}));
}

#[test]
fn valid_tree() {
    //                   9
    //                  / \
    //                 5   23
    //                / \   \
    //               3   7   25
    let n3 = Node { left: Link::Nil, right: Link::Nil, value: 3};
    let n7 = Node { left: Link::Nil, right: Link::Nil, value: 7};
    let n25 = Node { left: Link::Nil, right: Link::Nil, value: 25};

    let n5 = Node { left: Link::Child(Box::new(n3)),
                    right: Link::Child(Box::new(n7)),
                    value: 5};
    let n23 = Node { left: Link::Nil,
                     right: Link::Child(Box::new(n25)),
                     value: 23};

    let n9 = Node { left: Link::Child(Box::new(n5)),
                    right: Link::Child(Box::new(n23)),
                    value: 9};

    assert!(is_valid(&n9));
}

#[test]
fn leaf_in_left_subtree_greater_than_root() {
    //                   9
    //                  / \
    //                 5   23
    //                / \   \
    //               3  11   25
    let n3 = Node { left: Link::Nil, right: Link::Nil, value: 3};
    let n11 = Node { left: Link::Nil, right: Link::Nil, value: 11};
    let n25 = Node { left: Link::Nil, right: Link::Nil, value: 25};

    let n5 = Node { left: Link::Child(Box::new(n3)),
                    right: Link::Child(Box::new(n11)),
                    value: 5};
    let n23 = Node { left: Link::Nil,
                     right: Link::Child(Box::new(n25)),
                     value: 23};

    let n9 = Node { left: Link::Child(Box::new(n5)),
                    right: Link::Child(Box::new(n23)),
                    value: 9};

    assert!(!is_valid(&n9));
}
<commit_msg>Enforce uniqueness in the tree.<commit_after>pub struct Node {
    pub left: Link,
    pub right: Link,
    pub value: u32
}

pub enum Link {
    Child(Box<Node>),
    Nil
}

fn is_valid_range(node: &Node, min: Option<u32>, max: Option<u32>) -> bool {
    if let Some(m) = min {
        if node.value <= m {
            return false;
        }
    }

    if let Some(m) = max {
        if node.value >= m {
            return false;
        }
    }

    if let Link::Child(ref left) = node.left {
        if !is_valid_range(&left, min, Some(node.value)) {
            return false;
        }
    }
    if let Link::Child(ref right) = node.right {
        if !is_valid_range(&right, Some(node.value), max) {
            return false;
        }
    }
    true
}

/// Return true if the given binary search tree is valid.
///
/// # Examples
///
/// ```
/// use validbtree::*;
///
/// let n3 = Node{left: Link::Nil, right: Link::Nil, value: 3};
/// let n7 = Node{left: Link::Nil, right: Link::Nil, value: 7};
///
/// let n5 = Node {left: Link::Child(Box::new(n7)),
///                right: Link::Child(Box::new(n3)),
///                value: 5};
/// assert!(!is_valid(&n5));
/// ```
pub fn is_valid(node: &Node) -> bool {
    is_valid_range(node, None, None)
}

#[test]
fn root_only() {
    assert!(is_valid(&Node { left: Link::Nil, right: Link::Nil, value: 25}));
}

#[test]
fn valid_tree() {
    //                   9
    //                  / \
    //                 5   23
    //                / \   \
    //               3   7   25
    let n3 = Node{left: Link::Nil, right: Link::Nil, value: 3};
    let n7 = Node{left: Link::Nil, right: Link::Nil, value: 7};
    let n25 = Node{left: Link::Nil, right: Link::Nil, value: 25};

    let n5 = Node{left: Link::Child(Box::new(n3)),
                  right: Link::Child(Box::new(n7)),
                  value: 5};
    let n23 = Node{left: Link::Nil,
                   right: Link::Child(Box::new(n25)),
                   value: 23};

    let n9 = Node{left: Link::Child(Box::new(n5)),
                  right: Link::Child(Box::new(n23)),
                  value: 9};

    assert!(is_valid(&n9));
}

#[test]
fn leaf_in_left_subtree_greater_than_root() {
    //                   9
    //                  / \
    //                 5   23
    //                / \   \
    //               3  11   25
    let n3 = Node{left: Link::Nil, right: Link::Nil, value: 3};
    let n11 = Node{left: Link::Nil, right: Link::Nil, value: 11};
    let n25 = Node{left: Link::Nil, right: Link::Nil, value: 25};

    let n5 = Node{left: Link::Child(Box::new(n3)),
                  right: Link::Child(Box::new(n11)),
                  value: 5};
    let n23 = Node{left: Link::Nil,
                   right: Link::Child(Box::new(n25)),
                   value: 23};

    let n9 = Node{left: Link::Child(Box::new(n5)),
                  right: Link::Child(Box::new(n23)),
                  value: 9};

    assert!(!is_valid(&n9));
}

#[test]
fn duplicate_in_left_sub_tree() {
    //                   9
    //                  /
    //                 9
    let leaf = Node{left: Link::Nil, right: Link::Nil, value: 9};
    let root = Node{left: Link::Child(Box::new(leaf)),
                    right: Link::Nil,
                    value: 9};
        assert!(!is_valid(&root));
}

#[test]
fn duplicate_in_right_sub_tree() {
    //               9
    //                \
    //                 9
    let leaf = Node{left: Link::Nil, right: Link::Nil, value: 9};
    let root = Node{left: Link::Nil,
                    right: Link::Child(Box::new(leaf)),
                    value: 9};
        assert!(!is_valid(&root));
}<|endoftext|>


<commit_before><commit_msg>language changes: updated for recent renamings.<commit_after><|endoftext|>