1 //! Types for working with generics 2 3 use std::iter::Iterator; 4 use std::slice::Iter; 5 6 use crate::{FromGenericParam, FromGenerics, FromTypeParam, Result}; 7 8 /// Extension trait for `GenericParam` to support getting values by variant. 9 /// 10 /// # Usage 11 /// `darling::ast::Generics` needs a way to test its params array in order to iterate over type params. 12 /// Rather than require callers to use `darling::ast::GenericParam` in all cases, this trait makes that 13 /// polymorphic. 14 pub trait GenericParamExt { 15 /// The type this GenericParam uses to represent type params and their bounds 16 type TypeParam; 17 type LifetimeParam; 18 type ConstParam; 19 20 /// If this GenericParam is a type param, get the underlying value. as_type_param(&self) -> Option<&Self::TypeParam>21 fn as_type_param(&self) -> Option<&Self::TypeParam> { 22 None 23 } 24 25 /// If this GenericParam is a lifetime, get the underlying value. as_lifetime_param(&self) -> Option<&Self::LifetimeParam>26 fn as_lifetime_param(&self) -> Option<&Self::LifetimeParam> { 27 None 28 } 29 30 /// If this GenericParam is a const param, get the underlying value. as_const_param(&self) -> Option<&Self::ConstParam>31 fn as_const_param(&self) -> Option<&Self::ConstParam> { 32 None 33 } 34 } 35 36 impl GenericParamExt for syn::GenericParam { 37 type TypeParam = syn::TypeParam; 38 type LifetimeParam = syn::LifetimeParam; 39 type ConstParam = syn::ConstParam; 40 as_type_param(&self) -> Option<&Self::TypeParam>41 fn as_type_param(&self) -> Option<&Self::TypeParam> { 42 if let syn::GenericParam::Type(ref val) = *self { 43 Some(val) 44 } else { 45 None 46 } 47 } 48 as_lifetime_param(&self) -> Option<&Self::LifetimeParam>49 fn as_lifetime_param(&self) -> Option<&Self::LifetimeParam> { 50 if let syn::GenericParam::Lifetime(ref val) = *self { 51 Some(val) 52 } else { 53 None 54 } 55 } 56 as_const_param(&self) -> Option<&Self::ConstParam>57 fn as_const_param(&self) -> Option<&Self::ConstParam> { 58 if let syn::GenericParam::Const(ref val) = *self { 59 Some(val) 60 } else { 61 None 62 } 63 } 64 } 65 66 impl GenericParamExt for syn::TypeParam { 67 type TypeParam = syn::TypeParam; 68 type LifetimeParam = (); 69 type ConstParam = (); 70 as_type_param(&self) -> Option<&Self::TypeParam>71 fn as_type_param(&self) -> Option<&Self::TypeParam> { 72 Some(self) 73 } 74 } 75 76 /// A mirror of `syn::GenericParam` which is generic over all its contents. 77 #[derive(Debug, Clone, PartialEq, Eq)] 78 pub enum GenericParam<T = syn::TypeParam, L = syn::LifetimeParam, C = syn::ConstParam> { 79 Type(T), 80 Lifetime(L), 81 Const(C), 82 } 83 84 impl<T: FromTypeParam> FromTypeParam for GenericParam<T> { from_type_param(type_param: &syn::TypeParam) -> Result<Self>85 fn from_type_param(type_param: &syn::TypeParam) -> Result<Self> { 86 Ok(GenericParam::Type(FromTypeParam::from_type_param( 87 type_param, 88 )?)) 89 } 90 } 91 92 impl<T: FromTypeParam> FromGenericParam for GenericParam<T> { from_generic_param(param: &syn::GenericParam) -> Result<Self>93 fn from_generic_param(param: &syn::GenericParam) -> Result<Self> { 94 Ok(match *param { 95 syn::GenericParam::Type(ref ty) => { 96 GenericParam::Type(FromTypeParam::from_type_param(ty)?) 97 } 98 syn::GenericParam::Lifetime(ref val) => GenericParam::Lifetime(val.clone()), 99 syn::GenericParam::Const(ref val) => GenericParam::Const(val.clone()), 100 }) 101 } 102 } 103 104 impl<T, L, C> GenericParamExt for GenericParam<T, L, C> { 105 type TypeParam = T; 106 type LifetimeParam = L; 107 type ConstParam = C; 108 as_type_param(&self) -> Option<&T>109 fn as_type_param(&self) -> Option<&T> { 110 if let GenericParam::Type(ref val) = *self { 111 Some(val) 112 } else { 113 None 114 } 115 } 116 as_lifetime_param(&self) -> Option<&L>117 fn as_lifetime_param(&self) -> Option<&L> { 118 if let GenericParam::Lifetime(ref val) = *self { 119 Some(val) 120 } else { 121 None 122 } 123 } 124 as_const_param(&self) -> Option<&C>125 fn as_const_param(&self) -> Option<&C> { 126 if let GenericParam::Const(ref val) = *self { 127 Some(val) 128 } else { 129 None 130 } 131 } 132 } 133 134 /// A mirror of the `syn::Generics` type which can contain arbitrary representations 135 /// of params and where clauses. 136 #[derive(Debug, Clone, PartialEq, Eq)] 137 pub struct Generics<P, W = syn::WhereClause> { 138 pub params: Vec<P>, 139 pub where_clause: Option<W>, 140 } 141 142 impl<P, W> Generics<P, W> { type_params(&self) -> TypeParams<'_, P>143 pub fn type_params(&self) -> TypeParams<'_, P> { 144 TypeParams(self.params.iter()) 145 } 146 } 147 148 impl<P: FromGenericParam> FromGenerics for Generics<P> { from_generics(generics: &syn::Generics) -> Result<Self>149 fn from_generics(generics: &syn::Generics) -> Result<Self> { 150 Ok(Generics { 151 params: generics 152 .params 153 .iter() 154 .map(FromGenericParam::from_generic_param) 155 .collect::<Result<Vec<P>>>()?, 156 where_clause: generics.where_clause.clone(), 157 }) 158 } 159 } 160 161 pub struct TypeParams<'a, P>(Iter<'a, P>); 162 163 impl<'a, P: GenericParamExt> Iterator for TypeParams<'a, P> { 164 type Item = &'a <P as GenericParamExt>::TypeParam; 165 next(&mut self) -> Option<Self::Item>166 fn next(&mut self) -> Option<Self::Item> { 167 let next = self.0.next(); 168 match next { 169 None => None, 170 Some(v) => match v.as_type_param() { 171 Some(val) => Some(val), 172 None => self.next(), 173 }, 174 } 175 } 176 } 177 178 #[cfg(test)] 179 mod tests { 180 use syn::parse_quote; 181 182 use super::{GenericParam, Generics}; 183 use crate::FromGenerics; 184 185 #[test] generics()186 fn generics() { 187 let g: syn::Generics = parse_quote!(<T>); 188 let deified: Generics<GenericParam<syn::Ident>> = FromGenerics::from_generics(&g).unwrap(); 189 assert!(deified.params.len() == 1); 190 assert!(deified.where_clause.is_none()); 191 } 192 } 193