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