+ /// 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 {
}
/// Gets the ExportStatus of an object (struct, fn, etc) given its attributes.
pub fn export_status(attrs: &[syn::Attribute]) -> ExportStatus {
let line = format!("{}", lit);
if line.contains("(C-not exported)") {
return ExportStatus::NoExport;
let line = format!("{}", lit);
if line.contains("(C-not exported)") {
return ExportStatus::NoExport;
for field in fields.named.iter() {
match export_status(&field.attrs) {
ExportStatus::Export|ExportStatus::TestOnly => {},
for field in fields.named.iter() {
match export_status(&field.attrs) {
ExportStatus::Export|ExportStatus::TestOnly => {},
for field in fields.unnamed.iter() {
match export_status(&field.attrs) {
ExportStatus::Export|ExportStatus::TestOnly => {},
for field in fields.unnamed.iter() {
match export_status(&field.attrs) {
ExportStatus::Export|ExportStatus::TestOnly => {},
if path == "Sized" { continue; }
if non_lifetimes_processed { return false; }
non_lifetimes_processed = true;
if path == "Sized" { continue; }
if non_lifetimes_processed { return false; }
non_lifetimes_processed = true;
if p.path.leading_colon.is_some() { return false; }
let mut p_iter = p.path.segments.iter();
if let Some(gen) = self.typed_generics.get_mut(&p_iter.next().unwrap().ident) {
if p.path.leading_colon.is_some() { return false; }
let mut p_iter = p.path.segments.iter();
if let Some(gen) = self.typed_generics.get_mut(&p_iter.next().unwrap().ident) {
if &format!("{}", p_iter.next().unwrap().ident) != "Target" { return false; }
let mut non_lifetimes_processed = false;
if &format!("{}", p_iter.next().unwrap().ident) != "Target" { return false; }
let mut non_lifetimes_processed = false;
// implement Deref<Target=Self> for relevant types). We don't
// bother to implement it for associated types, however, so we just
// ignore such bounds.
// implement Deref<Target=Self> for relevant types). We don't
// bother to implement it for associated types, however, so we just
// ignore such bounds.
ExportStatus::Export => { declared.insert(s.ident.clone(), DeclType::StructImported); },
ExportStatus::NoExport => { declared.insert(s.ident.clone(), DeclType::StructIgnored); },
ExportStatus::TestOnly => continue,
ExportStatus::Export => { declared.insert(s.ident.clone(), DeclType::StructImported); },
ExportStatus::NoExport => { declared.insert(s.ident.clone(), DeclType::StructIgnored); },
ExportStatus::TestOnly => continue,
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); },
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); },
- 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,
"[u8; 3]" if !is_ref => Some("crate::c_types::ThreeBytes"), // Used for RGB values
"str" if is_ref => Some("crate::c_types::Str"),
"[u8; 3]" if !is_ref => Some("crate::c_types::ThreeBytes"), // Used for RGB values
"str" if is_ref => Some("crate::c_types::Str"),
"std::time::SystemTime" => Some("u64"),
"std::io::Error" => Some("crate::c_types::IOError"),
"std::time::SystemTime" => Some("u64"),
"std::io::Error" => Some("crate::c_types::IOError"),
"lightning::ln::PaymentHash" if !is_ref => Some("crate::c_types::ThirtyTwoBytes"),
"lightning::ln::PaymentPreimage" if is_ref => Some("*const [u8; 32]"),
"lightning::ln::PaymentPreimage" if !is_ref => Some("crate::c_types::ThirtyTwoBytes"),
"lightning::ln::PaymentHash" if !is_ref => Some("crate::c_types::ThirtyTwoBytes"),
"lightning::ln::PaymentPreimage" if is_ref => Some("*const [u8; 32]"),
"lightning::ln::PaymentPreimage" if !is_ref => Some("crate::c_types::ThirtyTwoBytes"),
- "lightning::ln::PaymentSecret" if is_ref => Some("crate::c_types::ThirtyTwoBytes"),
- "lightning::ln::PaymentSecret" if !is_ref => Some("crate::c_types::ThirtyTwoBytes"),
+ "lightning::ln::PaymentSecret" => Some("crate::c_types::ThirtyTwoBytes"),
// Override the default since Records contain an fmt with a lifetime:
"lightning::util::logger::Record" => Some("*const std::os::raw::c_char"),
// Override the default since Records contain an fmt with a lifetime:
"lightning::util::logger::Record" => Some("*const std::os::raw::c_char"),
"[usize]" if is_ref => Some(""),
"str" if is_ref => Some(""),
"[usize]" if is_ref => Some(""),
"str" 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.
// Note that we'll panic for String if is_ref, as we only have non-owned memory, we
// cannot create a &String.
"std::time::SystemTime" => Some("(::std::time::SystemTime::UNIX_EPOCH + std::time::Duration::from_secs("),
"bech32::u5" => Some(""),
"std::time::SystemTime" => Some("(::std::time::SystemTime::UNIX_EPOCH + std::time::Duration::from_secs("),
"bech32::u5" => Some(""),
"[usize]" if is_ref => Some(".to_slice()"),
"str" if is_ref => Some(".into_str()"),
"[usize]" if is_ref => Some(".to_slice()"),
"str" if is_ref => Some(".into_str()"),
"std::time::SystemTime" => Some("))"),
"bech32::u5" => Some(".into()"),
"std::time::SystemTime" => Some("))"),
"bech32::u5" => Some(".into()"),
"[usize]" if is_ref => Some("local_"),
"str" if is_ref => Some(""),
"[usize]" if is_ref => Some("local_"),
"str" if is_ref => Some(""),
"std::time::SystemTime" => Some(""),
"std::io::Error" if !is_ref => Some("crate::c_types::IOError::from_rust("),
"std::time::SystemTime" => Some(""),
"std::io::Error" if !is_ref => Some("crate::c_types::IOError::from_rust("),
"lightning::ln::PaymentHash" if !is_ref => Some("crate::c_types::ThirtyTwoBytes { data: "),
"lightning::ln::PaymentPreimage" if is_ref => Some("&"),
"lightning::ln::PaymentPreimage" => Some("crate::c_types::ThirtyTwoBytes { data: "),
"lightning::ln::PaymentHash" if !is_ref => Some("crate::c_types::ThirtyTwoBytes { data: "),
"lightning::ln::PaymentPreimage" if is_ref => Some("&"),
"lightning::ln::PaymentPreimage" => Some("crate::c_types::ThirtyTwoBytes { data: "),
// Override the default since Records contain an fmt with a lifetime:
"lightning::util::logger::Record" => Some("local_"),
// Override the default since Records contain an fmt with a lifetime:
"lightning::util::logger::Record" => Some("local_"),
"[usize]" if is_ref => Some(""),
"str" if is_ref => Some(".into()"),
"[usize]" if is_ref => Some(""),
"str" if is_ref => Some(".into()"),
- "String" if is_ref => Some(".as_str().into()"),
- "String" => Some(".into()"),
+ "alloc::string::String"|"String" if is_ref => Some(".as_str().into()"),
+ "alloc::string::String"|"String" => Some(".into()"),
"std::time::SystemTime" => Some(".duration_since(::std::time::SystemTime::UNIX_EPOCH).expect(\"Times must be post-1970\").as_secs()"),
"std::io::Error" if !is_ref => Some(")"),
"std::time::SystemTime" => Some(".duration_since(::std::time::SystemTime::UNIX_EPOCH).expect(\"Times must be post-1970\").as_secs()"),
"std::io::Error" if !is_ref => Some(")"),
"lightning::ln::PaymentHash" => Some(".0 }"),
"lightning::ln::PaymentPreimage" if is_ref => Some(".0"),
"lightning::ln::PaymentPreimage" => Some(".0 }"),
"lightning::ln::PaymentHash" => Some(".0 }"),
"lightning::ln::PaymentPreimage" if is_ref => Some(".0"),
"lightning::ln::PaymentPreimage" => Some(".0 }"),
// Override the default since Records contain an fmt with a lifetime:
"lightning::util::logger::Record" => Some(".as_ptr()"),
// Override the default since Records contain an fmt with a lifetime:
"lightning::util::logger::Record" => Some(".as_ptr()"),
Some(("Vec::new(); for item in ", vec![(format!(".iter() {{ local_{}.push(", var_name), "*item".to_string())], "); }", ContainerPrefixLocation::PerConv))
},
"Option" => {
Some(("Vec::new(); for item in ", vec![(format!(".iter() {{ local_{}.push(", var_name), "*item".to_string())], "); }", ContainerPrefixLocation::PerConv))
},
"Option" => {
- if let Some(syn::Type::Path(p)) = single_contained {
- let inner_path = self.resolve_path(&p.path, generics);
+ let contained_struct = if let Some(syn::Type::Path(p)) = single_contained {
+ Some(self.resolve_path(&p.path, generics))
+ } else if let Some(syn::Type::Reference(r)) = single_contained {
+ if let syn::Type::Path(p) = &*r.elem {
+ Some(self.resolve_path(&p.path, generics))
+ } else { None }
+ } else { None };
+ if let Some(inner_path) = contained_struct {
if self.is_primitive(&inner_path) {
return Some(("if ", vec![
(format!(".is_none() {{ {}::COption_{}Z::None }} else {{ ", Self::generated_container_path(), inner_path),
format!("{}::COption_{}Z::Some({}.unwrap())", Self::generated_container_path(), inner_path, var_access))
], " }", ContainerPrefixLocation::NoPrefix));
} else if self.c_type_has_inner_from_path(&inner_path) {
if self.is_primitive(&inner_path) {
return Some(("if ", vec![
(format!(".is_none() {{ {}::COption_{}Z::None }} else {{ ", Self::generated_container_path(), inner_path),
format!("{}::COption_{}Z::Some({}.unwrap())", Self::generated_container_path(), inner_path, var_access))
], " }", ContainerPrefixLocation::NoPrefix));
} else if self.c_type_has_inner_from_path(&inner_path) {
- (".is_none() { std::ptr::null() } else { ".to_owned(), format!("({}.as_ref().unwrap())", var_access))
+ (".is_none() { std::ptr::null() } else { ".to_owned(),
+ format!("({}{}.unwrap())", var_access, if is_inner_ref { "" } else { ".as_ref()" }))
], " }", ContainerPrefixLocation::OutsideConv));
} else {
return Some(("if ", vec![
], " }", ContainerPrefixLocation::OutsideConv));
} else {
return Some(("if ", vec![
let full_path = self.resolve_path(&p.path, None);
self.c_type_has_inner_from_path(&full_path)
},
let full_path = self.resolve_path(&p.path, None);
self.c_type_has_inner_from_path(&full_path)
},
/// unint'd memory).
pub fn write_empty_rust_val<W: std::io::Write>(&self, generics: Option<&GenericTypes>, w: &mut W, t: &syn::Type) {
match t {
/// unint'd memory).
pub fn write_empty_rust_val<W: std::io::Write>(&self, generics: Option<&GenericTypes>, w: &mut W, t: &syn::Type) {
match t {
syn::Type::Path(p) => {
let resolved = self.resolve_path(&p.path, generics);
if self.crate_types.opaques.get(&resolved).is_some() {
syn::Type::Path(p) => {
let resolved = self.resolve_path(&p.path, generics);
if self.crate_types.opaques.get(&resolved).is_some() {
/// See EmptyValExpectedTy for information on return types.
fn write_empty_rust_val_check_suffix<W: std::io::Write>(&self, generics: Option<&GenericTypes>, w: &mut W, t: &syn::Type) -> EmptyValExpectedTy {
match t {
/// See EmptyValExpectedTy for information on return types.
fn write_empty_rust_val_check_suffix<W: std::io::Write>(&self, generics: Option<&GenericTypes>, w: &mut W, t: &syn::Type) -> EmptyValExpectedTy {
match t {
syn::Type::Path(p) => {
let resolved = self.resolve_path(&p.path, generics);
if let Some(arr_ty) = self.is_real_type_array(&resolved) {
syn::Type::Path(p) => {
let resolved = self.resolve_path(&p.path, generics);
if let Some(arr_ty) = self.is_real_type_array(&resolved) {
/// Prints a suffix to determine if a variable is empty (ie was set by write_empty_rust_val).
pub fn write_empty_rust_val_check<W: std::io::Write>(&self, generics: Option<&GenericTypes>, w: &mut W, t: &syn::Type, var_access: &str) {
match t {
/// Prints a suffix to determine if a variable is empty (ie was set by write_empty_rust_val).
pub fn write_empty_rust_val_check<W: std::io::Write>(&self, generics: Option<&GenericTypes>, w: &mut W, t: &syn::Type, var_access: &str) {
match t {
syn::Type::Path(_) => {
write!(w, "{}", var_access).unwrap();
self.write_empty_rust_val_check_suffix(generics, w, t);
syn::Type::Path(_) => {
write!(w, "{}", var_access).unwrap();
self.write_empty_rust_val_check_suffix(generics, w, t);
// pretty manual here and most of the below special-cases are for Options.
let mut needs_ref_map = false;
let mut only_contained_type = None;
// pretty manual here and most of the below special-cases are for Options.
let mut needs_ref_map = false;
let mut only_contained_type = None;
let mut only_contained_has_inner = false;
let mut contains_slice = false;
if $args_len == 1 {
only_contained_has_inner = ty_has_inner;
let arg = $args_iter().next().unwrap();
if let syn::Type::Reference(t) = arg {
let mut only_contained_has_inner = false;
let mut contains_slice = false;
if $args_len == 1 {
only_contained_has_inner = ty_has_inner;
let arg = $args_iter().next().unwrap();
if let syn::Type::Reference(t) = arg {
write!(&mut var, "{}", var_name).unwrap();
let var_access = String::from_utf8(var.into_inner()).unwrap();
write!(&mut var, "{}", var_name).unwrap();
let var_access = String::from_utf8(var.into_inner()).unwrap();
write!(w, "{} {{ ", pfx).unwrap();
let new_var_name = format!("{}_{}", ident, idx);
write!(w, "{} {{ ", pfx).unwrap();
let new_var_name = format!("{}_{}", ident, idx);