1use std::io::Write;
2use std::ops::Deref;
3
4use syn::ext::IdentExt;
5
6use crate::bindgen::cdecl;
7use crate::bindgen::config::{Config, Language};
8use crate::bindgen::declarationtyperesolver::{DeclarationType, DeclarationTypeResolver};
9use crate::bindgen::ir::{ConstExpr, Path, Type};
10use crate::bindgen::utilities::IterHelpers;
11use crate::bindgen::writer::{Source, SourceWriter};
12
13#[derive(Debug, Clone)]
14pub enum GenericParamType {
15 Type,
16 Const(Type),
17}
18
19#[derive(Debug, Clone)]
20pub struct GenericParam {
21 name: Path,
22 ty: GenericParamType,
23}
24
25impl GenericParam {
26 pub fn new_type_param(name: &str) -> Self {
27 GenericParam {
28 name: Path::new(name),
29 ty: GenericParamType::Type,
30 }
31 }
32
33 pub fn load(param: &syn::GenericParam) -> Result<Option<Self>, String> {
34 match *param {
35 syn::GenericParam::Type(syn::TypeParam { ref ident, .. }) => Ok(Some(GenericParam {
36 name: Path::new(ident.unraw().to_string()),
37 ty: GenericParamType::Type,
38 })),
39
40 syn::GenericParam::Lifetime(_) => Ok(None),
41
42 syn::GenericParam::Const(syn::ConstParam {
43 ref ident, ref ty, ..
44 }) => match Type::load(ty)? {
45 None => {
46 // A type that evaporates, like PhantomData.
47 Err(format!("unsupported const generic type: {:?}", ty))
48 }
49 Some(ty) => Ok(Some(GenericParam {
50 name: Path::new(ident.unraw().to_string()),
51 ty: GenericParamType::Const(ty),
52 })),
53 },
54 }
55 }
56
57 pub fn name(&self) -> &Path {
58 &self.name
59 }
60}
61
62#[derive(Default, Debug, Clone)]
63pub struct GenericParams(pub Vec<GenericParam>);
64
65impl GenericParams {
66 pub fn load(generics: &syn::Generics) -> Result<Self, String> {
67 let mut params = vec![];
68 for param in &generics.params {
69 if let Some(p) = GenericParam::load(param)? {
70 params.push(p);
71 }
72 }
73
74 Ok(GenericParams(params))
75 }
76
77 /// Associate each parameter with an argument.
78 pub fn call<'out>(
79 &'out self,
80 item_name: &str,
81 arguments: &'out [GenericArgument],
82 ) -> Vec<(&'out Path, &'out GenericArgument)> {
83 assert!(self.len() > 0, "{} is not generic", item_name);
84 assert!(
85 self.len() == arguments.len(),
86 "{} has {} params but is being instantiated with {} values",
87 item_name,
88 self.len(),
89 arguments.len(),
90 );
91 self.iter()
92 .map(|param| param.name())
93 .zip(arguments.iter())
94 .collect()
95 }
96
97 fn write_internal<F: Write>(
98 &self,
99 config: &Config,
100 out: &mut SourceWriter<F>,
101 with_default: bool,
102 ) {
103 if !self.0.is_empty() && config.language == Language::Cxx {
104 out.write("template<");
105 for (i, item) in self.0.iter().enumerate() {
106 if i != 0 {
107 out.write(", ");
108 }
109 match item.ty {
110 GenericParamType::Type => {
111 write!(out, "typename {}", item.name);
112 if with_default {
113 write!(out, " = void");
114 }
115 }
116 GenericParamType::Const(ref ty) => {
117 cdecl::write_field(out, ty, item.name.name(), config);
118 if with_default {
119 write!(out, " = 0");
120 }
121 }
122 }
123 }
124 out.write(">");
125 out.new_line();
126 }
127 }
128
129 pub fn write_with_default<F: Write>(&self, config: &Config, out: &mut SourceWriter<F>) {
130 self.write_internal(config, out, true);
131 }
132}
133
134impl Deref for GenericParams {
135 type Target = [GenericParam];
136
137 fn deref(&self) -> &[GenericParam] {
138 &self.0
139 }
140}
141
142impl Source for GenericParams {
143 fn write<F: Write>(&self, config: &Config, out: &mut SourceWriter<F>) {
144 self.write_internal(config, out, with_default:false);
145 }
146}
147
148/// A (non-lifetime) argument passed to a generic, either a type or a constant expression.
149///
150/// Note: Both arguments in a type like `Array<T, N>` are represented as
151/// `GenericArgument::Type`s, even if `N` is actually the name of a const. This
152/// is a consequence of `syn::GenericArgument` doing the same thing.
153#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
154pub enum GenericArgument {
155 Type(Type),
156 Const(ConstExpr),
157}
158
159impl GenericArgument {
160 pub fn specialize(&self, mappings: &[(&Path, &GenericArgument)]) -> GenericArgument {
161 match *self {
162 GenericArgument::Type(ref ty) => {
163 if let Type::Path(ref path) = *ty {
164 if path.is_single_identifier() {
165 // See note on `GenericArgument` above: `ty` may
166 // actually be the name of a const. Check for that now.
167 for &(name, value) in mappings {
168 if *name == path.path {
169 return value.clone();
170 }
171 }
172 }
173 }
174 GenericArgument::Type(ty.specialize(mappings))
175 }
176 GenericArgument::Const(ref expr) => GenericArgument::Const(expr.clone()),
177 }
178 }
179
180 pub fn rename_for_config(&mut self, config: &Config, generic_params: &GenericParams) {
181 match *self {
182 GenericArgument::Type(ref mut ty) => ty.rename_for_config(config, generic_params),
183 GenericArgument::Const(ref mut expr) => expr.rename_for_config(config),
184 }
185 }
186}
187
188impl Source for GenericArgument {
189 fn write<F: Write>(&self, config: &Config, out: &mut SourceWriter<F>) {
190 match *self {
191 GenericArgument::Type(ref ty: &Type) => ty.write(config, out),
192 GenericArgument::Const(ref expr: &ConstExpr) => expr.write(config, out),
193 }
194 }
195}
196
197#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
198pub struct GenericPath {
199 path: Path,
200 export_name: String,
201 generics: Vec<GenericArgument>,
202 ctype: Option<DeclarationType>,
203}
204
205impl GenericPath {
206 pub fn new(path: Path, generics: Vec<GenericArgument>) -> Self {
207 let export_name = path.name().to_owned();
208 Self {
209 path,
210 export_name,
211 generics,
212 ctype: None,
213 }
214 }
215
216 pub fn self_path() -> Self {
217 Self::new(Path::new("Self"), vec![])
218 }
219
220 pub fn replace_self_with(&mut self, self_ty: &Path) {
221 if self.path.replace_self_with(self_ty) {
222 self.export_name = self_ty.name().to_owned();
223 }
224 // Caller deals with generics.
225 }
226
227 pub fn path(&self) -> &Path {
228 &self.path
229 }
230
231 pub fn generics(&self) -> &[GenericArgument] {
232 &self.generics
233 }
234
235 pub fn generics_mut(&mut self) -> &mut [GenericArgument] {
236 &mut self.generics
237 }
238
239 pub fn ctype(&self) -> Option<&DeclarationType> {
240 self.ctype.as_ref()
241 }
242
243 pub fn name(&self) -> &str {
244 self.path.name()
245 }
246
247 pub fn export_name(&self) -> &str {
248 &self.export_name
249 }
250
251 pub fn is_single_identifier(&self) -> bool {
252 self.generics.is_empty()
253 }
254
255 pub fn rename_for_config(&mut self, config: &Config, generic_params: &GenericParams) {
256 for generic in &mut self.generics {
257 generic.rename_for_config(config, generic_params);
258 }
259 if !generic_params.iter().any(|param| param.name == self.path) {
260 config.export.rename(&mut self.export_name);
261 }
262 }
263
264 pub fn resolve_declaration_types(&mut self, resolver: &DeclarationTypeResolver) {
265 self.ctype = resolver.type_for(&self.path);
266 }
267
268 pub fn load(path: &syn::Path) -> Result<Self, String> {
269 assert!(
270 !path.segments.is_empty(),
271 "{:?} doesn't have any segments",
272 path
273 );
274 let last_segment = path.segments.last().unwrap();
275 let name = last_segment.ident.unraw().to_string();
276
277 let path = Path::new(name);
278 let phantom_data_path = Path::new("PhantomData");
279 if path == phantom_data_path {
280 return Ok(Self::new(path, Vec::new()));
281 }
282
283 let generics = match last_segment.arguments {
284 syn::PathArguments::AngleBracketed(syn::AngleBracketedGenericArguments {
285 ref args,
286 ..
287 }) => args.iter().try_skip_map(|x| match *x {
288 syn::GenericArgument::Type(ref x) => Ok(Type::load(x)?.map(GenericArgument::Type)),
289 syn::GenericArgument::Lifetime(_) => Ok(None),
290 syn::GenericArgument::Const(ref x) => {
291 Ok(Some(GenericArgument::Const(ConstExpr::load(x)?)))
292 }
293 _ => Err(format!("can't handle generic argument {:?}", x)),
294 })?,
295 syn::PathArguments::Parenthesized(_) => {
296 return Err("Path contains parentheses.".to_owned());
297 }
298 _ => Vec::new(),
299 };
300
301 Ok(Self::new(path, generics))
302 }
303}
304