const DEFAULT_IMPORTS: &'static str = "
use alloc::str::FromStr;
+use alloc::string::String;
use core::ffi::c_void;
use core::convert::Infallible;
use bitcoin::hashes::Hash;
writeln!(w, ")").unwrap();
writeln!(w, "}}").unwrap();
+
+ writeln!(w, "#[allow(unused)]").unwrap();
+ writeln!(w, "pub(crate) extern \"C\" fn {}_write_void(obj: *const c_void) -> crate::c_types::derived::CVec_u8Z {{", for_obj).unwrap();
if has_inner {
- writeln!(w, "#[no_mangle]").unwrap();
- writeln!(w, "pub(crate) extern \"C\" fn {}_write_void(obj: *const c_void) -> crate::c_types::derived::CVec_u8Z {{", for_obj).unwrap();
writeln!(w, "\tcrate::c_types::serialize_obj(unsafe {{ &*(obj as *const native{}) }})", for_obj).unwrap();
- writeln!(w, "}}").unwrap();
+ } else {
+ writeln!(w, "\t{}_write(unsafe {{ &*(obj as *const {}) }})", for_obj, for_obj).unwrap();
}
+ writeln!(w, "}}").unwrap();
},
"lightning::util::ser::Readable"|"lightning::util::ser::ReadableArgs"|"lightning::util::ser::MaybeReadable" => {
// Create the Result<Object, DecodeError> syn::Type
} } }
macro_rules! get_module_type_resolver {
- ($module: expr, $crate_libs: expr, $crate_types: expr) => { {
- let module: &str = &$module;
+ ($type_in_module: expr, $crate_types: expr) => { {
+ let module: &str = &$type_in_module;
let mut module_iter = module.rsplitn(2, "::");
module_iter.next().unwrap();
let module = module_iter.next().unwrap();
(s, _i, _) => {
if let Some(supertrait) = types.crate_types.traits.get(s) {
supertrait_name = s.to_string();
- supertrait_resolver = get_module_type_resolver!(supertrait_name, types.crate_libs, types.crate_types);
+ supertrait_resolver = get_module_type_resolver!(supertrait_name, types.crate_types);
gen_types.learn_associated_types(&supertrait, &supertrait_resolver);
break;
}
writeln!(w, "\ttype {} = crate::{};", t.ident, $type_resolver.resolve_path(&tr.path, Some(&gen_types))).unwrap();
for bound in bounds_iter {
if let syn::TypeParamBound::Trait(t) = bound {
- // We only allow for `?Sized` here.
- if let syn::TraitBoundModifier::Maybe(_) = t.modifier {} else { panic!(); }
+ // We only allow for `Sized` here.
assert_eq!(t.path.segments.len(), 1);
assert_eq!(format!("{}", t.path.segments[0].ident), "Sized");
}
writeln!(w, "unsafe impl Send for {} {{}}", trait_name).unwrap();
writeln!(w, "unsafe impl Sync for {} {{}}", trait_name).unwrap();
- writeln!(w, "#[no_mangle]").unwrap();
- writeln!(w, "pub(crate) extern \"C\" fn {}_clone_fields(orig: &{}) -> {} {{", trait_name, trait_name, trait_name).unwrap();
+ writeln!(w, "#[allow(unused)]").unwrap();
+ writeln!(w, "pub(crate) fn {}_clone_fields(orig: &{}) -> {} {{", trait_name, trait_name, trait_name).unwrap();
writeln!(w, "\t{} {{", trait_name).unwrap();
writeln!(w, "\t\tthis_arg: orig.this_arg,").unwrap();
for (field, clone_fn, _) in generated_fields.iter() {
},
(s, i, generic_args) => {
if let Some(supertrait) = types.crate_types.traits.get(s) {
- let resolver = get_module_type_resolver!(s, types.crate_libs, types.crate_types);
+ let resolver = get_module_type_resolver!(s, types.crate_types);
macro_rules! impl_supertrait {
($s: expr, $supertrait: expr, $i: expr, $generic_args: expr) => {
- let resolver = get_module_type_resolver!($s, types.crate_libs, types.crate_types);
+ let resolver = get_module_type_resolver!($s, types.crate_types);
// Blindly assume that the same imports where `supertrait` is defined are also
// imported here. This will almost certainly break at some point, but it should be
writeln!(w, "// directly as a Deref trait in higher-level structs:").unwrap();
writeln!(w, "impl core::ops::Deref for {} {{\n\ttype Target = Self;", trait_name).unwrap();
writeln!(w, "\tfn deref(&self) -> &Self {{\n\t\tself\n\t}}\n}}").unwrap();
+ writeln!(w, "impl core::ops::DerefMut for {} {{", trait_name).unwrap();
+ writeln!(w, "\tfn deref_mut(&mut self) -> &mut Self {{\n\t\tself\n\t}}\n}}").unwrap();
}
writeln!(w, "/// Calls the free function if one is set").unwrap();
if all_fields_settable {
// Build a constructor!
writeln!(w, "/// Constructs a new {} given each field", struct_name).unwrap();
+ match &s.fields {
+ syn::Fields::Named(fields) => {
+ writeln_arg_docs(w, &[], "", types, Some(&gen_types),
+ fields.named.iter().map(|field| (format!("{}_arg", field.ident.as_ref().unwrap()), &field.ty)),
+ None);
+ },
+ syn::Fields::Unnamed(fields) => {
+ writeln_arg_docs(w, &[], "", types, Some(&gen_types),
+ fields.unnamed.iter().enumerate().map(|(idx, field)| (format!("{}_arg", ('a' as u8 + idx as u8)), &field.ty)),
+ None);
+ },
+ syn::Fields::Unit => {},
+ }
write!(w, "#[must_use]\n#[no_mangle]\npub extern \"C\" fn {}_new(", struct_name).unwrap();
match &s.fields {
(s, _i, _) => {
if let Some(supertrait) = types.crate_types.traits.get(s) {
supertrait_name = s.to_string();
- supertrait_resolver = get_module_type_resolver!(supertrait_name, types.crate_libs, types.crate_types);
+ supertrait_resolver = get_module_type_resolver!(supertrait_name, types.crate_types);
gen_types.learn_associated_types(&supertrait, &supertrait_resolver);
break;
}
// mappings from a trai defined in a different file, we may mis-resolve or
// fail to resolve the mapped types. Thus, we have to construct a new
// resolver for the module that the trait was defined in here first.
- let mut trait_resolver = get_module_type_resolver!(full_trait_path, types.crate_libs, types.crate_types);
+ let mut trait_resolver = get_module_type_resolver!(full_trait_path, types.crate_types);
gen_types.learn_associated_types(trait_obj, &trait_resolver);
let mut impl_associated_types = HashMap::new();
for item in i.items.iter() {
if is_type_unconstructable(&resolved_path) {
writeln!(w, "\t\tunreachable!();").unwrap();
} else {
- writeln!(w, "\t\tlet mut rust_obj = {} {{ inner: ObjOps::heap_alloc(obj), is_owned: true }};", ident).unwrap();
- writeln!(w, "\t\tlet mut ret = {}_as_{}(&rust_obj);", ident, trait_obj.ident).unwrap();
- writeln!(w, "\t\t// We want to free rust_obj when ret gets drop()'d, not rust_obj, so wipe rust_obj's pointer and set ret's free() fn").unwrap();
- writeln!(w, "\t\trust_obj.inner = core::ptr::null_mut();").unwrap();
+ types.write_to_c_conversion_new_var(w, &format_ident!("obj"), &*i.self_ty, Some(&gen_types), false);
+ write!(w, "\t\tlet rust_obj = ").unwrap();
+ types.write_to_c_conversion_inline_prefix(w, &*i.self_ty, Some(&gen_types), false);
+ write!(w, "obj").unwrap();
+ types.write_to_c_conversion_inline_suffix(w, &*i.self_ty, Some(&gen_types), false);
+ writeln!(w, ";\n\t\tlet mut ret = {}_as_{}(&rust_obj);", ident, trait_obj.ident).unwrap();
+ writeln!(w, "\t\t// We want to free rust_obj when ret gets drop()'d, not rust_obj, so forget it and set ret's free() fn").unwrap();
+ writeln!(w, "\t\tcore::mem::forget(rust_obj);").unwrap();
writeln!(w, "\t\tret.free = Some({}_free_void);", ident).unwrap();
writeln!(w, "\t\tret").unwrap();
}
writeln!(w, "/// This copies the `inner` pointer in this_arg and thus the returned {} must be freed before this_arg is", trait_obj.ident).unwrap();
write!(w, "#[no_mangle]\npub extern \"C\" fn {}_as_{}(this_arg: &{}) -> crate::{} {{\n", ident, trait_obj.ident, ident, full_trait_path).unwrap();
writeln!(w, "\tcrate::{} {{", full_trait_path).unwrap();
- writeln!(w, "\t\tthis_arg: unsafe {{ ObjOps::untweak_ptr((*this_arg).inner) as *mut c_void }},").unwrap();
+ if types.c_type_has_inner_from_path(&resolved_path) {
+ writeln!(w, "\t\tthis_arg: unsafe {{ ObjOps::untweak_ptr((*this_arg).inner) as *mut c_void }},").unwrap();
+ } else {
+ writeln!(w, "\t\tthis_arg: unsafe {{ ObjOps::untweak_ptr(this_arg as *const {} as *mut {}) as *mut c_void }},", ident, ident).unwrap();
+ }
writeln!(w, "\t\tfree: None,").unwrap();
macro_rules! write_meth {
}
write_impl_fields!(s, supertrait_obj, t, "\t", types);
- let resolver = get_module_type_resolver!(s, types.crate_libs, types.crate_types);
+ let resolver = get_module_type_resolver!(s, types.crate_types);
walk_supertraits!(supertrait_obj, Some(&resolver), (
(s, t, _) => {
if let Some(supertrait_obj) = types.crate_types.traits.get(s) {
writeln!(w, "extern \"C\" fn {}_{}_cloned(new_obj: &mut crate::{}) {{", trait_obj.ident, ident, full_trait_path).unwrap();
writeln!(w, "\tnew_obj.this_arg = {}_clone_void(new_obj.this_arg);", ident).unwrap();
writeln!(w, "\tnew_obj.free = Some({}_free_void);", ident).unwrap();
- walk_supertraits!(trait_obj, Some(&types), (
- (s, t, _) => {
- if types.crate_types.traits.get(s).is_some() {
- assert!(!types.is_clonable(s)); // We don't currently support cloning with a clonable supertrait
- writeln!(w, "\tnew_obj.{}.this_arg = new_obj.this_arg;", t).unwrap();
- writeln!(w, "\tnew_obj.{}.free = None;", t).unwrap();
+
+ fn seek_supertraits<W: std::io::Write>(w: &mut W, pfx: &str, tr: &syn::ItemTrait, types: &TypeResolver) {
+ walk_supertraits!(tr, Some(types), (
+ (s, t, _) => {
+ if types.crate_types.traits.get(s).is_some() {
+ assert!(!types.is_clonable(s)); // We don't currently support cloning with a clonable supertrait
+ writeln!(w, "\tnew_obj.{}{}.this_arg = new_obj.this_arg;", pfx, t).unwrap();
+ writeln!(w, "\tnew_obj.{}{}.free = None;", pfx, t).unwrap();
+ let tr = types.crate_types.traits.get(s).unwrap();
+ let resolver = get_module_type_resolver!(s, types.crate_types);
+ seek_supertraits(w, &format!("{}.", t), tr, &resolver);
+ }
}
- }
- ) );
+ ) );
+ }
+ seek_supertraits(w, "", trait_obj, types);
writeln!(w, "}}").unwrap();
}
write!(w, "\n").unwrap();
writeln!(w, "#[allow(unused)]").unwrap();
writeln!(w, "/// Used only if an object of this type is returned as a trait impl by a method").unwrap();
writeln!(w, "pub(crate) extern \"C\" fn {}_clone_void(this_ptr: *const c_void) -> *mut c_void {{", ident).unwrap();
- writeln!(w, "\tBox::into_raw(Box::new(unsafe {{ (*(this_ptr as *mut native{})).clone() }})) as *mut c_void", ident).unwrap();
+ writeln!(w, "\tBox::into_raw(Box::new(unsafe {{ (*(this_ptr as *const native{})).clone() }})) as *mut c_void", ident).unwrap();
writeln!(w, "}}").unwrap();
writeln!(w, "#[no_mangle]").unwrap();
writeln!(w, "/// Creates a copy of the {}", ident).unwrap();
writeln!(w, "pub extern \"C\" fn {}_clone(orig: &{}) -> {} {{", e.ident, e.ident, e.ident).unwrap();
writeln!(w, "\torig.clone()").unwrap();
writeln!(w, "}}").unwrap();
+ writeln!(w, "#[allow(unused)]").unwrap();
+ writeln!(w, "/// Used only if an object of this type is returned as a trait impl by a method").unwrap();
+ writeln!(w, "pub(crate) extern \"C\" fn {}_clone_void(this_ptr: *const c_void) -> *mut c_void {{", e.ident).unwrap();
+ writeln!(w, "\tBox::into_raw(Box::new(unsafe {{ (*(this_ptr as *const {})).clone() }})) as *mut c_void", e.ident).unwrap();
+ writeln!(w, "}}").unwrap();
}
+
+ writeln!(w, "#[allow(unused)]").unwrap();
+ writeln!(w, "/// Used only if an object of this type is returned as a trait impl by a method").unwrap();
+ writeln!(w, "pub(crate) extern \"C\" fn {}_free_void(this_ptr: *mut c_void) {{", e.ident).unwrap();
+ writeln!(w, "\tlet _ = unsafe {{ Box::from_raw(this_ptr as *mut {}) }};\n}}", e.ident).unwrap();
+
w.write_all(&constr).unwrap();
write_cpp_wrapper(cpp_headers, &format!("{}", e.ident), needs_free, None);
}