X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=c-bindings-gen%2Fsrc%2Ftypes.rs;h=6ea8e284a5286e1e267d01082ab6e8a0967007b6;hb=47b7d6e36914774534f4a80315c8d38e0424a2db;hp=740e8bdd2732fba3cdd4d1a4e62515431c78eae1;hpb=42f443826a74246e49d8fbbd2590c061ca8308be;p=ldk-c-bindings diff --git a/c-bindings-gen/src/types.rs b/c-bindings-gen/src/types.rs index 740e8bd..6ea8e28 100644 --- a/c-bindings-gen/src/types.rs +++ b/c-bindings-gen/src/types.rs @@ -66,6 +66,11 @@ pub enum ExportStatus { Export, NoExport, TestOnly, + /// This is used only for traits to indicate that users should not be able to implement their + /// own version of a trait, but we should export Rust implementations of the trait (and the + /// trait itself). + /// Concretly, this means that we do not implement the Rust trait for the C trait struct. + NotImplementable, } /// Gets the ExportStatus of an object (struct, fn, etc) given its attributes. pub fn export_status(attrs: &[syn::Attribute]) -> ExportStatus { @@ -117,6 +122,8 @@ pub fn export_status(attrs: &[syn::Attribute]) -> ExportStatus { let line = format!("{}", lit); if line.contains("(C-not exported)") { return ExportStatus::NoExport; + } else if line.contains("(C-not implementable)") { + return ExportStatus::NotImplementable; } }, _ => unimplemented!(), @@ -138,6 +145,7 @@ pub fn is_enum_opaque(e: &syn::ItemEnum) -> bool { for field in fields.named.iter() { match export_status(&field.attrs) { ExportStatus::Export|ExportStatus::TestOnly => {}, + ExportStatus::NotImplementable => panic!("(C-not implementable) should only appear on traits!"), ExportStatus::NoExport => return true, } } @@ -145,6 +153,7 @@ pub fn is_enum_opaque(e: &syn::ItemEnum) -> bool { for field in fields.unnamed.iter() { match export_status(&field.attrs) { ExportStatus::Export|ExportStatus::TestOnly => {}, + ExportStatus::NotImplementable => panic!("(C-not implementable) should only appear on traits!"), ExportStatus::NoExport => return true, } } @@ -167,7 +176,7 @@ pub struct GenericTypes<'a, 'b> { self_ty: Option<(String, &'a syn::Path)>, parent: Option<&'b GenericTypes<'b, 'b>>, typed_generics: HashMap<&'a syn::Ident, (String, Option<&'a syn::Path>)>, - default_generics: HashMap<&'a syn::Ident, (&'a syn::Type, syn::Type)>, + default_generics: HashMap<&'a syn::Ident, (syn::Type, syn::Type)>, } impl<'a, 'p: 'a> GenericTypes<'a, 'p> { pub fn new(self_ty: Option<(String, &'a syn::Path)>) -> Self { @@ -188,7 +197,7 @@ impl<'a, 'p: 'a> GenericTypes<'a, 'p> { match generic { syn::GenericParam::Type(type_param) => { let mut non_lifetimes_processed = false; - for bound in type_param.bounds.iter() { + 'bound_loop: for bound in type_param.bounds.iter() { if let syn::TypeParamBound::Trait(trait_bound) = bound { if let Some(ident) = single_ident_generic_path_to_ident(&trait_bound.path) { match &format!("{}", ident) as &str { "Send" => continue, "Sync" => continue, _ => {} } @@ -204,6 +213,26 @@ impl<'a, 'p: 'a> GenericTypes<'a, 'p> { let new_ident = if path != "std::ops::Deref" && path != "core::ops::Deref" { path = "crate::".to_string() + &path; Some(&trait_bound.path) + } else if trait_bound.path.segments.len() == 1 { + // If we're templated on Deref, store + // the reference type in `default_generics` which handles full + // types and not just paths. + if let syn::PathArguments::AngleBracketed(ref args) = + trait_bound.path.segments[0].arguments { + for subargument in args.args.iter() { + match subargument { + syn::GenericArgument::Lifetime(_) => {}, + syn::GenericArgument::Binding(ref b) => { + if &format!("{}", b.ident) != "Target" { return false; } + let default = &b.ty; + self.default_generics.insert(&type_param.ident, (parse_quote!(&#default), parse_quote!(&#default))); + break 'bound_loop; + }, + _ => unimplemented!(), + } + } + None + } else { None } } else { None }; self.typed_generics.insert(&type_param.ident, (path, new_ident)); } else { return false; } @@ -211,7 +240,7 @@ impl<'a, 'p: 'a> GenericTypes<'a, 'p> { } if let Some(default) = type_param.default.as_ref() { assert!(type_param.bounds.is_empty()); - self.default_generics.insert(&type_param.ident, (default, parse_quote!(&#default))); + self.default_generics.insert(&type_param.ident, (default.clone(), parse_quote!(&#default))); } }, _ => {}, @@ -479,6 +508,7 @@ impl<'mod_lifetime, 'crate_lft: 'mod_lifetime> ImportResolver<'mod_lifetime, 'cr ExportStatus::Export => { declared.insert(s.ident.clone(), DeclType::StructImported); }, ExportStatus::NoExport => { declared.insert(s.ident.clone(), DeclType::StructIgnored); }, ExportStatus::TestOnly => continue, + ExportStatus::NotImplementable => panic!("(C-not implementable) should only appear on traits!"), } } }, @@ -499,13 +529,19 @@ impl<'mod_lifetime, 'crate_lft: 'mod_lifetime> ImportResolver<'mod_lifetime, 'cr match export_status(&e.attrs) { ExportStatus::Export if is_enum_opaque(e) => { declared.insert(e.ident.clone(), DeclType::EnumIgnored); }, ExportStatus::Export => { declared.insert(e.ident.clone(), DeclType::MirroredEnum); }, + ExportStatus::NotImplementable => panic!("(C-not implementable) should only appear on traits!"), _ => continue, } } }, - syn::Item::Trait(t) if export_status(&t.attrs) == ExportStatus::Export => { - if let syn::Visibility::Public(_) = t.vis { - declared.insert(t.ident.clone(), DeclType::Trait(t)); + syn::Item::Trait(t) => { + match export_status(&t.attrs) { + ExportStatus::Export|ExportStatus::NotImplementable => { + if let syn::Visibility::Public(_) = t.vis { + declared.insert(t.ident.clone(), DeclType::Trait(t)); + } + }, + _ => continue, } }, syn::Item::Mod(m) => { @@ -914,6 +950,7 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> { "str" if is_ref => Some(""), "alloc::string::String"|"String" => Some(""), + "std::io::Error" if !is_ref => Some(""), // Note that we'll panic for String if is_ref, as we only have non-owned memory, we // cannot create a &String. @@ -980,6 +1017,7 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> { "str" if is_ref => Some(".into_str()"), "alloc::string::String"|"String" => Some(".into_string()"), + "std::io::Error" if !is_ref => Some(".to_rust()"), "std::time::Duration"|"core::time::Duration" => Some(")"), "std::time::SystemTime" => Some("))"),