<commit_before>use std::io::Write;
use std::collections::BTreeMap;
use std::cmp::Ordering;
use std::fs::File;

use syn::*;

use bindgen::config;
use bindgen::config::{Config, Language};
use bindgen::directive::*;
use bindgen::items::*;
use bindgen::rust_lib;
use bindgen::syn_helpers::*;
use bindgen::writer::Writer;

pub type ConvertResult<T> = Result<T, String>;
pub type GenerateResult<T> = Result<T, String>;

#[derive(Debug, Copy, Clone, PartialEq)]
pub enum Repr {
    None,
    C,
    U8,
    U16,
    U32,
}

pub type PathRef = String;
#[derive(Debug, Clone)]
pub enum PathValue {
    Enum(Enum),
    Struct(Struct),
    OpaqueStruct(OpaqueStruct),
    Typedef(Typedef),
    Specialization(Specialization),
}
impl PathValue {
    pub fn name(&self) -> &String {
        match self {
            &PathValue::Enum(ref x) => { &x.name },
            &PathValue::Struct(ref x) => { &x.name },
            &PathValue::OpaqueStruct(ref x) => { &x.name },
            &PathValue::Typedef(ref x) => { &x.name },
            &PathValue::Specialization(ref x) => { &x.name },
        }
    }

    pub fn add_deps(&self, library: &Library, out: &mut Vec<PathValue>) {
        match self {
            &PathValue::Enum(_) => { },
            &PathValue::Struct(ref x) => { x.add_deps(library, out); },
            &PathValue::OpaqueStruct(_) => { },
            &PathValue::Typedef(ref x) => { x.add_deps(library, out); },
            &PathValue::Specialization(ref x) => { x.add_deps(library, out); },
        }
    }
}

/// A library collects all of the information needed to generate
/// bindings for a specified rust library. It is turned into a
/// GeneratedLibrary, and in the process filters out unneeded information
/// and in the future will do validation.
#[derive(Debug, Clone)]
pub struct Library<'a> {
    config: &'a Config,

    enums: BTreeMap<String, Enum>,
    structs: BTreeMap<String, Struct>,
    opaque_structs: BTreeMap<String, OpaqueStruct>,
    typedefs: BTreeMap<String, Typedef>,
    specializations: BTreeMap<String, Specialization>,
    functions: BTreeMap<String, Function>,
}

impl<'a> Library<'a> {
    fn blank(config: &'a Config) -> Library<'a> {
        Library {
            config: config,
            enums: BTreeMap::new(),
            structs: BTreeMap::new(),
            opaque_structs: BTreeMap::new(),
            typedefs: BTreeMap::new(),
            specializations: BTreeMap::new(),
            functions: BTreeMap::new(),
        }
    }

    pub fn load(crate_or_src: &str, config: &'a Config) -> Library<'a>
    {
        let mut library = Library::blank(config);

        rust_lib::parse(crate_or_src, &mut |mod_name, items| {
            for item in items {
                match item.node {
                    ItemKind::ForeignMod(ref block) => {
                        if !block.abi.is_c() {
                            info!("skip {}::{} - non c abi extern block", mod_name, &item.ident);
                            continue;
                        }

                        for foreign_item in &block.items {
                            match foreign_item.node {
                                ForeignItemKind::Fn(ref decl,
                                                    ref _generic) => {
                                    let directives = match DirectiveSet::parse(foreign_item.get_doc_attr()) {
                                        Ok(x) => x,
                                        Err(msg) => {
                                            warn!("{}", msg);
                                            DirectiveSet::new()
                                        }
                                    };

                                    match Function::convert(foreign_item.ident.to_string(), directives, decl, true) {
                                        Ok(func) => {
                                            info!("take {}::{}", mod_name, &foreign_item.ident);

                                            library.functions.insert(func.name.clone(), func);
                                        }
                                        Err(msg) => {
                                            info!("skip {}::{} - ({})", mod_name, &foreign_item.ident, msg);
                                        },
                                    }
                                }
                                _ => {}
                            }
                        }
                    }
                    ItemKind::Fn(ref decl,
                                 ref _unsafe,
                                 ref _const,
                                 ref abi,
                                 ref _generic,
                                 ref _block) => {
                        if item.is_no_mangle() && abi.is_c() {
                            let directives = match DirectiveSet::parse(item.get_doc_attr()) {
                                Ok(x) => x,
                                Err(msg) => {
                                    warn!("{}", msg);
                                    DirectiveSet::new()
                                }
                            };

                            match Function::convert(item.ident.to_string(), directives, decl, false) {
                                Ok(func) => {
                                    info!("take {}::{}", mod_name, &item.ident);

                                    library.functions.insert(func.name.clone(), func);
                                }
                                Err(msg) => {
                                    info!("skip {}::{} - ({})", mod_name, &item.ident, msg);
                                },
                            }
                        }
                    }
                    ItemKind::Struct(ref variant,
                                     ref generics) => {
                        let struct_name = item.ident.to_string();
                        let directives = match DirectiveSet::parse(item.get_doc_attr()) {
                            Ok(x) => x,
                            Err(msg) => {
                                warn!("{}", msg);
                                DirectiveSet::new()
                            }
                        };

                        if item.is_repr_c() {
                            match Struct::convert(struct_name.clone(), directives.clone(), variant, generics) {
                                Ok(st) => {
                                    info!("take {}::{}", mod_name, &item.ident);
                                    library.structs.insert(struct_name,
                                                           st);
                                }
                                Err(msg) => {
                                    info!("take {}::{} - opaque ({})", mod_name, &item.ident, msg);
                                    library.opaque_structs.insert(struct_name.clone(),
                                                                  OpaqueStruct::new(struct_name, directives));
                                }
                            }
                        } else {
                            info!("take {}::{} - opaque (not marked as repr(C))", mod_name, &item.ident);
                            library.opaque_structs.insert(struct_name.clone(),
                                                          OpaqueStruct::new(struct_name, directives));
                        }
                    }
                    ItemKind::Enum(ref variants, ref generics) => {
                        if !generics.lifetimes.is_empty() ||
                           !generics.ty_params.is_empty() ||
                           !generics.where_clause.predicates.is_empty() {
                            info!("skip {}::{} - (has generics or lifetimes or where bounds)", mod_name, &item.ident);
                            continue;
                        }

                        let enum_name = item.ident.to_string();
                        let directives = match DirectiveSet::parse(item.get_doc_attr()) {
                            Ok(x) => x,
                            Err(msg) => {
                                warn!("{}", msg);
                                DirectiveSet::new()
                            }
                        };

                        match Enum::convert(enum_name.clone(), item.get_repr(), directives.clone(), variants) {
                            Ok(en) => {
                                info!("take {}::{}", mod_name, &item.ident);
                                library.enums.insert(enum_name, en);
                            }
                            Err(msg) => {
                                info!("take {}::{} - opaque ({})", mod_name, &item.ident, msg);
                                library.opaque_structs.insert(enum_name.clone(),
                                                              OpaqueStruct::new(enum_name, directives));
                            }
                        }
                    }
                    ItemKind::Ty(ref ty, ref generics) => {
                        if !generics.lifetimes.is_empty() ||
                           !generics.ty_params.is_empty() ||
                           !generics.where_clause.predicates.is_empty() {
                            info!("skip {}::{} - (has generics or lifetimes or where bounds)", mod_name, &item.ident);
                            continue;
                        }

                        let alias_name = item.ident.to_string();
                        let directives = match DirectiveSet::parse(item.get_doc_attr()) {
                            Ok(x) => x,
                            Err(msg) => {
                                warn!("{}", msg);
                                DirectiveSet::new()
                            }
                        };

                        let fail1 = match Specialization::convert(alias_name.clone(), directives.clone(), ty) {
                            Ok(spec) => {
                                info!("take {}::{}", mod_name, &item.ident);
                                library.specializations.insert(alias_name, spec);
                                continue;
                            }
                            Err(msg) => msg,
                        };
                        let fail2 = match Typedef::convert(alias_name.clone(), directives, ty) {
                            Ok(typedef) => {
                                info!("take {}::{}", mod_name, &item.ident);
                                library.typedefs.insert(alias_name, typedef);
                                continue;
                            }
                            Err(msg) => msg,
                        };
                        info!("skip {}::{} - ({} and {})", mod_name, &item.ident, fail1, fail2);
                    }
                    _ => {}
                }
            }
        });

        for (_, ref mut s) in &mut library.structs {
            s.resolve(config);
        }
        for (_, ref mut f) in &mut library.functions {
            f.resolve(config);
        }
        for (_, ref mut e) in &mut library.enums {
            e.resolve(config);
        }

        library
    }

    pub fn resolve_path(&self, p: &PathRef) -> Option<PathValue> {
        if let Some(x) = self.enums.get(p) {
            return Some(PathValue::Enum(x.clone()));
        }
        if let Some(x) = self.structs.get(p) {
            return Some(PathValue::Struct(x.clone()));
        }
        if let Some(x) = self.opaque_structs.get(p) {
            return Some(PathValue::OpaqueStruct(x.clone()));
        }
        if let Some(x) = self.typedefs.get(p) {
            return Some(PathValue::Typedef(x.clone()));
        }
        if let Some(x) = self.specializations.get(p) {
            return Some(PathValue::Specialization(x.clone()));
        }

        None
    }

    pub fn add_deps_for_path(&self, p: &PathRef, out: &mut Vec<PathValue>) {
        if let Some(value) = self.resolve_path(p) {
            value.add_deps(self, out);

            if !out.iter().any(|x| x.name() == value.name()) {
                out.push(value);
            }
        } else {
            warn!("can't find {}", p);
        }
    }

    pub fn add_deps_for_path_deps(&self, p: &PathRef, out: &mut Vec<PathValue>) {
        if let Some(value) = self.resolve_path(p) {
            value.add_deps(self, out);
        } else {
            warn!("can't find {}", p);
        }
    }

    pub fn generate(self) -> GenerateResult<GeneratedLibrary<'a>> {
        let mut result = GeneratedLibrary::blank(self.config);

        // Gather only the items that we need for this
        // `extern "c"` interface
        let mut deps = Vec::new();
        for (_, function) in &self.functions {
            function.add_deps(&self, &mut deps);
        }

        // Copy the binding items in dependencies order
        // into the GeneratedLibrary, specializing any type
        // aliases we encounter
        for dep in deps {
            match &dep {
                &PathValue::Struct(ref s) => {
                    if !s.generic_params.is_empty() {
                        continue;
                    }
                }
                &PathValue::Specialization(ref s) => {
                    match s.specialize(self.config, &self) {
                        Ok(value) => {
                            result.items.push(value);
                        }
                        Err(msg) => {
                            warn!("specializing {} failed - ({})", dep.name(), msg);
                        }
                    }
                    continue;
                }
                _ => { }
            }
            result.items.push(dep);
        }

        // Bring the enums all the way to the top because they
        // don't depend on anyone else, and it makes the output
        // nicer
        result.items.sort_by(|a, b| {
            match (a, b) {
                (&PathValue::Enum(ref e1), &PathValue::Enum(ref e2)) => e1.name.cmp(&e2.name),
                (&PathValue::Enum(_), _) => Ordering::Less,
                (_, &PathValue::Enum(_)) => Ordering::Greater,
                _ => Ordering::Equal,
            }
        });

        result.functions = self.functions.iter()
                                         .map(|(_, function)| function.clone())
                                         .collect::<Vec<_>>();

        Ok(result)
    }
}

/// A GeneratedLibrary represents a completed bindings file ready to be printed.
#[derive(Debug, Clone)]
pub struct GeneratedLibrary<'a> {
    config: &'a Config,

    items: Vec<PathValue>,
    functions: Vec<Function>,
}

impl<'a> GeneratedLibrary<'a> {
    fn blank(config: &'a Config) -> GeneratedLibrary<'a> {
        GeneratedLibrary {
            config: config,
            items: Vec::new(),
            functions: Vec::new(),
        }
    }

    pub fn write_to_file(&self, path: &str) {
        self.write(&mut File::create(path).unwrap());
    }

    pub fn write<F: Write>(&self, file: &mut F) {
        let mut out = Writer::new(file, self.config);

        if let Some(ref f) = self.config.header {
            out.new_line_if_not_start();
            out.write(&f);
            out.new_line();
        }
        if let Some(ref f) = self.config.include_guard {
            out.new_line_if_not_start();
            out.write(&format!("#ifndef {}", f));
            out.new_line();
            out.write(&format!("#define {}", f));
            out.new_line();
        }
        if self.config.include_version {
            out.new_line_if_not_start();
            out.write(&format!("/* Generated with cbindgen:{} */", config::VERSION));
            out.new_line();
        }
        if let Some(ref f) = self.config.autogen_warning {
            out.new_line_if_not_start();
            out.write(&f);
            out.new_line();
        }

        out.new_line_if_not_start();
        out.write("#include <stdint.h>");
        out.new_line();

        if self.config.language == Language::Cxx {
            out.new_line_if_not_start();
            out.write("extern \"C\" {");
            out.new_line();
        }

        for item in &self.items {
            out.new_line_if_not_start();
            match item {
                &PathValue::Enum(ref x) => x.write(self.config, &mut out),
                &PathValue::Struct(ref x) => x.write(self.config, &mut out),
                &PathValue::OpaqueStruct(ref x) => x.write(self.config, &mut out),
                &PathValue::Typedef(ref x) => x.write(&mut out),
                &PathValue::Specialization(_) => {
                    panic!("should not encounter a specialization in a built library")
                }
            }
            out.new_line();
        }

        if let Some(ref f) = self.config.autogen_warning {
            out.new_line_if_not_start();
            out.write(&f);
            out.new_line();
        }

        for function in &self.functions {
            if function.extern_decl {
                continue;
            }

            out.new_line_if_not_start();
            function.write(self.config, &mut out);
            out.new_line();
        }

        if self.config.language == Language::Cxx {
            out.new_line_if_not_start();
            out.write("} // extern \"C\"");
            out.new_line();
        }

        if let Some(ref f) = self.config.autogen_warning {
            out.new_line_if_not_start();
            out.write(&f);
            out.new_line();
        }
        if let Some(ref f) = self.config.include_guard {
            out.new_line_if_not_start();
            out.write(&format!("#endif // {}", f));
            out.new_line();
        }
        if let Some(ref f) = self.config.trailer {
            out.new_line_if_not_start();
            out.write(&f);
            out.new_line();
        }
    }
}
<commit_msg>Sort OpaqueStructs above normal Structs<commit_after>use std::io::Write;
use std::collections::BTreeMap;
use std::cmp::Ordering;
use std::fs::File;

use syn::*;

use bindgen::config;
use bindgen::config::{Config, Language};
use bindgen::directive::*;
use bindgen::items::*;
use bindgen::rust_lib;
use bindgen::syn_helpers::*;
use bindgen::writer::Writer;

pub type ConvertResult<T> = Result<T, String>;
pub type GenerateResult<T> = Result<T, String>;

#[derive(Debug, Copy, Clone, PartialEq)]
pub enum Repr {
    None,
    C,
    U8,
    U16,
    U32,
}

pub type PathRef = String;
#[derive(Debug, Clone)]
pub enum PathValue {
    Enum(Enum),
    Struct(Struct),
    OpaqueStruct(OpaqueStruct),
    Typedef(Typedef),
    Specialization(Specialization),
}
impl PathValue {
    pub fn name(&self) -> &String {
        match self {
            &PathValue::Enum(ref x) => { &x.name },
            &PathValue::Struct(ref x) => { &x.name },
            &PathValue::OpaqueStruct(ref x) => { &x.name },
            &PathValue::Typedef(ref x) => { &x.name },
            &PathValue::Specialization(ref x) => { &x.name },
        }
    }

    pub fn add_deps(&self, library: &Library, out: &mut Vec<PathValue>) {
        match self {
            &PathValue::Enum(_) => { },
            &PathValue::Struct(ref x) => { x.add_deps(library, out); },
            &PathValue::OpaqueStruct(_) => { },
            &PathValue::Typedef(ref x) => { x.add_deps(library, out); },
            &PathValue::Specialization(ref x) => { x.add_deps(library, out); },
        }
    }
}

/// A library collects all of the information needed to generate
/// bindings for a specified rust library. It is turned into a
/// GeneratedLibrary, and in the process filters out unneeded information
/// and in the future will do validation.
#[derive(Debug, Clone)]
pub struct Library<'a> {
    config: &'a Config,

    enums: BTreeMap<String, Enum>,
    structs: BTreeMap<String, Struct>,
    opaque_structs: BTreeMap<String, OpaqueStruct>,
    typedefs: BTreeMap<String, Typedef>,
    specializations: BTreeMap<String, Specialization>,
    functions: BTreeMap<String, Function>,
}

impl<'a> Library<'a> {
    fn blank(config: &'a Config) -> Library<'a> {
        Library {
            config: config,
            enums: BTreeMap::new(),
            structs: BTreeMap::new(),
            opaque_structs: BTreeMap::new(),
            typedefs: BTreeMap::new(),
            specializations: BTreeMap::new(),
            functions: BTreeMap::new(),
        }
    }

    pub fn load(crate_or_src: &str, config: &'a Config) -> Library<'a>
    {
        let mut library = Library::blank(config);

        rust_lib::parse(crate_or_src, &mut |mod_name, items| {
            for item in items {
                match item.node {
                    ItemKind::ForeignMod(ref block) => {
                        if !block.abi.is_c() {
                            info!("skip {}::{} - non c abi extern block", mod_name, &item.ident);
                            continue;
                        }

                        for foreign_item in &block.items {
                            match foreign_item.node {
                                ForeignItemKind::Fn(ref decl,
                                                    ref _generic) => {
                                    let directives = match DirectiveSet::parse(foreign_item.get_doc_attr()) {
                                        Ok(x) => x,
                                        Err(msg) => {
                                            warn!("{}", msg);
                                            DirectiveSet::new()
                                        }
                                    };

                                    match Function::convert(foreign_item.ident.to_string(), directives, decl, true) {
                                        Ok(func) => {
                                            info!("take {}::{}", mod_name, &foreign_item.ident);

                                            library.functions.insert(func.name.clone(), func);
                                        }
                                        Err(msg) => {
                                            info!("skip {}::{} - ({})", mod_name, &foreign_item.ident, msg);
                                        },
                                    }
                                }
                                _ => {}
                            }
                        }
                    }
                    ItemKind::Fn(ref decl,
                                 ref _unsafe,
                                 ref _const,
                                 ref abi,
                                 ref _generic,
                                 ref _block) => {
                        if item.is_no_mangle() && abi.is_c() {
                            let directives = match DirectiveSet::parse(item.get_doc_attr()) {
                                Ok(x) => x,
                                Err(msg) => {
                                    warn!("{}", msg);
                                    DirectiveSet::new()
                                }
                            };

                            match Function::convert(item.ident.to_string(), directives, decl, false) {
                                Ok(func) => {
                                    info!("take {}::{}", mod_name, &item.ident);

                                    library.functions.insert(func.name.clone(), func);
                                }
                                Err(msg) => {
                                    info!("skip {}::{} - ({})", mod_name, &item.ident, msg);
                                },
                            }
                        }
                    }
                    ItemKind::Struct(ref variant,
                                     ref generics) => {
                        let struct_name = item.ident.to_string();
                        let directives = match DirectiveSet::parse(item.get_doc_attr()) {
                            Ok(x) => x,
                            Err(msg) => {
                                warn!("{}", msg);
                                DirectiveSet::new()
                            }
                        };

                        if item.is_repr_c() {
                            match Struct::convert(struct_name.clone(), directives.clone(), variant, generics) {
                                Ok(st) => {
                                    info!("take {}::{}", mod_name, &item.ident);
                                    library.structs.insert(struct_name,
                                                           st);
                                }
                                Err(msg) => {
                                    info!("take {}::{} - opaque ({})", mod_name, &item.ident, msg);
                                    library.opaque_structs.insert(struct_name.clone(),
                                                                  OpaqueStruct::new(struct_name, directives));
                                }
                            }
                        } else {
                            info!("take {}::{} - opaque (not marked as repr(C))", mod_name, &item.ident);
                            library.opaque_structs.insert(struct_name.clone(),
                                                          OpaqueStruct::new(struct_name, directives));
                        }
                    }
                    ItemKind::Enum(ref variants, ref generics) => {
                        if !generics.lifetimes.is_empty() ||
                           !generics.ty_params.is_empty() ||
                           !generics.where_clause.predicates.is_empty() {
                            info!("skip {}::{} - (has generics or lifetimes or where bounds)", mod_name, &item.ident);
                            continue;
                        }

                        let enum_name = item.ident.to_string();
                        let directives = match DirectiveSet::parse(item.get_doc_attr()) {
                            Ok(x) => x,
                            Err(msg) => {
                                warn!("{}", msg);
                                DirectiveSet::new()
                            }
                        };

                        match Enum::convert(enum_name.clone(), item.get_repr(), directives.clone(), variants) {
                            Ok(en) => {
                                info!("take {}::{}", mod_name, &item.ident);
                                library.enums.insert(enum_name, en);
                            }
                            Err(msg) => {
                                info!("take {}::{} - opaque ({})", mod_name, &item.ident, msg);
                                library.opaque_structs.insert(enum_name.clone(),
                                                              OpaqueStruct::new(enum_name, directives));
                            }
                        }
                    }
                    ItemKind::Ty(ref ty, ref generics) => {
                        if !generics.lifetimes.is_empty() ||
                           !generics.ty_params.is_empty() ||
                           !generics.where_clause.predicates.is_empty() {
                            info!("skip {}::{} - (has generics or lifetimes or where bounds)", mod_name, &item.ident);
                            continue;
                        }

                        let alias_name = item.ident.to_string();
                        let directives = match DirectiveSet::parse(item.get_doc_attr()) {
                            Ok(x) => x,
                            Err(msg) => {
                                warn!("{}", msg);
                                DirectiveSet::new()
                            }
                        };

                        let fail1 = match Specialization::convert(alias_name.clone(), directives.clone(), ty) {
                            Ok(spec) => {
                                info!("take {}::{}", mod_name, &item.ident);
                                library.specializations.insert(alias_name, spec);
                                continue;
                            }
                            Err(msg) => msg,
                        };
                        let fail2 = match Typedef::convert(alias_name.clone(), directives, ty) {
                            Ok(typedef) => {
                                info!("take {}::{}", mod_name, &item.ident);
                                library.typedefs.insert(alias_name, typedef);
                                continue;
                            }
                            Err(msg) => msg,
                        };
                        info!("skip {}::{} - ({} and {})", mod_name, &item.ident, fail1, fail2);
                    }
                    _ => {}
                }
            }
        });

        for (_, ref mut s) in &mut library.structs {
            s.resolve(config);
        }
        for (_, ref mut f) in &mut library.functions {
            f.resolve(config);
        }
        for (_, ref mut e) in &mut library.enums {
            e.resolve(config);
        }

        library
    }

    pub fn resolve_path(&self, p: &PathRef) -> Option<PathValue> {
        if let Some(x) = self.enums.get(p) {
            return Some(PathValue::Enum(x.clone()));
        }
        if let Some(x) = self.structs.get(p) {
            return Some(PathValue::Struct(x.clone()));
        }
        if let Some(x) = self.opaque_structs.get(p) {
            return Some(PathValue::OpaqueStruct(x.clone()));
        }
        if let Some(x) = self.typedefs.get(p) {
            return Some(PathValue::Typedef(x.clone()));
        }
        if let Some(x) = self.specializations.get(p) {
            return Some(PathValue::Specialization(x.clone()));
        }

        None
    }

    pub fn add_deps_for_path(&self, p: &PathRef, out: &mut Vec<PathValue>) {
        if let Some(value) = self.resolve_path(p) {
            value.add_deps(self, out);

            if !out.iter().any(|x| x.name() == value.name()) {
                out.push(value);
            }
        } else {
            warn!("can't find {}", p);
        }
    }

    pub fn add_deps_for_path_deps(&self, p: &PathRef, out: &mut Vec<PathValue>) {
        if let Some(value) = self.resolve_path(p) {
            value.add_deps(self, out);
        } else {
            warn!("can't find {}", p);
        }
    }

    pub fn generate(self) -> GenerateResult<GeneratedLibrary<'a>> {
        let mut result = GeneratedLibrary::blank(self.config);

        // Gather only the items that we need for this
        // `extern "c"` interface
        let mut deps = Vec::new();
        for (_, function) in &self.functions {
            function.add_deps(&self, &mut deps);
        }

        // Copy the binding items in dependencies order
        // into the GeneratedLibrary, specializing any type
        // aliases we encounter
        for dep in deps {
            match &dep {
                &PathValue::Struct(ref s) => {
                    if !s.generic_params.is_empty() {
                        continue;
                    }
                }
                &PathValue::Specialization(ref s) => {
                    match s.specialize(self.config, &self) {
                        Ok(value) => {
                            result.items.push(value);
                        }
                        Err(msg) => {
                            warn!("specializing {} failed - ({})", dep.name(), msg);
                        }
                    }
                    continue;
                }
                _ => { }
            }
            result.items.push(dep);
        }

        // Sort enums and opaque structs into their own layers because they don't
        // depend on each other or anything else.
        result.items.sort_by(|a, b| {
            match (a, b) {
                (&PathValue::Enum(ref e1), &PathValue::Enum(ref e2)) => e1.name.cmp(&e2.name),
                (&PathValue::Enum(_), _) => Ordering::Less,
                (_, &PathValue::Enum(_)) => Ordering::Greater,

                (&PathValue::OpaqueStruct(ref o1), &PathValue::OpaqueStruct(ref o2)) => o1.name.cmp(&o2.name),
                (&PathValue::OpaqueStruct(_), _) => Ordering::Less,
                (_, &PathValue::OpaqueStruct(_)) => Ordering::Greater,

                _ => Ordering::Equal,
            }
        });

        result.functions = self.functions.iter()
                                         .map(|(_, function)| function.clone())
                                         .collect::<Vec<_>>();

        Ok(result)
    }
}

/// A GeneratedLibrary represents a completed bindings file ready to be printed.
#[derive(Debug, Clone)]
pub struct GeneratedLibrary<'a> {
    config: &'a Config,

    items: Vec<PathValue>,
    functions: Vec<Function>,
}

impl<'a> GeneratedLibrary<'a> {
    fn blank(config: &'a Config) -> GeneratedLibrary<'a> {
        GeneratedLibrary {
            config: config,
            items: Vec::new(),
            functions: Vec::new(),
        }
    }

    pub fn write_to_file(&self, path: &str) {
        self.write(&mut File::create(path).unwrap());
    }

    pub fn write<F: Write>(&self, file: &mut F) {
        let mut out = Writer::new(file, self.config);

        if let Some(ref f) = self.config.header {
            out.new_line_if_not_start();
            out.write(&f);
            out.new_line();
        }
        if let Some(ref f) = self.config.include_guard {
            out.new_line_if_not_start();
            out.write(&format!("#ifndef {}", f));
            out.new_line();
            out.write(&format!("#define {}", f));
            out.new_line();
        }
        if self.config.include_version {
            out.new_line_if_not_start();
            out.write(&format!("/* Generated with cbindgen:{} */", config::VERSION));
            out.new_line();
        }
        if let Some(ref f) = self.config.autogen_warning {
            out.new_line_if_not_start();
            out.write(&f);
            out.new_line();
        }

        out.new_line_if_not_start();
        out.write("#include <stdint.h>");
        out.new_line();

        if self.config.language == Language::Cxx {
            out.new_line_if_not_start();
            out.write("extern \"C\" {");
            out.new_line();
        }

        for item in &self.items {
            out.new_line_if_not_start();
            match item {
                &PathValue::Enum(ref x) => x.write(self.config, &mut out),
                &PathValue::Struct(ref x) => x.write(self.config, &mut out),
                &PathValue::OpaqueStruct(ref x) => x.write(self.config, &mut out),
                &PathValue::Typedef(ref x) => x.write(&mut out),
                &PathValue::Specialization(_) => {
                    panic!("should not encounter a specialization in a built library")
                }
            }
            out.new_line();
        }

        if let Some(ref f) = self.config.autogen_warning {
            out.new_line_if_not_start();
            out.write(&f);
            out.new_line();
        }

        for function in &self.functions {
            if function.extern_decl {
                continue;
            }

            out.new_line_if_not_start();
            function.write(self.config, &mut out);
            out.new_line();
        }

        if self.config.language == Language::Cxx {
            out.new_line_if_not_start();
            out.write("} // extern \"C\"");
            out.new_line();
        }

        if let Some(ref f) = self.config.autogen_warning {
            out.new_line_if_not_start();
            out.write(&f);
            out.new_line();
        }
        if let Some(ref f) = self.config.include_guard {
            out.new_line_if_not_start();
            out.write(&format!("#endif // {}", f));
            out.new_line();
        }
        if let Some(ref f) = self.config.trailer {
            out.new_line_if_not_start();
            out.write(&f);
            out.new_line();
        }
    }
}
<|endoftext|>


<commit_before>
// Std
use std::io::Write;

// Internal
use app::parser::Parser;
use INTERNAL_ERROR_MSG;

pub struct PowerShellGen<'a, 'b>
    where 'a: 'b
{
    p: &'b Parser<'a, 'b>,
}

impl<'a, 'b> PowerShellGen<'a, 'b> {
    pub fn new(p: &'b Parser<'a, 'b>) -> Self { PowerShellGen { p: p } }

    pub fn generate_to<W: Write>(&self, buf: &mut W) {
        let bin_name = self.p.meta.bin_name.as_ref().unwrap();

        let mut names = vec![];
        let (subcommands_detection_cases, subcommands_cases) = generate_inner(self.p, "", &mut names);

        let mut bin_names = vec![bin_name.to_string(), format!("./{0}", bin_name)];
        if cfg!(windows) {
            bin_names.push(format!("{0}.exe", bin_name));
            bin_names.push(format!(r".\{0}", bin_name));
            bin_names.push(format!(r".\{0}.exe", bin_name));
            bin_names.push(format!(r"./{0}.exe", bin_name));
        }

        let bin_names = bin_names.iter().fold(String::new(), |previous, current| {
            format!("{0}, '{1}'", previous, current)
        });
        let bin_names = bin_names.trim_left_matches(", ");

        let result = format!(r#"
@({bin_names}) | %{{
    Register-ArgumentCompleter -Native -CommandName $_ -ScriptBlock {{
        param($wordToComplete, $commandAst, $cursorPosition)

        $command = '_{bin_name}'
        $commandAst.CommandElements |
            Select-Object -Skip 1 |
            %{{
                switch ($_.ToString()) {{
{subcommands_detection_cases}
                    default {{
                        break
                    }}
                }}
            }}

        $completions = @()

        switch ($command) {{
{subcommands_cases}
        }}

        $completions |
            ?{{ $_ -like "$wordToComplete*" }} |
            Sort-Object |
            %{{ New-Object System.Management.Automation.CompletionResult $_, $_, 'ParameterValue', $_ }}
    }}
}}
"#,
            bin_names = bin_names,
            bin_name = bin_name,
            subcommands_detection_cases = subcommands_detection_cases,
            subcommands_cases = subcommands_cases
        );

        w!(buf, result.as_bytes());
    }
}

fn generate_inner<'a, 'b, 'p>(p: &'p Parser<'a, 'b>, previous_command_name: &str, names: &mut Vec<&'p str>) -> (String, String) {
    debugln!("PowerShellGen::generate_inner;");
    let command_name = if previous_command_name.is_empty() {
        format!("{}_{}", previous_command_name, &p.meta.bin_name.as_ref().expect(INTERNAL_ERROR_MSG))
    } else {
        format!("{}_{}", previous_command_name, &p.meta.name)
    };

    let mut subcommands_detection_cases = if previous_command_name.is_empty() {
        String::new()
    } else if !names.contains(&&*p.meta.name) {
        names.push(&*p.meta.name);
        format!(r"
                    '{0}' {{
                        $command += '_{0}'
                        break
                    }}
",
                &p.meta.name)
    } else {
        String::new()
    };

    let mut completions = String::new();
    for subcommand in &p.subcommands {
        completions.push_str(&format!("'{}', ", &subcommand.p.meta.name));
    }
    for short in shorts!(p) {
        completions.push_str(&format!("'-{}', ", short));
    }
    for long in longs!(p) {
        completions.push_str(&format!("'--{}', ", long));
    }

    let mut subcommands_cases = format!(r"
            '{}' {{
                $completions = @({})
            }}
",
                                        &command_name,
                                        completions.trim_right_matches(", "));

    for subcommand in &p.subcommands {
        let (subcommand_subcommands_detection_cases, subcommand_subcommands_cases) =
            generate_inner(&subcommand.p, &command_name, names);
        subcommands_detection_cases.push_str(&subcommand_subcommands_detection_cases);
        subcommands_cases.push_str(&subcommand_subcommands_cases);
    }

    (subcommands_detection_cases, subcommands_cases)
}
<commit_msg>clippy: if_same_then_else<commit_after>
// Std
use std::io::Write;

// Internal
use app::parser::Parser;
use INTERNAL_ERROR_MSG;

pub struct PowerShellGen<'a, 'b>
    where 'a: 'b
{
    p: &'b Parser<'a, 'b>,
}

impl<'a, 'b> PowerShellGen<'a, 'b> {
    pub fn new(p: &'b Parser<'a, 'b>) -> Self { PowerShellGen { p: p } }

    pub fn generate_to<W: Write>(&self, buf: &mut W) {
        let bin_name = self.p.meta.bin_name.as_ref().unwrap();

        let mut names = vec![];
        let (subcommands_detection_cases, subcommands_cases) = generate_inner(self.p, "", &mut names);

        let mut bin_names = vec![bin_name.to_string(), format!("./{0}", bin_name)];
        if cfg!(windows) {
            bin_names.push(format!("{0}.exe", bin_name));
            bin_names.push(format!(r".\{0}", bin_name));
            bin_names.push(format!(r".\{0}.exe", bin_name));
            bin_names.push(format!(r"./{0}.exe", bin_name));
        }

        let bin_names = bin_names.iter().fold(String::new(), |previous, current| {
            format!("{0}, '{1}'", previous, current)
        });
        let bin_names = bin_names.trim_left_matches(", ");

        let result = format!(r#"
@({bin_names}) | %{{
    Register-ArgumentCompleter -Native -CommandName $_ -ScriptBlock {{
        param($wordToComplete, $commandAst, $cursorPosition)

        $command = '_{bin_name}'
        $commandAst.CommandElements |
            Select-Object -Skip 1 |
            %{{
                switch ($_.ToString()) {{
{subcommands_detection_cases}
                    default {{
                        break
                    }}
                }}
            }}

        $completions = @()

        switch ($command) {{
{subcommands_cases}
        }}

        $completions |
            ?{{ $_ -like "$wordToComplete*" }} |
            Sort-Object |
            %{{ New-Object System.Management.Automation.CompletionResult $_, $_, 'ParameterValue', $_ }}
    }}
}}
"#,
            bin_names = bin_names,
            bin_name = bin_name,
            subcommands_detection_cases = subcommands_detection_cases,
            subcommands_cases = subcommands_cases
        );

        w!(buf, result.as_bytes());
    }
}

fn generate_inner<'a, 'b, 'p>(p: &'p Parser<'a, 'b>, previous_command_name: &str, names: &mut Vec<&'p str>) -> (String, String) {
    debugln!("PowerShellGen::generate_inner;");
    let command_name = if previous_command_name.is_empty() {
        format!("{}_{}", previous_command_name, &p.meta.bin_name.as_ref().expect(INTERNAL_ERROR_MSG))
    } else {
        format!("{}_{}", previous_command_name, &p.meta.name)
    };

    let mut subcommands_detection_cases = if !names.contains(&&*p.meta.name) {
        names.push(&*p.meta.name);
        format!(r"
                    '{0}' {{
                        $command += '_{0}'
                        break
                    }}
",
                &p.meta.name)
    } else {
        String::new()
    };

    let mut completions = String::new();
    for subcommand in &p.subcommands {
        completions.push_str(&format!("'{}', ", &subcommand.p.meta.name));
    }
    for short in shorts!(p) {
        completions.push_str(&format!("'-{}', ", short));
    }
    for long in longs!(p) {
        completions.push_str(&format!("'--{}', ", long));
    }

    let mut subcommands_cases = format!(r"
            '{}' {{
                $completions = @({})
            }}
",
                                        &command_name,
                                        completions.trim_right_matches(", "));

    for subcommand in &p.subcommands {
        let (subcommand_subcommands_detection_cases, subcommand_subcommands_cases) =
            generate_inner(&subcommand.p, &command_name, names);
        subcommands_detection_cases.push_str(&subcommand_subcommands_detection_cases);
        subcommands_cases.push_str(&subcommand_subcommands_cases);
    }

    (subcommands_detection_cases, subcommands_cases)
}
<|endoftext|>


<commit_before>//! Main entry point to the library.
//! See examples for documentation on how to use this struct.

use libc;
use std::{env, ptr, any::Any, cell::UnsafeCell, ffi::CStr};

use {DataDeviceManager, SurfaceHandle};
use extensions::server_decoration::ServerDecorationManager;
use manager::{InputManager, InputManagerHandler, OutputManager, OutputManagerHandler,
              WlShellManager, WlShellManagerHandler, XdgV6ShellManager, XdgV6ShellManagerHandler};
use render::GenericRenderer;

use wayland_sys::server::{wl_display, wl_event_loop, signal::wl_signal_add, WAYLAND_SERVER_HANDLE};
use wlroots_sys::{wlr_backend, wlr_backend_autocreate, wlr_backend_destroy, wlr_backend_start,
                  wlr_compositor, wlr_compositor_create, wlr_compositor_destroy, wlr_wl_shell,
                  wlr_wl_shell_create, wlr_xdg_shell_v6, wlr_xdg_shell_v6_create};
use wlroots_sys::wayland_server::sys::wl_display_init_shm;

/// Global compositor pointer, used to refer to the compositor state unsafely.
pub static mut COMPOSITOR_PTR: *mut Compositor = 0 as *mut _;

pub trait CompositorHandler {
    /// Callback that's triggered when a surface is provided to the compositor.
    fn new_surface(&mut self, &mut Compositor, &mut SurfaceHandle) {}

    /// Callback that's triggered during shutdown.
    fn on_shutdown(&mut self) {}
}

wayland_listener!(InternalCompositor, Box<CompositorHandler>, [
    new_surface_listener => new_surface_notify: |this: &mut InternalCompositor,
                                                 surface: *mut libc::c_void,|
    unsafe {
        let handler = &mut this.data;
        let compositor = &mut *COMPOSITOR_PTR;
        let mut surface = SurfaceHandle::from_ptr(surface as _);
        handler.new_surface(compositor, &mut surface);
    };
    shutdown_listener => shutdown_notify: |this: &mut InternalCompositor,
                                           _data: *mut libc::c_void,|
    unsafe {
        let handler = &mut this.data;
        assert!(COMPOSITOR_PTR.is_null(), "COMPOSITOR_PTR was not NULL!");
        handler.on_shutdown();
    };
]);

#[allow(dead_code)]
pub struct Compositor {
    /// User data.
    pub data: Box<Any>,
    /// Internal compositor handler
    compositor_handler: Option<Box<InternalCompositor>>,
    /// Manager for the inputs.
    input_manager: Option<Box<InputManager>>,
    /// Manager for the outputs.
    output_manager: Option<Box<OutputManager>>,
    /// Manager for Wayland shells.
    wl_shell_manager: Option<Box<WlShellManager>>,
    /// Manager for XDG shells v6.
    xdg_v6_shell_manager: Option<Box<XdgV6ShellManager>>,
    /// Pointer to wl_shell global.
    /// If wl_shell_manager is `None`, this value will be `NULL`.
    wl_shell_global: *mut wlr_wl_shell,
    /// Pointer to the xdg_shell_v6 global.
    /// If xdg_v6_shell_manager is `None`, this value will be `NULL`.
    xdg_v6_shell_global: *mut wlr_xdg_shell_v6,
    /// Pointer to the wlr_compositor.
    compositor: *mut wlr_compositor,
    /// Pointer to the wlroots backend in use.
    backend: *mut wlr_backend,
    /// Pointer to the wayland display.
    display: *mut wl_display,
    /// Pointer to the event loop.
    event_loop: *mut wl_event_loop,
    /// Shared memory buffer file descriptor.
    shm_fd: i32,
    /// Name of the Wayland socket that we are binding to.
    socket_name: String,
    /// Optional decoration manager extension.
    pub server_decoration_manager: Option<ServerDecorationManager>,
    /// The renderer used to draw things to the screen.
    pub renderer: Option<GenericRenderer>,
    /// The DnD manager
    data_device_manager: Option<DataDeviceManager>,
    /// The error from the panic, if there was one.
    panic_error: Option<Box<Any + Send>>
}

pub struct CompositorBuilder {
    compositor_handler: Option<Box<CompositorHandler>>,
    input_manager_handler: Option<Box<InputManagerHandler>>,
    output_manager_handler: Option<Box<OutputManagerHandler>>,
    wl_shell_manager_handler: Option<Box<WlShellManagerHandler>>,
    xdg_v6_shell_manager_handler: Option<Box<XdgV6ShellManagerHandler>>,
    gles2: bool,
    server_decoration_manager: bool,
    data_device_manager: bool
}

impl CompositorBuilder {
    /// Make a new compositor builder.
    ///
    /// Unless otherwise noted, each option is `false`/`None`.
    pub fn new() -> Self {
        CompositorBuilder { gles2: false,
                            server_decoration_manager: false,
                            data_device_manager: false,
                            compositor_handler: None,
                            input_manager_handler: None,
                            output_manager_handler: None,
                            wl_shell_manager_handler: None,
                            xdg_v6_shell_manager_handler: None }
    }

    /// Set the handler for global compositor callbacks.
    pub fn compositor_handler(mut self, compositor_handler: Box<CompositorHandler>) -> Self {
        self.compositor_handler = Some(compositor_handler);
        self
    }

    /// Set the handler for inputs.
    pub fn input_manager(mut self, input_manager_handler: Box<InputManagerHandler>) -> Self {
        self.input_manager_handler = Some(input_manager_handler);
        self
    }

    /// Set the handler for outputs.
    pub fn output_manager(mut self, output_manager_handler: Box<OutputManagerHandler>) -> Self {
        self.output_manager_handler = Some(output_manager_handler);
        self
    }

    /// Set the handler for Wayland shells.
    pub fn wl_shell_manager(mut self,
                            wl_shell_manager_handler: Box<WlShellManagerHandler>)
                            -> Self {
        self.wl_shell_manager_handler = Some(wl_shell_manager_handler);
        self
    }

    /// Set the handler for xdg v6 shells.
    pub fn xdg_shell_v6_manager(mut self,
                                xdg_v6_shell_manager_handler: Box<XdgV6ShellManagerHandler>)
                                -> Self {
        self.xdg_v6_shell_manager_handler = Some(xdg_v6_shell_manager_handler);
        self
    }

    /// Decide whether or not to enable the data device manager.
    ///
    /// This is used to do DnD, or "drag 'n drop" copy paste.
    pub fn data_device(mut self, data_device_manager: bool) -> Self {
        self.data_device_manager = data_device_manager;
        self
    }

    /// Decide whether or not to enable the GLES2 extension.
    pub fn gles2(mut self, gles2_renderer: bool) -> Self {
        self.gles2 = gles2_renderer;
        self
    }

    /// Decide whether or not to enable the server decoration manager protocol
    /// extension.
    pub fn server_decoration_manager(mut self, server_decoration_manager: bool) -> Self {
        self.server_decoration_manager = server_decoration_manager;
        self
    }

    /// Makes a new compositor that handles the setup of the graphical backend
    /// (e.g, Wayland, X11, or DRM).
    ///
    /// Also automatically opens the socket for clients to communicate to the
    /// compositor with.
    pub fn build_auto<D>(self, data: D) -> Compositor
        where D: Any + 'static
    {
        unsafe {
            let display =
                ffi_dispatch!(WAYLAND_SERVER_HANDLE, wl_display_create,) as *mut wl_display;
            let event_loop =
                ffi_dispatch!(WAYLAND_SERVER_HANDLE, wl_display_get_event_loop, display);
            let backend = wlr_backend_autocreate(display as *mut _);
            if backend.is_null() {
                // NOTE Rationale for panicking:
                // * Won't be in C land just yet, so it's safe to panic
                // * Can always be returned in a Result instead, but for now
                //   if you auto create it's assumed you can't recover.
                panic!("Could not auto-create backend");
            }
            // Set up shared memory buffer for Wayland clients.
            let shm_fd = wl_display_init_shm(display as *mut _);
            // Create optional extensions.
            let server_decoration_manager = if self.server_decoration_manager {
                ServerDecorationManager::new(display)
            } else {
                None
            };
            let data_device_manager = if self.data_device_manager {
                DataDeviceManager::new(display as _)
            } else {
                None
            };
            let compositor;
            let renderer = if self.gles2 {
                let gles2 = GenericRenderer::gles2_renderer(backend);
                // Set up wlr_compositor
                let gles2_ptr = gles2.as_ptr();
                compositor = wlr_compositor_create(display as *mut _, gles2_ptr);
                Some(gles2)
            } else {
                compositor = wlr_compositor_create(display as *mut _, ptr::null_mut());
                None
            };

            // Set up compositor handler, if the user provided it.
            let compositor_handler = self.compositor_handler.map(|handler| {
                let mut compositor_handler = InternalCompositor::new(handler);
                wl_signal_add(&mut (*compositor).events.new_surface as *mut _ as _,
                              compositor_handler.new_surface_listener() as *mut _ as _);
                wl_signal_add(&mut (*compositor).events.destroy as *mut _ as _,
                              compositor_handler.shutdown_listener() as *mut _ as _);
                compositor_handler
            });

            // Set up input manager, if the user provided it.
            let input_manager = self.input_manager_handler.map(|handler| {
                let mut input_manager = InputManager::new((vec![], handler));
                wl_signal_add(&mut (*backend).events.new_input as *mut _ as _,
                              input_manager.add_listener() as *mut _ as _);
                input_manager
            });

            // Set up output manager, if the user provided it.
            let output_manager = self.output_manager_handler.map(|handler| {
                let mut output_manager = OutputManager::new((vec![], handler));
                wl_signal_add(&mut (*backend).events.new_output as *mut _ as _,
                              output_manager.add_listener() as *mut _ as _);
                output_manager
            });

            // Set up wl_shell handler and associated Wayland global,
            // if user provided a manager for it.
            let mut wl_shell_global = ptr::null_mut();
            let wl_shell_manager = self.wl_shell_manager_handler.map(|handler| {
                wl_shell_global = wlr_wl_shell_create(display as *mut _);
                let mut wl_shell_manager = WlShellManager::new(handler);
                wl_signal_add(&mut (*wl_shell_global).events.new_surface as *mut _ as _,
                              wl_shell_manager.add_listener() as *mut _ as _);
                wl_shell_manager
            });

            // Set up the xdg_shell_v6 handler and associated Wayland global,
            // if user provided a manager for it.
            let mut xdg_v6_shell_global = ptr::null_mut();
            let xdg_v6_shell_manager = self.xdg_v6_shell_manager_handler.map(|handler| {
                xdg_v6_shell_global = wlr_xdg_shell_v6_create(display as *mut _);
                let mut xdg_v6_shell_manager = XdgV6ShellManager::new((vec![], handler));
                wl_signal_add(&mut (*xdg_v6_shell_global).events.new_surface as *mut _ as _,
                              xdg_v6_shell_manager.add_listener() as *mut _ as _);
                xdg_v6_shell_manager
            });

            // Open the socket to the Wayland server.
            let socket = ffi_dispatch!(WAYLAND_SERVER_HANDLE, wl_display_add_socket_auto, display);
            if socket.is_null() {
                // NOTE Rationale for panicking:
                // * Won't be in C land just yet, so it's safe to panic
                // * Can always be returned in a Result instead, but for now
                //   if you auto create it's assumed you can't recover.
                panic!("Unable to open wayland socket");
            }
            let socket_name = CStr::from_ptr(socket).to_string_lossy().into_owned();
            wlr_log!(L_DEBUG,
                     "Running compositor on wayland display {}",
                     socket_name);
            env::set_var("_WAYLAND_DISPLAY", socket_name.clone());
            Compositor { data: Box::new(data),
                         compositor_handler,
                         socket_name,
                         input_manager,
                         output_manager,
                         wl_shell_manager,
                         wl_shell_global,
                         xdg_v6_shell_manager,
                         xdg_v6_shell_global,
                         data_device_manager,
                         compositor,
                         backend,
                         display,
                         event_loop,
                         shm_fd,
                         server_decoration_manager,
                         renderer,
                         panic_error: None }
        }
    }
}

impl Compositor {
    /// Enters the wayland event loop. Won't return until the compositor is
    /// shut off
    pub fn run(self) {
        unsafe {
            let compositor = UnsafeCell::new(self);
            if COMPOSITOR_PTR != 0 as _ {
                // NOTE Rationale for panicking:
                // * Nicer than an abort
                // * Not yet in C land
                panic!("A compositor is already running!")
            }
            COMPOSITOR_PTR = compositor.get();
            wlr_log!(L_INFO, "Starting compositor");
            if !wlr_backend_start((*compositor.get()).backend) {
                wlr_backend_destroy((*compositor.get()).backend);
                // NOTE Rationale for panicking:
                // * Won't be in C land just yet, so it's safe to panic
                // * Can always be returned in a Result instead, but for now
                //   if you auto create it's assumed you can't recover.
                panic!("Failed to start backend");
            }
            env::set_var("WAYLAND_DISPLAY", (*COMPOSITOR_PTR).socket_name.clone());
            ffi_dispatch!(WAYLAND_SERVER_HANDLE,
                          wl_display_run,
                          (*compositor.get()).display);
            match (*compositor.get()).panic_error.take() {
                None => {}
                Some(err) => {
                    // A panic occured, now we can re-throw it safely.
                    ::std::panic::resume_unwind(err)
                }
            }
        }
    }

    pub fn terminate(&mut self) {
        unsafe {
            COMPOSITOR_PTR = 0 as _;
            ffi_dispatch!(WAYLAND_SERVER_HANDLE, wl_display_terminate, self.display);
        }
    }

    pub unsafe fn display(&self) -> *mut wl_display {
        self.display
    }

    pub unsafe fn event_loop(&self) -> *mut wl_event_loop {
        self.event_loop
    }

    /// Saves the panic error information in the compositor, to be re-thrown
    /// later when we are out of the C callback stack.
    pub(crate) fn save_panic_error(&mut self, error: Box<Any + Send>) {
        self.panic_error = Some(error);
    }
}

impl Drop for Compositor {
    fn drop(&mut self) {
        unsafe { wlr_compositor_destroy(self.compositor) }
    }
}

/// Terminates the compositor.
/// If one is not running, does nothing
pub fn terminate() {
    unsafe {
        if COMPOSITOR_PTR != 0 as _ {
            (*COMPOSITOR_PTR).terminate();
            COMPOSITOR_PTR = 0 as _
        }
    }
}
<commit_msg>Fixed safety hole in termination<commit_after>//! Main entry point to the library.
//! See examples for documentation on how to use this struct.

use libc;
use std::{env, ptr, any::Any, cell::UnsafeCell, ffi::CStr};

use {DataDeviceManager, SurfaceHandle};
use extensions::server_decoration::ServerDecorationManager;
use manager::{InputManager, InputManagerHandler, OutputManager, OutputManagerHandler,
              WlShellManager, WlShellManagerHandler, XdgV6ShellManager, XdgV6ShellManagerHandler};
use render::GenericRenderer;

use wayland_sys::server::{wl_display, wl_event_loop, signal::wl_signal_add, WAYLAND_SERVER_HANDLE};
use wlroots_sys::{wlr_backend, wlr_backend_autocreate, wlr_backend_destroy, wlr_backend_start,
                  wlr_compositor, wlr_compositor_create, wlr_compositor_destroy, wlr_wl_shell,
                  wlr_wl_shell_create, wlr_xdg_shell_v6, wlr_xdg_shell_v6_create};
use wlroots_sys::wayland_server::sys::wl_display_init_shm;

/// Global compositor pointer, used to refer to the compositor state unsafely.
pub static mut COMPOSITOR_PTR: *mut Compositor = 0 as *mut _;

pub trait CompositorHandler {
    /// Callback that's triggered when a surface is provided to the compositor.
    fn new_surface(&mut self, &mut Compositor, &mut SurfaceHandle) {}

    /// Callback that's triggered during shutdown.
    fn on_shutdown(&mut self) {}
}

wayland_listener!(InternalCompositor, Box<CompositorHandler>, [
    new_surface_listener => new_surface_notify: |this: &mut InternalCompositor,
                                                 surface: *mut libc::c_void,|
    unsafe {
        let handler = &mut this.data;
        let compositor = &mut *COMPOSITOR_PTR;
        let mut surface = SurfaceHandle::from_ptr(surface as _);
        handler.new_surface(compositor, &mut surface);
    };
    shutdown_listener => shutdown_notify: |this: &mut InternalCompositor,
                                           _data: *mut libc::c_void,|
    unsafe {
        let handler = &mut this.data;
        assert!(COMPOSITOR_PTR.is_null(), "COMPOSITOR_PTR was not NULL!");
        handler.on_shutdown();
    };
]);

#[allow(dead_code)]
pub struct Compositor {
    terminating: bool,
    /// User data.
    pub data: Box<Any>,
    /// Internal compositor handler
    compositor_handler: Option<Box<InternalCompositor>>,
    /// Manager for the inputs.
    input_manager: Option<Box<InputManager>>,
    /// Manager for the outputs.
    output_manager: Option<Box<OutputManager>>,
    /// Manager for Wayland shells.
    wl_shell_manager: Option<Box<WlShellManager>>,
    /// Manager for XDG shells v6.
    xdg_v6_shell_manager: Option<Box<XdgV6ShellManager>>,
    /// Pointer to wl_shell global.
    /// If wl_shell_manager is `None`, this value will be `NULL`.
    wl_shell_global: *mut wlr_wl_shell,
    /// Pointer to the xdg_shell_v6 global.
    /// If xdg_v6_shell_manager is `None`, this value will be `NULL`.
    xdg_v6_shell_global: *mut wlr_xdg_shell_v6,
    /// Pointer to the wlr_compositor.
    compositor: *mut wlr_compositor,
    /// Pointer to the wlroots backend in use.
    backend: *mut wlr_backend,
    /// Pointer to the wayland display.
    display: *mut wl_display,
    /// Pointer to the event loop.
    event_loop: *mut wl_event_loop,
    /// Shared memory buffer file descriptor.
    shm_fd: i32,
    /// Name of the Wayland socket that we are binding to.
    socket_name: String,
    /// Optional decoration manager extension.
    pub server_decoration_manager: Option<ServerDecorationManager>,
    /// The renderer used to draw things to the screen.
    pub renderer: Option<GenericRenderer>,
    /// The DnD manager
    data_device_manager: Option<DataDeviceManager>,
    /// The error from the panic, if there was one.
    panic_error: Option<Box<Any + Send>>
}

pub struct CompositorBuilder {
    compositor_handler: Option<Box<CompositorHandler>>,
    input_manager_handler: Option<Box<InputManagerHandler>>,
    output_manager_handler: Option<Box<OutputManagerHandler>>,
    wl_shell_manager_handler: Option<Box<WlShellManagerHandler>>,
    xdg_v6_shell_manager_handler: Option<Box<XdgV6ShellManagerHandler>>,
    gles2: bool,
    server_decoration_manager: bool,
    data_device_manager: bool
}

impl CompositorBuilder {
    /// Make a new compositor builder.
    ///
    /// Unless otherwise noted, each option is `false`/`None`.
    pub fn new() -> Self {
        CompositorBuilder { gles2: false,
                            server_decoration_manager: false,
                            data_device_manager: false,
                            compositor_handler: None,
                            input_manager_handler: None,
                            output_manager_handler: None,
                            wl_shell_manager_handler: None,
                            xdg_v6_shell_manager_handler: None }
    }

    /// Set the handler for global compositor callbacks.
    pub fn compositor_handler(mut self, compositor_handler: Box<CompositorHandler>) -> Self {
        self.compositor_handler = Some(compositor_handler);
        self
    }

    /// Set the handler for inputs.
    pub fn input_manager(mut self, input_manager_handler: Box<InputManagerHandler>) -> Self {
        self.input_manager_handler = Some(input_manager_handler);
        self
    }

    /// Set the handler for outputs.
    pub fn output_manager(mut self, output_manager_handler: Box<OutputManagerHandler>) -> Self {
        self.output_manager_handler = Some(output_manager_handler);
        self
    }

    /// Set the handler for Wayland shells.
    pub fn wl_shell_manager(mut self,
                            wl_shell_manager_handler: Box<WlShellManagerHandler>)
                            -> Self {
        self.wl_shell_manager_handler = Some(wl_shell_manager_handler);
        self
    }

    /// Set the handler for xdg v6 shells.
    pub fn xdg_shell_v6_manager(mut self,
                                xdg_v6_shell_manager_handler: Box<XdgV6ShellManagerHandler>)
                                -> Self {
        self.xdg_v6_shell_manager_handler = Some(xdg_v6_shell_manager_handler);
        self
    }

    /// Decide whether or not to enable the data device manager.
    ///
    /// This is used to do DnD, or "drag 'n drop" copy paste.
    pub fn data_device(mut self, data_device_manager: bool) -> Self {
        self.data_device_manager = data_device_manager;
        self
    }

    /// Decide whether or not to enable the GLES2 extension.
    pub fn gles2(mut self, gles2_renderer: bool) -> Self {
        self.gles2 = gles2_renderer;
        self
    }

    /// Decide whether or not to enable the server decoration manager protocol
    /// extension.
    pub fn server_decoration_manager(mut self, server_decoration_manager: bool) -> Self {
        self.server_decoration_manager = server_decoration_manager;
        self
    }

    /// Makes a new compositor that handles the setup of the graphical backend
    /// (e.g, Wayland, X11, or DRM).
    ///
    /// Also automatically opens the socket for clients to communicate to the
    /// compositor with.
    pub fn build_auto<D>(self, data: D) -> Compositor
        where D: Any + 'static
    {
        unsafe {
            let display =
                ffi_dispatch!(WAYLAND_SERVER_HANDLE, wl_display_create,) as *mut wl_display;
            let event_loop =
                ffi_dispatch!(WAYLAND_SERVER_HANDLE, wl_display_get_event_loop, display);
            let backend = wlr_backend_autocreate(display as *mut _);
            if backend.is_null() {
                // NOTE Rationale for panicking:
                // * Won't be in C land just yet, so it's safe to panic
                // * Can always be returned in a Result instead, but for now
                //   if you auto create it's assumed you can't recover.
                panic!("Could not auto-create backend");
            }
            // Set up shared memory buffer for Wayland clients.
            let shm_fd = wl_display_init_shm(display as *mut _);
            // Create optional extensions.
            let server_decoration_manager = if self.server_decoration_manager {
                ServerDecorationManager::new(display)
            } else {
                None
            };
            let data_device_manager = if self.data_device_manager {
                DataDeviceManager::new(display as _)
            } else {
                None
            };
            let compositor;
            let renderer = if self.gles2 {
                let gles2 = GenericRenderer::gles2_renderer(backend);
                // Set up wlr_compositor
                let gles2_ptr = gles2.as_ptr();
                compositor = wlr_compositor_create(display as *mut _, gles2_ptr);
                Some(gles2)
            } else {
                compositor = wlr_compositor_create(display as *mut _, ptr::null_mut());
                None
            };

            // Set up compositor handler, if the user provided it.
            let compositor_handler = self.compositor_handler.map(|handler| {
                let mut compositor_handler = InternalCompositor::new(handler);
                wl_signal_add(&mut (*compositor).events.new_surface as *mut _ as _,
                              compositor_handler.new_surface_listener() as *mut _ as _);
                wl_signal_add(&mut (*compositor).events.destroy as *mut _ as _,
                              compositor_handler.shutdown_listener() as *mut _ as _);
                compositor_handler
            });

            // Set up input manager, if the user provided it.
            let input_manager = self.input_manager_handler.map(|handler| {
                let mut input_manager = InputManager::new((vec![], handler));
                wl_signal_add(&mut (*backend).events.new_input as *mut _ as _,
                              input_manager.add_listener() as *mut _ as _);
                input_manager
            });

            // Set up output manager, if the user provided it.
            let output_manager = self.output_manager_handler.map(|handler| {
                let mut output_manager = OutputManager::new((vec![], handler));
                wl_signal_add(&mut (*backend).events.new_output as *mut _ as _,
                              output_manager.add_listener() as *mut _ as _);
                output_manager
            });

            // Set up wl_shell handler and associated Wayland global,
            // if user provided a manager for it.
            let mut wl_shell_global = ptr::null_mut();
            let wl_shell_manager = self.wl_shell_manager_handler.map(|handler| {
                wl_shell_global = wlr_wl_shell_create(display as *mut _);
                let mut wl_shell_manager = WlShellManager::new(handler);
                wl_signal_add(&mut (*wl_shell_global).events.new_surface as *mut _ as _,
                              wl_shell_manager.add_listener() as *mut _ as _);
                wl_shell_manager
            });

            // Set up the xdg_shell_v6 handler and associated Wayland global,
            // if user provided a manager for it.
            let mut xdg_v6_shell_global = ptr::null_mut();
            let xdg_v6_shell_manager = self.xdg_v6_shell_manager_handler.map(|handler| {
                xdg_v6_shell_global = wlr_xdg_shell_v6_create(display as *mut _);
                let mut xdg_v6_shell_manager = XdgV6ShellManager::new((vec![], handler));
                wl_signal_add(&mut (*xdg_v6_shell_global).events.new_surface as *mut _ as _,
                              xdg_v6_shell_manager.add_listener() as *mut _ as _);
                xdg_v6_shell_manager
            });

            // Open the socket to the Wayland server.
            let socket = ffi_dispatch!(WAYLAND_SERVER_HANDLE, wl_display_add_socket_auto, display);
            if socket.is_null() {
                // NOTE Rationale for panicking:
                // * Won't be in C land just yet, so it's safe to panic
                // * Can always be returned in a Result instead, but for now
                //   if you auto create it's assumed you can't recover.
                panic!("Unable to open wayland socket");
            }
            let socket_name = CStr::from_ptr(socket).to_string_lossy().into_owned();
            wlr_log!(L_DEBUG,
                     "Running compositor on wayland display {}",
                     socket_name);
            env::set_var("_WAYLAND_DISPLAY", socket_name.clone());
            Compositor { data: Box::new(data),
                         terminating: false,
                         compositor_handler,
                         socket_name,
                         input_manager,
                         output_manager,
                         wl_shell_manager,
                         wl_shell_global,
                         xdg_v6_shell_manager,
                         xdg_v6_shell_global,
                         data_device_manager,
                         compositor,
                         backend,
                         display,
                         event_loop,
                         shm_fd,
                         server_decoration_manager,
                         renderer,
                         panic_error: None }
        }
    }
}

impl Compositor {
    /// Enters the wayland event loop. Won't return until the compositor is
    /// shut off
    pub fn run(self) {
        unsafe {
            let compositor = UnsafeCell::new(self);
            if COMPOSITOR_PTR != 0 as _ {
                // NOTE Rationale for panicking:
                // * Nicer than an abort
                // * Not yet in C land
                panic!("A compositor is already running!")
            }
            COMPOSITOR_PTR = compositor.get();
            wlr_log!(L_INFO, "Starting compositor");
            if !wlr_backend_start((*compositor.get()).backend) {
                wlr_backend_destroy((*compositor.get()).backend);
                // NOTE Rationale for panicking:
                // * Won't be in C land just yet, so it's safe to panic
                // * Can always be returned in a Result instead, but for now
                //   if you auto create it's assumed you can't recover.
                panic!("Failed to start backend");
            }
            env::set_var("WAYLAND_DISPLAY", (*COMPOSITOR_PTR).socket_name.clone());
            ffi_dispatch!(WAYLAND_SERVER_HANDLE,
                          wl_display_run,
                          (*compositor.get()).display);
            if (*compositor.get()).terminating {
                return
            }
            match (*compositor.get()).panic_error.take() {
                None => {}
                Some(err) => {
                    // A panic occured, now we can re-throw it safely.
                    ::std::panic::resume_unwind(err)
                }
            }
        }
    }

    pub fn terminate(&mut self) -> ! {
        unsafe {
            self.terminating = true;
            COMPOSITOR_PTR = 0 as _;
            ffi_dispatch!(WAYLAND_SERVER_HANDLE, wl_display_terminate, self.display);
            panic!("terminating gracefully");
        }
    }

    pub unsafe fn display(&self) -> *mut wl_display {
        self.display
    }

    pub unsafe fn event_loop(&self) -> *mut wl_event_loop {
        self.event_loop
    }

    /// Saves the panic error information in the compositor, to be re-thrown
    /// later when we are out of the C callback stack.
    pub(crate) fn save_panic_error(&mut self, error: Box<Any + Send>) {
        self.panic_error = Some(error);
    }
}

impl Drop for Compositor {
    fn drop(&mut self) {
        unsafe { wlr_compositor_destroy(self.compositor) }
    }
}

/// Terminates the compositor.
/// If one is not running, does nothing
pub fn terminate() {
    unsafe {
        if COMPOSITOR_PTR != 0 as _ {
            (*COMPOSITOR_PTR).terminate();
        }
    }
}
<|endoftext|>


<commit_before>use cudnn::ffi;
use cudnn::{Tensor, Filter4d, Convolution2d};
use cudart::Memory;
use std::ptr;

pub struct Cudnn {
    handle: ffi::Handle
}

impl Drop for Cudnn {
    fn drop(&mut self) {
        unsafe { ffi::cudnnDestroy(self.handle) };
    }
}

impl Cudnn {
    pub fn new() -> Result<Cudnn, &'static str> {
        let mut handle: ffi::Handle = ptr::null_mut();
        match unsafe { ffi::cudnnCreate(&mut handle) } {
            ffi::Status::Success => Ok(Cudnn { handle : handle }),
            e => Err(e.to_str())
        }
    }

    pub fn sigmoid_forward(self,
                           src_desc: Tensor,
                           src: &Memory<f32>,
                           dst_desc: Tensor,
                           dst: &mut Memory<f32>) -> Result<(), &'static str> {
        match unsafe { ffi::cudnnActivationForward(self.handle,
                                                   ffi::ActivationDescriptor::Sigmoid,
                                                   *&[1.0f32].as_ptr() as *const ::libc::c_void,
                                                   src_desc.desc,
                                                   src.data,
                                                   *&[0.0f32].as_ptr() as *const ::libc::c_void,
                                                   dst_desc.desc,
                                                   dst.data) } {
            ffi::Status::Success => Ok(()),
            e => Err(e.to_str())
        }
    }

    pub fn get_conv_forward_algo(&self,
                                 x_desc: &Tensor,
                                 w_desc: &Filter4d,
                                 conv_desc: &Convolution2d,
                                 y_desc: &Tensor) -> Result<ffi::ConvolutionFwdAlgo, &'static str> {
        let mut res = ffi::ConvolutionFwdAlgo::ImplicitGemm;
        match unsafe { ffi::cudnnGetConvolutionForwardAlgorithm(self.handle,
                                                                x_desc.desc,
                                                                w_desc.desc,
                                                                conv_desc.desc,
                                                                y_desc.desc,
                                                                ffi::ConvolutionFwdPreference::PreferFastest,
                                                                0,
                                                                &mut res) } {
            ffi::Status::Success => Ok(res),
            e => Err(e.to_str())
        }
    }

    pub fn get_conv_forward_workspace_size(&self,
                                           x_desc: &Tensor,
                                           w_desc: &Filter4d,
                                           conv_desc: &Convolution2d,
                                           y_desc: &Tensor,
                                           algo: ffi::ConvolutionFwdAlgo) -> Result<usize, &'static str> {

        let mut res = 0usize;
        match unsafe { ffi::cudnnGetConvolutionForwardWorkspaceSize(self.handle,
                                                                    x_desc.desc,
                                                                    w_desc.desc,
                                                                    conv_desc.desc,
                                                                    y_desc.desc,
                                                                    algo,
                                                                    &mut res) } {
            ffi::Status::Success => Ok(res),
            e => Err(e.to_str())
        }
    }

    pub fn conv_forward(&self,
                        x_desc: &Tensor,
                        x: &Memory<f32>,
                        w_desc: &Filter4d,
                        w: &Memory<f32>,
                        conv_desc: &Convolution2d,
                        y_desc: &Tensor,
                        y: &Memory<f32>) -> Result<(), &'static str> {
        let alpha = 1f32;
        let beta = 0f32;
        let algo = try!(self.get_conv_forward_algo(&x_desc,
                                                   &w_desc,
                                                   &conv_desc,
                                                   &y_desc));
        let workspace_size = try!(self.get_conv_forward_workspace_size(&x_desc,
                                                                       &w_desc,
                                                                       &conv_desc,
                                                                       &y_desc,
                                                                       algo));
        let workspace = try!(Memory::<f32>::new(workspace_size / 4));
        match unsafe { ffi::cudnnConvolutionForward(self.handle,
                                                    &alpha as *const _ as *const ::libc::c_void,
                                                    x_desc.desc,
                                                    x.data,
                                                    w_desc.desc,
                                                    w.data,
                                                    conv_desc.desc,
                                                    algo,
                                                    workspace.data,
                                                    workspace_size,
                                                    &beta as *const _ as *const ::libc::c_void,
                                                    y_desc.desc,
                                                    y.data) } {
            ffi::Status::Success => Ok(()),
            e => Err(e.to_str())
        }
    }
}
<commit_msg>convolution: sharing src & dst<commit_after>use cudnn::ffi;
use cudnn::{Tensor, Filter4d, Convolution2d};
use cudart::Memory;
use std::ptr;

pub struct Cudnn {
    handle: ffi::Handle
}

impl Drop for Cudnn {
    fn drop(&mut self) {
        unsafe { ffi::cudnnDestroy(self.handle) };
    }
}

impl Cudnn {
    pub fn new() -> Result<Cudnn, &'static str> {
        let mut handle: ffi::Handle = ptr::null_mut();
        match unsafe { ffi::cudnnCreate(&mut handle) } {
            ffi::Status::Success => Ok(Cudnn { handle : handle }),
            e => Err(e.to_str())
        }
    }

    pub fn sigmoid_forward(self,
                           src_desc: Tensor,
                           src: &Memory<f32>,
                           dst_desc: Tensor,
                           dst: &mut Memory<f32>) -> Result<(), &'static str> {
        match unsafe { ffi::cudnnActivationForward(self.handle,
                                                   ffi::ActivationDescriptor::Sigmoid,
                                                   *&[1.0f32].as_ptr() as *const ::libc::c_void,
                                                   src_desc.desc,
                                                   src.data,
                                                   *&[0.0f32].as_ptr() as *const ::libc::c_void,
                                                   dst_desc.desc,
                                                   dst.data) } {
            ffi::Status::Success => Ok(()),
            e => Err(e.to_str())
        }
    }

    pub fn get_conv_forward_algo(&self,
                                 x_desc: &Tensor,
                                 w_desc: &Filter4d,
                                 conv_desc: &Convolution2d,
                                 y_desc: &Tensor) -> Result<ffi::ConvolutionFwdAlgo, &'static str> {
        let mut res = ffi::ConvolutionFwdAlgo::ImplicitGemm;
        match unsafe { ffi::cudnnGetConvolutionForwardAlgorithm(self.handle,
                                                                x_desc.desc,
                                                                w_desc.desc,
                                                                conv_desc.desc,
                                                                y_desc.desc,
                                                                ffi::ConvolutionFwdPreference::PreferFastest,
                                                                0,
                                                                &mut res) } {
            ffi::Status::Success => Ok(res),
            e => Err(e.to_str())
        }
    }

    pub fn get_conv_forward_workspace_size(&self,
                                           x_desc: &Tensor,
                                           w_desc: &Filter4d,
                                           conv_desc: &Convolution2d,
                                           y_desc: &Tensor,
                                           algo: ffi::ConvolutionFwdAlgo) -> Result<usize, &'static str> {

        let mut res = 0usize;
        match unsafe { ffi::cudnnGetConvolutionForwardWorkspaceSize(self.handle,
                                                                    x_desc.desc,
                                                                    w_desc.desc,
                                                                    conv_desc.desc,
                                                                    y_desc.desc,
                                                                    algo,
                                                                    &mut res) } {
            ffi::Status::Success => Ok(res),
            e => Err(e.to_str())
        }
    }

    pub fn conv_forward(&self,
                        x_desc: &Tensor,
                        x: &Memory<f32>,
                        w_desc: &Filter4d,
                        w: &Memory<f32>,
                        conv_desc: &Convolution2d,
                        y_desc: &Tensor,
                        y: &Memory<f32>) -> Result<(), &'static str> {
        let alpha = 1f32;
        let beta = 0f32;
        let algo = try!(self.get_conv_forward_algo(&x_desc,
                                                   &w_desc,
                                                   &conv_desc,
                                                   &y_desc));
        let workspace_size = try!(self.get_conv_forward_workspace_size(&x_desc,
                                                                       &w_desc,
                                                                       &conv_desc,
                                                                       &y_desc,
                                                                       algo));
        let workspace = try!(Memory::<f32>::new(workspace_size / 4));
        match unsafe { ffi::cudnnConvolutionForward(self.handle,
                                                    &alpha as *const _ as *const ::libc::c_void,
                                                    x_desc.desc,
                                                    x.data,
                                                    w_desc.desc,
                                                    w.data,
                                                    conv_desc.desc,
                                                    algo,
                                                    workspace.data,
                                                    workspace_size,
                                                    &beta as *const _ as *const ::libc::c_void,
                                                    y_desc.desc,
                                                    y.data) } {
            ffi::Status::Success => Ok(()),
            e => Err(e.to_str())
        }
    }

    pub fn conv_forward_src(&self,
                            x_desc: &Tensor,
                            x: &Memory<f32>,
                            w_desc: &Filter4d,
                            w: &Memory<f32>,
                            conv_desc: &Convolution2d,
                            y_desc: &Tensor) -> Result<(), &'static str> {
        let alpha = 1f32;
        let beta = 0f32;
        let algo = try!(self.get_conv_forward_algo(&x_desc,
                                                   &w_desc,
                                                   &conv_desc,
                                                   &y_desc));
        let workspace_size = try!(self.get_conv_forward_workspace_size(&x_desc,
                                                                       &w_desc,
                                                                       &conv_desc,
                                                                       &y_desc,
                                                                       algo));
        let workspace = try!(Memory::<f32>::new(workspace_size / 4));
        match unsafe { ffi::cudnnConvolutionForward(self.handle,
                                                    &alpha as *const _ as *const ::libc::c_void,
                                                    x_desc.desc,
                                                    x.data,
                                                    w_desc.desc,
                                                    w.data,
                                                    conv_desc.desc,
                                                    algo,
                                                    workspace.data,
                                                    workspace_size,
                                                    &beta as *const _ as *const ::libc::c_void,
                                                    y_desc.desc,
                                                    x.data) } {
            ffi::Status::Success => Ok(()),
            e => Err(e.to_str())
        }
    }
}
<|endoftext|>


<commit_before>use std::sync::{Arc, RWLock};

use util::{HostMask};

use msg::{RawMessage};
use cmd;

/// Struct to hold the user info synchronized across all threads.
pub type SharedInfo = Arc<RWLock<UserInfo>>;

/// Struct holding the user info like nick name, host name etc.
pub struct UserInfo {
    id: super::PeerId,
    server_name: String,
    nick: String,
    username: String,
    realname: String,
    hostname: String,
    hostmask: HostMask
}

impl UserInfo {
    /// Creates the user info struct.
    pub fn new(id: super::PeerId, server_name: String, hostname: String) -> UserInfo {
        let mask = HostMask::from_parts("*", "*", hostname.as_slice());
        UserInfo {
            id: id,
            server_name: server_name,
            nick: "*".to_string(),
            username: "*".to_string(),
            realname: "John Doe".to_string(),
            hostname: hostname,
            hostmask: mask
        }
    }

    /// Getter for the peer id
    pub fn id(&self) -> super::PeerId {
        self.id.clone()
    }
    /// Getter for the nick name
    pub fn nick(&self) -> &String {
        &self.nick
    }

    /// Setter for the nick name
    pub fn set_nick(&mut self, nick: String) {
        self.nick = nick;
        self.update_mask()
    }
    /// Getter for the user name
    pub fn set_username(&mut self, name: String) {
        self.username = name;
        self.update_mask()
    }
    /// Getter for the real name
    pub fn set_realname(&mut self, name: String) {
        self.realname = name;
        self.update_mask()
    }
    /// Getter for the server name
    pub fn server_name(&self) -> &String {
        &self.server_name
    }

    /// Updates the real hostmask
    fn update_mask(&mut self) {
        self.hostmask = HostMask::from_parts(
            self.nick.as_slice(),
            self.username.as_slice(),
            self.hostname.as_slice()
        )
    }

    /// Getter for the public host mask.
    ///
    /// This is the host mask that is send out to other users.
    pub fn public_hostmask(&self) -> &HostMask {
        &self.hostmask
    }
    /// Getter for the real host mask
    pub fn real_hostmask(&self) -> &HostMask {
        &self.hostmask
    }

}

/// Struct representing a peer.
///
/// Allows access to the globally shared user data can easily be cloned
#[deriving(Clone)]
pub struct Peer {
    info: SharedInfo,
    tx: Sender<RawMessage>,
}
impl Peer {
    /// Create a new peer struct.
    pub fn new(info: UserInfo, tx: Sender<RawMessage>) -> Peer {
        Peer {
            info: Arc::new(RWLock::new(info)),
            tx: tx
        }
    }

    /// Sends a message to the peer.
    pub fn send_msg(&self, msg: RawMessage) {
        let _ = self.tx.send_opt(msg);
    }

    /// Sends a response to the peer.
    ///
    /// This should be the preferred way of sending responses. Do
    /// not construct raw responsed. This method prepends the params
    /// with the nick name to create well-formed responses.
    pub fn send_response<'a>(&'a self, command: cmd::ResponseCode,
                         params: &[&'a str], origin: &str) {
        let info = self.info.read();
        let msg = RawMessage::new(
            cmd::REPLY(command),
            (vec![info.nick().as_slice()].append(params)).as_slice(),
            Some(origin)
        );
        let _ = self.tx.send_opt(msg);
    }

    /// Getter for the shared user info
    pub fn info(&self) -> &SharedInfo {
        &self.info
    }

    /// Getter for the peer id
    pub fn id(&self) -> super::PeerId {
        self.info().read().id()
    }
}
<commit_msg>more getters<commit_after>use std::sync::{Arc, RWLock};

use util::{HostMask};

use msg::{RawMessage};
use cmd;

/// Struct to hold the user info synchronized across all threads.
pub type SharedInfo = Arc<RWLock<UserInfo>>;

/// Struct holding the user info like nick name, host name etc.
pub struct UserInfo {
    id: super::PeerId,
    server_name: String,
    nick: String,
    username: String,
    realname: String,
    hostname: String,
    hostmask: HostMask
}

impl UserInfo {
    /// Creates the user info struct.
    pub fn new(id: super::PeerId, server_name: String, hostname: String) -> UserInfo {
        let mask = HostMask::from_parts("*", "*", hostname.as_slice());
        UserInfo {
            id: id,
            server_name: server_name,
            nick: "*".to_string(),
            username: "*".to_string(),
            realname: "John Doe".to_string(),
            hostname: hostname,
            hostmask: mask
        }
    }

    /// Getter for the peer id
    pub fn id(&self) -> super::PeerId {
        self.id.clone()
    }

    /// Getter for the nick name
    pub fn nick(&self) -> &String {
        &self.nick
    }
    /// Setter for the nick name
    pub fn set_nick(&mut self, nick: String) {
        self.nick = nick;
        self.update_mask()
    }
    /// Getter for the nick name
    pub fn username(&self) -> &String {
        &self.username
    }
    /// Getter for the user name
    pub fn set_username(&mut self, name: String) {
        self.username = name;
        self.update_mask()
    }
    /// Getter for the nick name
    pub fn realname(&self) -> &String {
        &self.realname
    }
    /// Getter for the real name
    pub fn set_realname(&mut self, name: String) {
        self.realname = name;
        self.update_mask()
    }
    /// Getter for the server name
    pub fn server_name(&self) -> &String {
        &self.server_name
    }
    /// Getter for the server name
    pub fn hostname(&self) -> &String {
        &self.hostname
    }

    /// Updates the real hostmask
    fn update_mask(&mut self) {
        self.hostmask = HostMask::from_parts(
            self.nick.as_slice(),
            self.username.as_slice(),
            self.hostname.as_slice()
        )
    }

    /// Getter for the public host mask.
    ///
    /// This is the host mask that is send out to other users.
    pub fn public_hostmask(&self) -> &HostMask {
        &self.hostmask
    }
    /// Getter for the real host mask
    pub fn real_hostmask(&self) -> &HostMask {
        &self.hostmask
    }

}

/// Struct representing a peer.
///
/// Allows access to the globally shared user data can easily be cloned
#[deriving(Clone)]
pub struct Peer {
    info: SharedInfo,
    tx: Sender<RawMessage>,
}
impl Peer {
    /// Create a new peer struct.
    pub fn new(info: UserInfo, tx: Sender<RawMessage>) -> Peer {
        Peer {
            info: Arc::new(RWLock::new(info)),
            tx: tx
        }
    }

    /// Sends a message to the peer.
    pub fn send_msg(&self, msg: RawMessage) {
        let _ = self.tx.send_opt(msg);
    }

    /// Sends a response to the peer.
    ///
    /// This should be the preferred way of sending responses. Do
    /// not construct raw responsed. This method prepends the params
    /// with the nick name to create well-formed responses.
    pub fn send_response<'a>(&'a self, command: cmd::ResponseCode,
                         params: &[&'a str], origin: &str) {
        let info = self.info.read();
        let msg = RawMessage::new(
            cmd::REPLY(command),
            (vec![info.nick().as_slice()].append(params)).as_slice(),
            Some(origin)
        );
        let _ = self.tx.send_opt(msg);
    }

    /// Getter for the shared user info
    pub fn info(&self) -> &SharedInfo {
        &self.info
    }

    /// Getter for the peer id
    pub fn id(&self) -> super::PeerId {
        self.info().read().id()
    }
}
<|endoftext|>