Skip to content

Commit bfa9148

Browse files
committed
impl X for Y
1 parent 67541ae commit bfa9148

File tree

7 files changed

+533
-263
lines changed

7 files changed

+533
-263
lines changed

c-bindings-gen/src/main.rs

Lines changed: 106 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -248,6 +248,31 @@ fn maybe_print_generics<W: std::io::Write>(w: &mut W, generics: &syn::Generics,
248248
}
249249
}
250250

251+
macro_rules! walk_supertraits { ($t: expr, $types: expr, ($( $pat: pat => $e: expr),*) ) => { {
252+
if $t.colon_token.is_some() {
253+
for st in $t.supertraits.iter() {
254+
match st {
255+
syn::TypeParamBound::Trait(supertrait) => {
256+
if supertrait.paren_token.is_some() || supertrait.lifetimes.is_some() {
257+
unimplemented!();
258+
}
259+
if let Some(ident) = supertrait.path.get_ident() {
260+
match (&format!("{}", ident) as &str, &ident) {
261+
$( $pat => $e, )*
262+
}
263+
} else {
264+
let path = $types.resolve_path(&supertrait.path);
265+
match (&path as &str, &supertrait.path.segments.iter().last().unwrap().ident) {
266+
$( $pat => $e, )*
267+
}
268+
}
269+
},
270+
syn::TypeParamBound::Lifetime(_) => unimplemented!(),
271+
}
272+
}
273+
}
274+
} } }
275+
251276
fn println_trait<'a, W: std::io::Write>(w: &mut W, t: &'a syn::ItemTrait, types: &mut TypeResolver<'a>) {
252277
let trait_name = format!("{}", t.ident);
253278
match export_status(&t.attrs) {
@@ -256,40 +281,15 @@ fn println_trait<'a, W: std::io::Write>(w: &mut W, t: &'a syn::ItemTrait, types:
256281
}
257282
println_docs(w, &t.attrs, "");
258283

259-
macro_rules! walk_supertraits { ($( $pat: pat => $e: expr),*) => { {
260-
if t.colon_token.is_some() {
261-
for st in t.supertraits.iter() {
262-
match st {
263-
syn::TypeParamBound::Trait(supertrait) => {
264-
if supertrait.paren_token.is_some() || supertrait.lifetimes.is_some() {
265-
unimplemented!();
266-
}
267-
if let Some(ident) = supertrait.path.get_ident() {
268-
match (&format!("{}", ident) as &str, &ident) {
269-
$( $pat => $e, )*
270-
}
271-
} else {
272-
let path = types.resolve_path(&supertrait.path);
273-
match (&path as &str, &supertrait.path.segments.iter().last().unwrap().ident) {
274-
$( $pat => $e, )*
275-
}
276-
}
277-
},
278-
syn::TypeParamBound::Lifetime(_) => unimplemented!(),
279-
}
280-
}
281-
}
282-
} } }
283-
284-
walk_supertraits!(
284+
walk_supertraits!(t, types, (
285285
("Clone", _) => write!(w, "#[derive(Clone)]\n").unwrap(),
286286
("std::cmp::Eq", _) => {},
287287
("std::hash::Hash", _) => {},
288288
("Send", _) => {}, ("Sync", _) => {},
289289
(s, _) => {
290290
if !s.starts_with("util::") { unimplemented!(); }
291291
}
292-
);
292+
) );
293293
write!(w, "#[repr(C)]\npub struct {} {{\n", trait_name).unwrap();
294294
write!(w, "\tpub this_arg: *mut c_void,\n").unwrap();
295295
let mut associated_types: HashMap<&syn::Ident, &syn::Ident> = HashMap::new();
@@ -325,7 +325,7 @@ fn println_trait<'a, W: std::io::Write>(w: &mut W, t: &'a syn::ItemTrait, types:
325325
_ => unimplemented!(),
326326
}
327327
}
328-
walk_supertraits!(
328+
walk_supertraits!(t, types, (
329329
("Clone", _) => {},
330330
("std::cmp::Eq", _) => write!(w, "\tpub eq: extern \"C\" fn (this_arg: *const c_void, other_arg: *const c_void) -> bool,\n").unwrap(),
331331
("std::hash::Hash", _) => write!(w, "\tpub hash: extern \"C\" fn (this_arg: *const c_void) -> u64,\n").unwrap(),
@@ -334,9 +334,9 @@ fn println_trait<'a, W: std::io::Write>(w: &mut W, t: &'a syn::ItemTrait, types:
334334
if !s.starts_with("util::") { unimplemented!(); }
335335
write!(w, "\tpub {}: crate::{},\n", i, s).unwrap();
336336
}
337-
);
337+
) );
338338
write!(w, "}}\n").unwrap();
339-
walk_supertraits!(
339+
walk_supertraits!(t, types, (
340340
("Send", _) => write!(w, "unsafe impl Send for {} {{}}\n", trait_name).unwrap(),
341341
("Sync", _) => write!(w, "unsafe impl Sync for {} {{}}\n", trait_name).unwrap(),
342342
("std::cmp::Eq", _) => {
@@ -357,7 +357,7 @@ fn println_trait<'a, W: std::io::Write>(w: &mut W, t: &'a syn::ItemTrait, types:
357357
write!(w, "\tfn get_and_clear_pending_msg_events(&self) -> Vec<lightning::util::events::MessageSendEvent> {{\n").unwrap();
358358
write!(w, "\t\tunimplemented!()\n\t}}\n}}\n").unwrap();
359359
}
360-
);
360+
) );
361361
write!(w, "\nuse {}::{}::{} as ln{};\n", types.orig_crate, types.module_path, t.ident, trait_name).unwrap();
362362
write!(w, "impl ln{}", t.ident).unwrap();
363363
maybe_print_generics(w, &t.generics, types);
@@ -573,8 +573,82 @@ fn println_impl<W: std::io::Write>(w: &mut W, i: &syn::ItemImpl, types: &TypeRes
573573
if trait_path.0.is_some() { unimplemented!(); }
574574
if types.understood_c_path(&trait_path.1) {
575575
eprintln!("WIP: IMPL {:?} FOR {}", trait_path.1, ident);
576+
let full_trait_path = types.resolve_path(&trait_path.1);
577+
let trait_obj = types.crate_types.traits.get(&full_trait_path).unwrap();
578+
let export = export_status(&trait_obj.attrs);
579+
match export {
580+
ExportStatus::Export => {},
581+
ExportStatus::NoExport|ExportStatus::TestOnly => return,
582+
}
583+
write!(w, "#[no_mangle]\npub extern \"C\" fn {}_as_{}(this_arg: *const {}) -> crate::{} {{\n", ident, trait_obj.ident, ident, full_trait_path).unwrap();
584+
write!(w, "\tcrate::{} {{\n\t\tthis_arg: unsafe {{ (*this_arg).inner as *mut c_void }},\n", full_trait_path).unwrap();
585+
586+
for item in i.items.iter() {
587+
match item {
588+
syn::ImplItem::Method(m) => {
589+
let trait_method = trait_obj.items.iter().filter_map(|item| {
590+
if let syn::TraitItem::Method(t_m) = item { Some(t_m) } else { None }
591+
}).find(|trait_meth| trait_meth.sig.ident == m.sig.ident).unwrap();
592+
match export_status(&trait_method.attrs) {
593+
ExportStatus::Export => {},
594+
ExportStatus::NoExport => {
595+
write!(w, "\t\t//XXX: Need to export {}\n", m.sig.ident).unwrap();
596+
continue;
597+
},
598+
ExportStatus::TestOnly => continue,
599+
}
600+
write!(w, "\t\t{}: {}_{}_{},\n", m.sig.ident, ident, trait_obj.ident, m.sig.ident).unwrap();
601+
},
602+
_ => {},
603+
}
604+
}
605+
walk_supertraits!(trait_obj, types, (
606+
(s, t) => {
607+
if s.starts_with("util::") {
608+
let supertrait_obj = types.crate_types.traits.get(s).unwrap();
609+
write!(w, "\t\t{}: crate::{} {{\t\t\tthis_arg: unsafe {{ (*this_arg).inner as *mut c_void }},\n", t, s).unwrap();
610+
// TODO: Expose supertrait methods
611+
write!(w, "\t\t}},\n").unwrap();
612+
}
613+
}
614+
) );
615+
write!(w, "\t}}\n}}\nuse {}::{} as {}TraitImport;\n", types.orig_crate, full_trait_path, trait_obj.ident).unwrap();
616+
617+
for item in i.items.iter() {
618+
match item {
619+
syn::ImplItem::Method(m) => {
620+
let trait_method = trait_obj.items.iter().filter_map(|item| {
621+
if let syn::TraitItem::Method(t_m) = item { Some(t_m) } else { None }
622+
}).find(|trait_meth| trait_meth.sig.ident == m.sig.ident).unwrap();
623+
match export_status(&trait_method.attrs) {
624+
ExportStatus::Export => {},
625+
ExportStatus::NoExport|ExportStatus::TestOnly => continue,
626+
}
627+
write!(w, "extern \"C\" fn {}_{}_{}(", ident, trait_obj.ident, m.sig.ident).unwrap();
628+
print_method_params(w, &m.sig, &HashMap::new(), "c_void", types, Some(&gen_types), true);
629+
write!(w, " {{\n\t").unwrap();
630+
print_method_var_decl_body(w, &m.sig, "", types, Some(&gen_types), false);
631+
let mut takes_self = false;
632+
for inp in m.sig.inputs.iter() {
633+
if let syn::FnArg::Receiver(_) = inp {
634+
takes_self = true;
635+
}
636+
}
637+
if takes_self {
638+
write!(w, "unsafe {{ &*(*(this_arg as *const {})).inner }}.{}(", ident, m.sig.ident).unwrap();
639+
} else {
640+
write!(w, "lightning::{}::{}(", resolved_path, m.sig.ident).unwrap();
641+
}
642+
print_method_call_params(w, &m.sig, types, Some(&gen_types), "", false);
643+
write!(w, "\n}}\n").unwrap();
644+
},
645+
syn::ImplItem::Type(_) => {},
646+
_ => unimplemented!(),
647+
}
648+
}
649+
write!(w, "\n").unwrap();
576650
} else if let Some(trait_ident) = trait_path.1.get_ident() {
577-
//XXX: implement for basic things like ToString and implement traits
651+
//XXX: implement for other things like ToString
578652
match &format!("{}", trait_ident) as &str {
579653
"From" => {},
580654
"Default" => {

c-bindings-gen/src/types.rs

Lines changed: 79 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -276,6 +276,7 @@ impl<'a> TypeResolver<'a> {
276276
return Some("");
277277
}
278278
match full_path {
279+
"bitcoin::secp256k1::key::PublicKey" if is_ref => Some("&"),
279280
"bitcoin::secp256k1::key::PublicKey" => Some(""),
280281
"bitcoin::secp256k1::key::SecretKey" if is_ref => unimplemented!(),
281282
"bitcoin::secp256k1::key::SecretKey" => Some(""),
@@ -340,7 +341,6 @@ impl<'a> TypeResolver<'a> {
340341
return None;
341342
}
342343
match full_path {
343-
"bitcoin::blockdata::script::Script" => Some(("::bitcoin::consensus::encode::serialize(", ")")),
344344
"bitcoin::blockdata::transaction::Transaction" => Some(("::bitcoin::consensus::encode::serialize(", ")")),
345345
"bitcoin::hash_types::Txid" => None,
346346

@@ -358,8 +358,10 @@ impl<'a> TypeResolver<'a> {
358358
match full_path {
359359
"bitcoin::secp256k1::key::PublicKey" if is_ref => Some("crate::c_types::PublicKey::from_rust("),
360360
"bitcoin::secp256k1::key::PublicKey" => Some("crate::c_types::PublicKey::from_rust(&"),
361-
"bitcoin::blockdata::script::Script" => Some("crate::c_types::Script::from_slice(&c_"),
362-
"bitcoin::blockdata::transaction::Transaction" => Some("crate::c_types::Transaction::from_slice(&c_"),
361+
"bitcoin::secp256k1::key::SecretKey" if is_ref => unimplemented!(),
362+
"bitcoin::secp256k1::key::SecretKey" if !is_ref => Some("crate::c_types::SecretKey::from_rust("),
363+
"bitcoin::blockdata::script::Script" if is_ref => Some("crate::c_types::Script::from_slice(&c_"),
364+
"bitcoin::blockdata::transaction::Transaction" if is_ref => Some("crate::c_types::Transaction::from_slice(&c_"),
363365
"bitcoin::hash_types::Txid" => Some(""),
364366

365367
// Override the default since Records contain an fmt with a lifetime:
@@ -384,6 +386,7 @@ impl<'a> TypeResolver<'a> {
384386
}
385387
match full_path {
386388
"bitcoin::secp256k1::key::PublicKey" => Some(")"),
389+
"bitcoin::secp256k1::key::SecretKey" => Some(")"),
387390
"bitcoin::blockdata::script::Script" => Some(")"),
388391
"bitcoin::blockdata::transaction::Transaction" => Some(")"),
389392
"bitcoin::hash_types::Txid" => Some(".into_inner()"),
@@ -467,24 +470,24 @@ impl<'a> TypeResolver<'a> {
467470
self.declared.get(ident)
468471
}
469472

473+
pub fn maybe_resolve_ident(&self, id: &syn::Ident) -> Option<String> {
474+
if let Some(imp) = self.imports.get(id) {
475+
Some(imp.clone())
476+
} else if self.declared.get(id).is_some() {
477+
Some(self.module_path.to_string() + "::" + &format!("{}", id))
478+
} else { None }
479+
}
480+
470481
pub fn maybe_resolve_path(&self, p: &syn::Path) -> Option<String> {
471482
if p.leading_colon.is_some() {
472483
//format!("{}", p.segments);
473484
return None;
474485
} else if let Some(id) = p.get_ident() {
475-
if let Some(imp) = self.imports.get(id) {
476-
Some(imp.clone())
477-
} else if self.declared.get(id).is_some() {
478-
Some(self.module_path.to_string() + "::" + &format!("{}", id))
479-
} else { None }
486+
self.maybe_resolve_ident(id)
480487
} else {
481488
if p.segments.len() == 1 {
482489
let seg = p.segments.iter().next().unwrap();
483-
if let Some(imp) = self.imports.get(&seg.ident) {
484-
return Some(imp.clone());
485-
} else if self.declared.get(&seg.ident).is_some() {
486-
return Some(self.module_path.to_string() + "::" + &format!("{}", seg.ident));
487-
} else { return None; }
490+
return self.maybe_resolve_ident(&seg.ident);
488491
}
489492
let mut seg_iter = p.segments.iter();
490493
let first_seg = seg_iter.next().unwrap();
@@ -845,17 +848,18 @@ impl<'a> TypeResolver<'a> {
845848
} else { unimplemented!(); }
846849
} else { unimplemented!(); }
847850
true
848-
} else {
849-
let ty_ident = single_ident_generic_path_to_ident(&p.path).unwrap();
850-
if let Some(full_path) = self.imports.get(ty_ident) {
851-
if let Some(rust_type) = self.from_c_conversion_new_var_from_path_prefix(&full_path) {
851+
} else if self.is_primitive(&resolved_path) {
852+
false
853+
} else if let Some(ty_ident) = single_ident_generic_path_to_ident(&p.path) {
854+
if let Some(rust_type) = self.from_c_conversion_new_var_from_path_prefix(&resolved_path) {
855+
if let Some(_) = self.imports.get(ty_ident) {
852856
write!(w, "let rust_{} = {}{});", ident, rust_type, ident).unwrap();
853857
true
854858
} else { false }
855859
} else if self.declared.get(ty_ident).is_some() {
856860
false
857-
} else { unimplemented!(); }
858-
}
861+
} else { false }
862+
} else { false }
859863
},
860864
syn::Type::Array(_) => {
861865
// We assume all arrays contain only primitive types.
@@ -901,17 +905,22 @@ impl<'a> TypeResolver<'a> {
901905
if self.is_known_container(&resolved_path) {
902906
write!(w, "rust_").unwrap();
903907
} else {
904-
let ident = single_ident_generic_path_to_ident(&p.path).unwrap();
905-
if let Some(full_path) = self.imports.get(ident) {
906-
if let Some(c_type) = self.from_c_conversion_prefix_from_path(&full_path, is_ref) {
907-
write!(w, "{}", c_type).unwrap();
908+
if let Some(c_type) = self.from_c_conversion_prefix_from_path(&resolved_path, is_ref) {
909+
write!(w, "{}", c_type).unwrap();
910+
} else if let Some(ident) = single_ident_generic_path_to_ident(&p.path) {
911+
if let Some(decl_type) = self.declared.get(ident) {
912+
match decl_type {
913+
DeclType::StructImported(_) if !is_ref => write!(w, "*unsafe {{ Box::from_raw(").unwrap(),
914+
DeclType::StructImported(_) => {},
915+
DeclType::MirroredEnum => {},
916+
_ => unimplemented!(),
917+
}
908918
} else { unimplemented!(); }
909-
} else if let Some(decl_type) = self.declared.get(ident) {
910-
match decl_type {
911-
DeclType::StructImported(_) if !is_ref => write!(w, "*unsafe {{ Box::from_raw(").unwrap(),
912-
DeclType::StructImported(_) => {},
913-
DeclType::MirroredEnum => {},
914-
_ => unimplemented!(),
919+
} else if self.crate_types.structs.get(&resolved_path).is_some() {
920+
if !is_ref {
921+
write!(w, "&unsafe {{ &*").unwrap();
922+
} else {
923+
write!(w, "unsafe {{ &*").unwrap();
915924
}
916925
} else { unimplemented!(); }
917926
}
@@ -964,18 +973,19 @@ impl<'a> TypeResolver<'a> {
964973
if self.is_known_container(&resolved_path) {
965974
write!(w, "").unwrap();
966975
} else {
967-
let ident = single_ident_generic_path_to_ident(&p.path).unwrap();
968-
if let Some(full_path) = self.imports.get(ident) {
969-
if let Some(c_type) = self.from_c_conversion_suffix_from_path(&full_path) {
970-
write!(w, "{}", c_type).unwrap();
976+
if let Some(c_type) = self.from_c_conversion_suffix_from_path(&resolved_path) {
977+
write!(w, "{}", c_type).unwrap();
978+
} else if let Some(ident) = single_ident_generic_path_to_ident(&p.path) {
979+
if let Some(decl_type) = self.declared.get(ident) {
980+
match decl_type {
981+
DeclType::StructImported(_) if !is_ref => write!(w, ".inner as *mut _) }}").unwrap(),
982+
DeclType::StructImported(_) => {},
983+
DeclType::MirroredEnum => write!(w, ".to_ln()").unwrap(),
984+
_ => unimplemented!(),
985+
}
971986
} else { unimplemented!(); }
972-
} else if let Some(decl_type) = self.declared.get(ident) {
973-
match decl_type {
974-
DeclType::StructImported(_) if !is_ref => write!(w, ".inner as *mut _) }}").unwrap(),
975-
DeclType::StructImported(_) => {},
976-
DeclType::MirroredEnum => write!(w, ".to_ln()").unwrap(),
977-
_ => unimplemented!(),
978-
}
987+
} else if self.crate_types.structs.get(&resolved_path).is_some() {
988+
write!(w, ".inner }}").unwrap();
979989
} else { unimplemented!(); }
980990
}
981991
},
@@ -1031,6 +1041,34 @@ impl<'a> TypeResolver<'a> {
10311041
true
10321042
} else { false }
10331043
}
1044+
1045+
fn print_c_path_intern<W: std::io::Write>(&self, w: &mut W, path: &syn::Path, is_ref: bool, is_mut: bool, ptr_for_ref: bool) -> bool {
1046+
let full_path = match self.maybe_resolve_path(&path) {
1047+
Some(path) => path, None => return false };
1048+
if let Some(ident) = single_ident_generic_path_to_ident(&path) {
1049+
self.print_c_ident_intern(w, ident, is_ref, is_mut, ptr_for_ref)
1050+
} else if let Some(t) = self.crate_types.traits.get(&full_path) {
1051+
if is_ref && ptr_for_ref {
1052+
write!(w, "*const crate::{}", full_path).unwrap();
1053+
} else if is_ref {
1054+
write!(w, "&crate::{}", full_path).unwrap();
1055+
} else {
1056+
write!(w, "crate::{}", full_path).unwrap();
1057+
}
1058+
true
1059+
} else if let Some(s) = self.crate_types.structs.get(&full_path) {
1060+
if is_ref && ptr_for_ref {
1061+
write!(w, "*const crate::{}", full_path).unwrap();
1062+
} else if is_ref {
1063+
write!(w, "&crate::{}", full_path).unwrap();
1064+
} else {
1065+
write!(w, "crate::{}", full_path).unwrap();
1066+
}
1067+
true
1068+
} else {
1069+
false
1070+
}
1071+
}
10341072
fn print_c_type_intern<W: std::io::Write>(&self, generics: Option<&GenericTypes>, w: &mut W, t: &syn::Type, is_ref: bool, is_mut: bool, ptr_for_ref: bool) -> bool {
10351073
match t {
10361074
syn::Type::Path(p) => {
@@ -1054,9 +1092,7 @@ impl<'a> TypeResolver<'a> {
10541092
}
10551093
}
10561094
if p.path.leading_colon.is_some() { return false; }
1057-
if let Some(ident) = single_ident_generic_path_to_ident(&p.path) {
1058-
self.print_c_ident_intern(w, &ident, is_ref, is_mut, ptr_for_ref)
1059-
} else { false }
1095+
self.print_c_path_intern(w, &p.path, is_ref, is_mut, ptr_for_ref)
10601096
},
10611097
syn::Type::Reference(r) => {
10621098
if r.lifetime.is_some() { return false; }

0 commit comments

Comments
 (0)