1 /* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 5 use std::io::Write; 6 7 use syn; 8 9 use crate::bindgen::config::{Config, Language}; 10 use crate::bindgen::declarationtyperesolver::DeclarationTypeResolver; 11 use crate::bindgen::dependencies::Dependencies; 12 use crate::bindgen::ir::{ 13 AnnotationSet, Cfg, ConditionWrite, Documentation, GenericParams, Item, ItemContainer, Path, 14 ToCondition, Type, 15 }; 16 use crate::bindgen::library::Library; 17 use crate::bindgen::mangle; 18 use crate::bindgen::monomorph::Monomorphs; 19 use crate::bindgen::writer::{Source, SourceWriter}; 20 21 #[derive(Debug, Clone)] 22 pub struct OpaqueItem { 23 pub path: Path, 24 pub export_name: String, 25 pub generic_params: GenericParams, 26 pub cfg: Option<Cfg>, 27 pub annotations: AnnotationSet, 28 pub documentation: Documentation, 29 } 30 31 impl OpaqueItem { load( path: Path, generics: &syn::Generics, attrs: &[syn::Attribute], mod_cfg: Option<&Cfg>, ) -> Result<OpaqueItem, String>32 pub fn load( 33 path: Path, 34 generics: &syn::Generics, 35 attrs: &[syn::Attribute], 36 mod_cfg: Option<&Cfg>, 37 ) -> Result<OpaqueItem, String> { 38 Ok(Self::new( 39 path, 40 GenericParams::new(generics), 41 Cfg::append(mod_cfg, Cfg::load(attrs)), 42 AnnotationSet::load(attrs).unwrap_or_else(|_| AnnotationSet::new()), 43 Documentation::load(attrs), 44 )) 45 } 46 new( path: Path, generic_params: GenericParams, cfg: Option<Cfg>, annotations: AnnotationSet, documentation: Documentation, ) -> OpaqueItem47 pub fn new( 48 path: Path, 49 generic_params: GenericParams, 50 cfg: Option<Cfg>, 51 annotations: AnnotationSet, 52 documentation: Documentation, 53 ) -> OpaqueItem { 54 let export_name = path.name().to_owned(); 55 Self { 56 path, 57 export_name, 58 generic_params, 59 cfg, 60 annotations, 61 documentation, 62 } 63 } 64 } 65 66 impl Item for OpaqueItem { path(&self) -> &Path67 fn path(&self) -> &Path { 68 &self.path 69 } 70 export_name(&self) -> &str71 fn export_name(&self) -> &str { 72 &self.export_name 73 } 74 cfg(&self) -> Option<&Cfg>75 fn cfg(&self) -> Option<&Cfg> { 76 self.cfg.as_ref() 77 } 78 annotations(&self) -> &AnnotationSet79 fn annotations(&self) -> &AnnotationSet { 80 &self.annotations 81 } 82 annotations_mut(&mut self) -> &mut AnnotationSet83 fn annotations_mut(&mut self) -> &mut AnnotationSet { 84 &mut self.annotations 85 } 86 container(&self) -> ItemContainer87 fn container(&self) -> ItemContainer { 88 ItemContainer::OpaqueItem(self.clone()) 89 } 90 collect_declaration_types(&self, resolver: &mut DeclarationTypeResolver)91 fn collect_declaration_types(&self, resolver: &mut DeclarationTypeResolver) { 92 resolver.add_struct(&self.path); 93 } 94 rename_for_config(&mut self, config: &Config)95 fn rename_for_config(&mut self, config: &Config) { 96 config.export.rename(&mut self.export_name); 97 } 98 add_dependencies(&self, _: &Library, _: &mut Dependencies)99 fn add_dependencies(&self, _: &Library, _: &mut Dependencies) {} 100 instantiate_monomorph( &self, generic_values: &[Type], _library: &Library, out: &mut Monomorphs, )101 fn instantiate_monomorph( 102 &self, 103 generic_values: &[Type], 104 _library: &Library, 105 out: &mut Monomorphs, 106 ) { 107 assert!( 108 self.generic_params.len() > 0, 109 "{} is not generic", 110 self.path 111 ); 112 assert!( 113 self.generic_params.len() == generic_values.len(), 114 "{} has {} params but is being instantiated with {} values", 115 self.path, 116 self.generic_params.len(), 117 generic_values.len(), 118 ); 119 120 let mangled_path = mangle::mangle_path(&self.path, generic_values); 121 let monomorph = OpaqueItem::new( 122 mangled_path, 123 GenericParams::default(), 124 self.cfg.clone(), 125 self.annotations.clone(), 126 self.documentation.clone(), 127 ); 128 129 out.insert_opaque(self, monomorph, generic_values.to_owned()); 130 } 131 } 132 133 impl Source for OpaqueItem { write<F: Write>(&self, config: &Config, out: &mut SourceWriter<F>)134 fn write<F: Write>(&self, config: &Config, out: &mut SourceWriter<F>) { 135 let condition = self.cfg.to_condition(config); 136 condition.write_before(config, out); 137 138 self.documentation.write(config, out); 139 140 self.generic_params.write(config, out); 141 142 if config.style.generate_typedef() && config.language == Language::C { 143 write!( 144 out, 145 "typedef struct {} {};", 146 self.export_name(), 147 self.export_name() 148 ); 149 } else { 150 write!(out, "struct {};", self.export_name()); 151 } 152 153 condition.write_after(config, out); 154 } 155 } 156