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