1 use std::io::Write;
2 use std::ops::Deref;
3 
4 use crate::bindgen::config::{Config, Language};
5 use crate::bindgen::declarationtyperesolver::{DeclarationType, DeclarationTypeResolver};
6 use crate::bindgen::ir::{Path, Type};
7 use crate::bindgen::utilities::IterHelpers;
8 use crate::bindgen::writer::{Source, SourceWriter};
9 
10 #[derive(Default, Debug, Clone)]
11 pub struct GenericParams(pub Vec<Path>);
12 
13 impl GenericParams {
new(generics: &syn::Generics) -> Self14     pub fn new(generics: &syn::Generics) -> Self {
15         GenericParams(
16             generics
17                 .params
18                 .iter()
19                 .filter_map(|x| match *x {
20                     syn::GenericParam::Type(syn::TypeParam { ref ident, .. }) => {
21                         Some(Path::new(ident.to_string()))
22                     }
23                     _ => None,
24                 })
25                 .collect(),
26         )
27     }
28 
write_internal<F: Write>( &self, config: &Config, out: &mut SourceWriter<F>, with_default: bool, )29     fn write_internal<F: Write>(
30         &self,
31         config: &Config,
32         out: &mut SourceWriter<F>,
33         with_default: bool,
34     ) {
35         if !self.0.is_empty() && config.language == Language::Cxx {
36             out.write("template<");
37             for (i, item) in self.0.iter().enumerate() {
38                 if i != 0 {
39                     out.write(", ");
40                 }
41                 write!(out, "typename {}", item);
42                 if with_default {
43                     write!(out, " = void");
44                 }
45             }
46             out.write(">");
47             out.new_line();
48         }
49     }
50 
write_with_default<F: Write>(&self, config: &Config, out: &mut SourceWriter<F>)51     pub fn write_with_default<F: Write>(&self, config: &Config, out: &mut SourceWriter<F>) {
52         self.write_internal(config, out, true);
53     }
54 }
55 
56 impl Deref for GenericParams {
57     type Target = [Path];
58 
deref(&self) -> &[Path]59     fn deref(&self) -> &[Path] {
60         &self.0
61     }
62 }
63 
64 impl Source for GenericParams {
write<F: Write>(&self, config: &Config, out: &mut SourceWriter<F>)65     fn write<F: Write>(&self, config: &Config, out: &mut SourceWriter<F>) {
66         self.write_internal(config, out, false);
67     }
68 }
69 
70 #[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
71 pub struct GenericPath {
72     path: Path,
73     export_name: String,
74     generics: Vec<Type>,
75     ctype: Option<DeclarationType>,
76 }
77 
78 impl GenericPath {
new(path: Path, generics: Vec<Type>) -> Self79     pub fn new(path: Path, generics: Vec<Type>) -> Self {
80         let export_name = path.name().to_owned();
81         Self {
82             path,
83             export_name,
84             generics,
85             ctype: None,
86         }
87     }
88 
self_path() -> Self89     pub fn self_path() -> Self {
90         Self::new(Path::new("Self"), vec![])
91     }
92 
replace_self_with(&mut self, self_ty: &Path)93     pub fn replace_self_with(&mut self, self_ty: &Path) {
94         if self.path.replace_self_with(self_ty) {
95             self.export_name = self_ty.name().to_owned();
96         }
97         // Caller deals with generics.
98     }
99 
path(&self) -> &Path100     pub fn path(&self) -> &Path {
101         &self.path
102     }
103 
generics(&self) -> &[Type]104     pub fn generics(&self) -> &[Type] {
105         &self.generics
106     }
107 
generics_mut(&mut self) -> &mut [Type]108     pub fn generics_mut(&mut self) -> &mut [Type] {
109         &mut self.generics
110     }
111 
ctype(&self) -> Option<&DeclarationType>112     pub fn ctype(&self) -> Option<&DeclarationType> {
113         self.ctype.as_ref()
114     }
115 
name(&self) -> &str116     pub fn name(&self) -> &str {
117         self.path.name()
118     }
119 
export_name(&self) -> &str120     pub fn export_name(&self) -> &str {
121         &self.export_name
122     }
123 
rename_for_config(&mut self, config: &Config, generic_params: &GenericParams)124     pub fn rename_for_config(&mut self, config: &Config, generic_params: &GenericParams) {
125         for generic in &mut self.generics {
126             generic.rename_for_config(config, generic_params);
127         }
128         if !generic_params.contains(&self.path) {
129             config.export.rename(&mut self.export_name);
130         }
131     }
132 
resolve_declaration_types(&mut self, resolver: &DeclarationTypeResolver)133     pub fn resolve_declaration_types(&mut self, resolver: &DeclarationTypeResolver) {
134         self.ctype = resolver.type_for(&self.path);
135     }
136 
load(path: &syn::Path) -> Result<Self, String>137     pub fn load(path: &syn::Path) -> Result<Self, String> {
138         assert!(
139             !path.segments.is_empty(),
140             "{:?} doesn't have any segments",
141             path
142         );
143         let last_segment = path.segments.last().unwrap();
144         let name = last_segment.ident.to_string();
145 
146         let path = Path::new(name);
147         let phantom_data_path = Path::new("PhantomData");
148         if path == phantom_data_path {
149             return Ok(Self::new(path, Vec::new()));
150         }
151 
152         let generics = match last_segment.arguments {
153             syn::PathArguments::AngleBracketed(syn::AngleBracketedGenericArguments {
154                 ref args,
155                 ..
156             }) => args.iter().try_skip_map(|x| match *x {
157                 syn::GenericArgument::Type(ref x) => Type::load(x),
158                 syn::GenericArgument::Lifetime(_) => Ok(None),
159                 _ => Err(format!("can't handle generic argument {:?}", x)),
160             })?,
161             syn::PathArguments::Parenthesized(_) => {
162                 return Err("Path contains parentheses.".to_owned());
163             }
164             _ => Vec::new(),
165         };
166 
167         Ok(Self::new(path, generics))
168     }
169 }
170