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