diff --git a/src/bindgen/items.rs b/src/bindgen/items.rs index 0771538..f78d1d9 100644 --- a/src/bindgen/items.rs +++ b/src/bindgen/items.rs @@ -125,50 +125,79 @@ pub enum Type { FuncPtr(Option>, Vec), } impl Type { - pub fn convert(ty: &syn::Ty) -> ConvertResult { - match ty { + pub fn convert(ty: &syn::Ty) -> ConvertResult> { + let converted = match ty { &syn::Ty::Rptr(_, ref mut_ty) => { let converted = try!(Type::convert(&mut_ty.ty)); - Ok(match mut_ty.mutability { + let converted = match converted { + Some(converted) => converted, + None => return Err(format!("cannot have a pointer to a zero sized type")), + }; + + match mut_ty.mutability { syn::Mutability::Mutable => Type::Ptr(Box::new(converted)), syn::Mutability::Immutable => Type::ConstPtr(Box::new(converted)), - }) + } } &syn::Ty::Ptr(ref mut_ty) => { let converted = try!(Type::convert(&mut_ty.ty)); - Ok(match mut_ty.mutability { + let converted = match converted { + Some(converted) => converted, + None => return Err(format!("cannot have a pointer to a zero sized type")), + }; + + match mut_ty.mutability { syn::Mutability::Mutable => Type::Ptr(Box::new(converted)), syn::Mutability::Immutable => Type::ConstPtr(Box::new(converted)), - }) + } } &syn::Ty::Path(_, ref p) => { - let p = try!(p.convert_to_simple_single_segment()); + let (name, generics) = try!(p.convert_to_generic_single_segment()); - if let Some(prim) = PrimitiveType::maybe(&p) { - Ok(Type::Primitive(prim)) + if name == "PhantomData" && generics.len() == 1 { + return Ok(None); + } else if generics.len() != 0 { + return Err(format!("cannot have a type with generics")); } else { - Ok(Type::Path(p)) + if let Some(prim) = PrimitiveType::maybe(&name) { + Type::Primitive(prim) + } else { + Type::Path(name) + } } } &syn::Ty::Array(ref ty, syn::ConstExpr::Lit(syn::Lit::Int(sz, _))) => { let converted = try!(Type::convert(ty)); - Ok(Type::Array(Box::new(converted), sz)) + let converted = match converted { + Some(converted) => converted, + None => return Err(format!("cannot have an array of zero sized types")), + }; + + Type::Array(Box::new(converted), sz) }, &syn::Ty::BareFn(ref f) => { let args = try!(f.inputs.iter() - .try_map(|x| Type::convert(&x.ty))); + .try_skip_map(|x| Type::convert(&x.ty))); let ret = try!(f.output.as_type()); - Ok(Type::FuncPtr( + Type::FuncPtr( ret.map(|x| Box::new(x)), args, - )) + ) + }, + &syn::Ty::Tup(ref tys) => { + if tys.len() == 0 { + return Ok(None); + } + return Err(format!("tuples are not supported as types")) } - _ => Err(format!("unexpected type")), - } + _ => return Err(format!("unexpected type")), + }; + + return Ok(Some(converted)); } pub fn add_deps_with_generics(&self, generic_params: &Vec, library: &Library, out: &mut Vec) { @@ -286,7 +315,7 @@ impl Function { extern_decl: bool) -> ConvertResult { let args = try!(decl.inputs.iter() - .try_map(|x| x.as_ident_and_type())); + .try_skip_map(|x| x.as_ident_and_type())); let ret = try!(decl.output.as_type()); Ok(Function { @@ -426,15 +455,16 @@ impl Struct { let fields = match decl { &syn::VariantData::Struct(ref fields) => { try!(fields.iter() - .try_map(|x| x.as_ident_and_type())) + .try_skip_map(|x| x.as_ident_and_type())) } &syn::VariantData::Tuple(ref fields) => { let mut out = Vec::new(); let mut current = 0; for field in fields { - out.push((format!("{}", current), - try!(Type::convert(&field.ty)))); - current += 1; + if let Some(x) = try!(Type::convert(&field.ty)) { + out.push((format!("{}", current), x)); + current += 1; + } } out } @@ -817,11 +847,15 @@ impl Typedef { pub fn convert(name: String, annotations: AnnotationSet, ty: &syn::Ty) -> ConvertResult { - Ok(Typedef { - name: name, - annotations: annotations, - aliased: try!(Type::convert(ty)), - }) + if let Some(x) = try!(Type::convert(ty)) { + Ok(Typedef { + name: name, + annotations: annotations, + aliased: x, + }) + } else { + Err(format!("cannot have a typedef of a zero sized type")) + } } pub fn add_deps(&self, library: &Library, out: &mut Vec) { diff --git a/src/bindgen/utilities.rs b/src/bindgen/utilities.rs index 0438fb4..191bf79 100644 --- a/src/bindgen/utilities.rs +++ b/src/bindgen/utilities.rs @@ -13,16 +13,18 @@ pub fn find_first_some(slice: &[Option]) -> Option<&T> { } pub trait IterHelpers : Iterator { - fn try_map(&mut self, f: F) -> Result, E> - where F: FnMut(&Self::Item) -> Result; + fn try_skip_map(&mut self, f: F) -> Result, E> + where F: FnMut(&Self::Item) -> Result, E>; } impl IterHelpers for I where I: Iterator { - fn try_map(&mut self, mut f: F) -> Result, E> - where F: FnMut(&Self::Item) -> Result + fn try_skip_map(&mut self, mut f: F) -> Result, E> + where F: FnMut(&Self::Item) -> Result, E> { let mut out = Vec::new(); while let Some(item) = self.next() { - out.push(try!(f(&item))); + if let Some(x) = try!(f(&item)) { + out.push(x); + } } Ok(out) } @@ -129,19 +131,29 @@ impl SynFnRetTyHelpers for FunctionRetTy { fn as_type(&self) -> ConvertResult> { match self { &FunctionRetTy::Default => Ok(None), - &FunctionRetTy::Ty(ref t) => Ok(Some(try!(Type::convert(t)))), + &FunctionRetTy::Ty(ref t) => { + if let Some(x) = try!(Type::convert(t)) { + Ok(Some(x)) + } else { + Ok(None) + } + }, } } } pub trait SynFnArgHelpers { - fn as_ident_and_type(&self) -> ConvertResult<(String, Type)>; + fn as_ident_and_type(&self) -> ConvertResult>; } impl SynFnArgHelpers for FnArg { - fn as_ident_and_type(&self) -> ConvertResult<(String, Type)> { + fn as_ident_and_type(&self) -> ConvertResult> { match self { &FnArg::Captured(Pat::Ident(_, ref ident, _), ref ty) => { - Ok((ident.to_string(), try!(Type::convert(ty)))) + if let Some(x) = try!(Type::convert(ty)) { + Ok(Some((ident.to_string(), x))) + } else { + Ok(None) + } } _ => Err(format!("unexpected param type")), } @@ -149,14 +161,18 @@ impl SynFnArgHelpers for FnArg { } pub trait SynFieldHelpers { - fn as_ident_and_type(&self) -> ConvertResult<(String, Type)>; + fn as_ident_and_type(&self) -> ConvertResult>; } impl SynFieldHelpers for Field { - fn as_ident_and_type(&self) -> ConvertResult<(String, Type)> { + fn as_ident_and_type(&self) -> ConvertResult> { let ident = try!(self.ident.as_ref().ok_or(format!("missing ident"))).clone(); let converted_ty = try!(Type::convert(&self.ty)); - Ok((ident.to_string(), converted_ty)) + if let Some(x) = converted_ty { + Ok(Some((ident.to_string(), x))) + } else { + Ok(None) + } } } @@ -200,11 +216,8 @@ impl SynPathHelpers for Path { return Err(format!("Generic parameter contains bindings, or lifetimes")); } - let mut generics = Vec::new(); - for ty in &d.types { - generics.push(try!(Type::convert(ty))); - } - generics + try!(d.types.iter() + .try_skip_map(|x| Type::convert(x))) } &PathParameters::Parenthesized(_) => { return Err(format!("Path contains parentheses"));