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)>,
}
impl<'a, 'p: 'a> GenericTypes<'a, 'p> {
pub fn new(self_ty: Option<(String, &'a syn::Path)>) -> Self {
- Self { self_ty, parent: None, typed_generics: HashMap::new(), }
+ Self { self_ty, parent: None, typed_generics: HashMap::new(), default_generics: HashMap::new(), }
}
/// push a new context onto the stack, allowing for a new set of generics to be learned which
/// will override any lower contexts, but which will still fall back to resoltion via lower
/// contexts.
pub fn push_ctx<'c>(&'c self) -> GenericTypes<'a, 'c> {
- GenericTypes { self_ty: None, parent: Some(self), typed_generics: HashMap::new(), }
+ GenericTypes { self_ty: None, parent: Some(self), typed_generics: HashMap::new(), default_generics: HashMap::new(), }
}
/// Learn the generics in generics in the current context, given a TypeResolver.
} else { return false; }
}
}
+ 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)));
+ }
},
_ => {},
}
None
}
}
+
/// Attempt to resolve a Path as a generic parameter and return the full path. as both a string
/// and syn::Path.
pub fn maybe_resolve_path<'b>(&'b self, path: &syn::Path) -> Option<(&'b String, &'a syn::Path)> {
}
}
+trait ResolveType<'a> { fn resolve_type(&'a self, ty: &'a syn::Type) -> &'a syn::Type; }
+impl<'a, 'b, 'c: 'a + 'b> ResolveType<'c> for Option<&GenericTypes<'a, 'b>> {
+ fn resolve_type(&'c self, ty: &'c syn::Type) -> &'c syn::Type {
+ if let Some(us) = self {
+ match ty {
+ syn::Type::Path(p) => {
+ if let Some(ident) = p.path.get_ident() {
+ if let Some((ty, _)) = us.default_generics.get(ident) {
+ return ty;
+ }
+ }
+ },
+ syn::Type::Reference(syn::TypeReference { elem, .. }) => {
+ if let syn::Type::Path(p) = &**elem {
+ if let Some(ident) = p.path.get_ident() {
+ if let Some((_, refty)) = us.default_generics.get(ident) {
+ return refty;
+ }
+ }
+ }
+ }
+ _ => {},
+ }
+ }
+ ty
+ }
+}
+
#[derive(Clone, PartialEq)]
// The type of declaration and the object itself
pub enum DeclType<'a> {
priv_modules: HashSet<syn::Ident>,
}
impl<'mod_lifetime, 'crate_lft: 'mod_lifetime> ImportResolver<'mod_lifetime, 'crate_lft> {
- fn process_use_intern(crate_name: &str, dependencies: &HashSet<syn::Ident>, imports: &mut HashMap<syn::Ident, (String, syn::Path)>,
+ fn process_use_intern(crate_name: &str, module_path: &str, dependencies: &HashSet<syn::Ident>, imports: &mut HashMap<syn::Ident, (String, syn::Path)>,
u: &syn::UseTree, partial_path: &str, mut path: syn::punctuated::Punctuated<syn::PathSegment, syn::token::Colon2>) {
let new_path;
macro_rules! push_path {
($ident: expr, $path_suffix: expr) => {
- if partial_path == "" && !dependencies.contains(&$ident) {
+ if partial_path == "" && format!("{}", $ident) == "super" {
+ let mut mod_iter = module_path.rsplitn(2, "::");
+ mod_iter.next().unwrap();
+ let super_mod = mod_iter.next().unwrap();
+ new_path = format!("{}{}", super_mod, $path_suffix);
+ assert_eq!(path.len(), 0);
+ for module in super_mod.split("::") {
+ path.push(syn::PathSegment { ident: syn::Ident::new(module, Span::call_site()), arguments: syn::PathArguments::None });
+ }
+ } else if partial_path == "" && !dependencies.contains(&$ident) {
new_path = format!("{}::{}{}", crate_name, $ident, $path_suffix);
let crate_name_ident = format_ident!("{}", crate_name);
path.push(parse_quote!(#crate_name_ident));
match u {
syn::UseTree::Path(p) => {
push_path!(p.ident, "::");
- Self::process_use_intern(crate_name, dependencies, imports, &p.tree, &new_path, path);
+ Self::process_use_intern(crate_name, module_path, dependencies, imports, &p.tree, &new_path, path);
},
syn::UseTree::Name(n) => {
push_path!(n.ident, "");
},
syn::UseTree::Group(g) => {
for i in g.items.iter() {
- Self::process_use_intern(crate_name, dependencies, imports, i, partial_path, path.clone());
+ Self::process_use_intern(crate_name, module_path, dependencies, imports, i, partial_path, path.clone());
}
},
syn::UseTree::Rename(r) => {
}
}
- fn process_use(crate_name: &str, dependencies: &HashSet<syn::Ident>, imports: &mut HashMap<syn::Ident, (String, syn::Path)>, u: &syn::ItemUse) {
+ fn process_use(crate_name: &str, module_path: &str, dependencies: &HashSet<syn::Ident>, imports: &mut HashMap<syn::Ident, (String, syn::Path)>, u: &syn::ItemUse) {
if let syn::Visibility::Public(_) = u.vis {
// We actually only use these for #[cfg(fuzztarget)]
eprintln!("Ignoring pub(use) tree!");
return;
}
if u.leading_colon.is_some() { eprintln!("Ignoring leading-colon use!"); return; }
- Self::process_use_intern(crate_name, dependencies, imports, &u.tree, "", syn::punctuated::Punctuated::new());
+ Self::process_use_intern(crate_name, module_path, dependencies, imports, &u.tree, "", syn::punctuated::Punctuated::new());
}
fn insert_primitive(imports: &mut HashMap<syn::Ident, (String, syn::Path)>, id: &str) {
}
pub fn new(crate_name: &'mod_lifetime str, dependencies: &'mod_lifetime HashSet<syn::Ident>, module_path: &'mod_lifetime str, contents: &'crate_lft [syn::Item]) -> Self {
+ Self::from_borrowed_items(crate_name, dependencies, module_path, &contents.iter().map(|a| a).collect::<Vec<_>>())
+ }
+ pub fn from_borrowed_items(crate_name: &'mod_lifetime str, dependencies: &'mod_lifetime HashSet<syn::Ident>, module_path: &'mod_lifetime str, contents: &[&'crate_lft syn::Item]) -> Self {
let mut imports = HashMap::new();
// Add primitives to the "imports" list:
Self::insert_primitive(&mut imports, "bool");
for item in contents.iter() {
match item {
- syn::Item::Use(u) => Self::process_use(crate_name, dependencies, &mut imports, &u),
+ syn::Item::Use(u) => Self::process_use(crate_name, module_path, dependencies, &mut imports, &u),
syn::Item::Struct(s) => {
if let syn::Visibility::Public(_) = s.vis {
match export_status(&s.attrs) {
}
} else if let Some(_) = self.priv_modules.get(&first_seg.ident) {
Some(format!("{}::{}{}", self.module_path, first_seg.ident, remaining))
- } else if first_seg_str == "std" || self.dependencies.contains(&first_seg.ident) {
+ } else if first_seg_str == "std" || first_seg_str == "core" || self.dependencies.contains(&first_seg.ident) {
Some(first_seg_str + &remaining)
} else { None }
}
pub fn resolve_imported_refs(&self, mut ty: syn::Type) -> syn::Type {
match &mut ty {
syn::Type::Path(p) => {
-eprintln!("rir {:?}", p);
if p.path.segments.len() != 1 { unimplemented!(); }
let mut args = p.path.segments[0].arguments.clone();
if let syn::PathArguments::AngleBracketed(ref mut generics) = &mut args {
match ty {
"()" => true,
"crate::c_types::Signature" => true,
+ "crate::c_types::RecoverableSignature" => true,
"crate::c_types::TxOut" => true,
_ => false,
}
"[u8; 3]" if !is_ref => Some("crate::c_types::ThreeBytes"), // Used for RGB values
"str" if is_ref => Some("crate::c_types::Str"),
- "String" if !is_ref => Some("crate::c_types::derived::CVec_u8Z"),
- "String" if is_ref => Some("crate::c_types::Str"),
+ "String" => Some("crate::c_types::Str"),
"std::time::Duration" => Some("u64"),
+ "std::time::SystemTime" => Some("u64"),
"std::io::Error" => Some("crate::c_types::IOError"),
"bech32::u5" => Some("crate::c_types::u5"),
"bitcoin::secp256k1::key::PublicKey"|"bitcoin::secp256k1::PublicKey"|"secp256k1::key::PublicKey"
=> Some("crate::c_types::PublicKey"),
"bitcoin::secp256k1::Signature" => Some("crate::c_types::Signature"),
+ "bitcoin::secp256k1::recovery::RecoverableSignature" => Some("crate::c_types::RecoverableSignature"),
"bitcoin::secp256k1::key::SecretKey"|"bitcoin::secp256k1::SecretKey"
if is_ref => Some("*const [u8; 32]"),
"bitcoin::secp256k1::key::SecretKey"|"bitcoin::secp256k1::SecretKey"
"bitcoin::hash_types::Txid"|"bitcoin::hash_types::BlockHash"|"bitcoin_hashes::sha256::Hash"
if !is_ref => Some("crate::c_types::ThirtyTwoBytes"),
"bitcoin::secp256k1::Message" if !is_ref => Some("crate::c_types::ThirtyTwoBytes"),
- "lightning::ln::channelmanager::PaymentHash" if is_ref => Some("*const [u8; 32]"),
- "lightning::ln::channelmanager::PaymentHash" if !is_ref => Some("crate::c_types::ThirtyTwoBytes"),
- "lightning::ln::channelmanager::PaymentPreimage" if is_ref => Some("*const [u8; 32]"),
- "lightning::ln::channelmanager::PaymentPreimage" if !is_ref => Some("crate::c_types::ThirtyTwoBytes"),
- "lightning::ln::channelmanager::PaymentSecret" if is_ref => Some("crate::c_types::ThirtyTwoBytes"),
- "lightning::ln::channelmanager::PaymentSecret" if !is_ref => Some("crate::c_types::ThirtyTwoBytes"),
+ "lightning::ln::PaymentHash" if is_ref => Some("*const [u8; 32]"),
+ "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"),
// 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(""),
- "String" if !is_ref => Some("String::from_utf8("),
+ "String" => Some(""),
// Note that we'll panic for String if is_ref, as we only have non-owned memory, we
// cannot create a &String.
"std::time::Duration" => Some("std::time::Duration::from_secs("),
+ "std::time::SystemTime" => Some("(::std::time::SystemTime::UNIX_EPOCH + std::time::Duration::from_secs("),
"bech32::u5" => Some(""),
=> Some(""),
"bitcoin::secp256k1::Signature" if is_ref => Some("&"),
"bitcoin::secp256k1::Signature" => Some(""),
+ "bitcoin::secp256k1::recovery::RecoverableSignature" => Some(""),
"bitcoin::secp256k1::key::SecretKey"|"bitcoin::secp256k1::SecretKey"
if is_ref => Some("&::bitcoin::secp256k1::key::SecretKey::from_slice(&unsafe { *"),
"bitcoin::secp256k1::key::SecretKey"|"bitcoin::secp256k1::SecretKey"
"bitcoin::hash_types::Txid" if is_ref => Some("&::bitcoin::hash_types::Txid::from_slice(&unsafe { &*"),
"bitcoin::hash_types::Txid" if !is_ref => Some("::bitcoin::hash_types::Txid::from_slice(&"),
"bitcoin::hash_types::BlockHash" => Some("::bitcoin::hash_types::BlockHash::from_slice(&"),
- "lightning::ln::channelmanager::PaymentHash" if !is_ref => Some("::lightning::ln::channelmanager::PaymentHash("),
- "lightning::ln::channelmanager::PaymentHash" if is_ref => Some("&::lightning::ln::channelmanager::PaymentHash(unsafe { *"),
- "lightning::ln::channelmanager::PaymentPreimage" if !is_ref => Some("::lightning::ln::channelmanager::PaymentPreimage("),
- "lightning::ln::channelmanager::PaymentPreimage" if is_ref => Some("&::lightning::ln::channelmanager::PaymentPreimage(unsafe { *"),
- "lightning::ln::channelmanager::PaymentSecret" => Some("::lightning::ln::channelmanager::PaymentSecret("),
+ "lightning::ln::PaymentHash" if !is_ref => Some("::lightning::ln::PaymentHash("),
+ "lightning::ln::PaymentHash" if is_ref => Some("&::lightning::ln::PaymentHash(unsafe { *"),
+ "lightning::ln::PaymentPreimage" if !is_ref => Some("::lightning::ln::PaymentPreimage("),
+ "lightning::ln::PaymentPreimage" if is_ref => Some("&::lightning::ln::PaymentPreimage(unsafe { *"),
+ "lightning::ln::PaymentSecret" => Some("::lightning::ln::PaymentSecret("),
// List of traits we map (possibly during processing of other files):
"crate::util::logger::Logger" => Some(""),
"[u8]" if is_ref => Some(".to_slice()"),
"[usize]" if is_ref => Some(".to_slice()"),
- "str" if is_ref => Some(".into()"),
- "String" if !is_ref => Some(".into_rust()).unwrap()"),
+ "str" if is_ref => Some(".into_str()"),
+ "String" => Some(".into_string()"),
"std::time::Duration" => Some(")"),
+ "std::time::SystemTime" => Some("))"),
"bech32::u5" => Some(".into()"),
"bitcoin::secp256k1::key::PublicKey"|"bitcoin::secp256k1::PublicKey"|"secp256k1::key::PublicKey"
=> Some(".into_rust()"),
"bitcoin::secp256k1::Signature" => Some(".into_rust()"),
+ "bitcoin::secp256k1::recovery::RecoverableSignature" => Some(".into_rust()"),
"bitcoin::secp256k1::key::SecretKey"|"bitcoin::secp256k1::SecretKey"
if !is_ref => Some(".into_rust()"),
"bitcoin::secp256k1::key::SecretKey"|"bitcoin::secp256k1::SecretKey"
"bitcoin::hash_types::Txid" if is_ref => Some(" }[..]).unwrap()"),
"bitcoin::hash_types::Txid" => Some(".data[..]).unwrap()"),
"bitcoin::hash_types::BlockHash" if !is_ref => Some(".data[..]).unwrap()"),
- "lightning::ln::channelmanager::PaymentHash" if !is_ref => Some(".data)"),
- "lightning::ln::channelmanager::PaymentHash" if is_ref => Some(" })"),
- "lightning::ln::channelmanager::PaymentPreimage" if !is_ref => Some(".data)"),
- "lightning::ln::channelmanager::PaymentPreimage" if is_ref => Some(" })"),
- "lightning::ln::channelmanager::PaymentSecret" => Some(".data)"),
+ "lightning::ln::PaymentHash" if !is_ref => Some(".data)"),
+ "lightning::ln::PaymentHash" if is_ref => Some(" })"),
+ "lightning::ln::PaymentPreimage" if !is_ref => Some(".data)"),
+ "lightning::ln::PaymentPreimage" if is_ref => Some(" })"),
+ "lightning::ln::PaymentSecret" => Some(".data)"),
// List of traits we map (possibly during processing of other files):
"crate::util::logger::Logger" => Some(""),
"String" => Some(""),
"std::time::Duration" => Some(""),
+ "std::time::SystemTime" => Some(""),
"std::io::Error" if !is_ref => Some("crate::c_types::IOError::from_rust("),
"bech32::u5" => Some(""),
"bitcoin::secp256k1::key::PublicKey"|"bitcoin::secp256k1::PublicKey"|"secp256k1::key::PublicKey"
=> Some("crate::c_types::PublicKey::from_rust(&"),
"bitcoin::secp256k1::Signature" => Some("crate::c_types::Signature::from_rust(&"),
+ "bitcoin::secp256k1::recovery::RecoverableSignature" => Some("crate::c_types::RecoverableSignature::from_rust(&"),
"bitcoin::secp256k1::key::SecretKey"|"bitcoin::secp256k1::SecretKey"
if is_ref => Some(""),
"bitcoin::secp256k1::key::SecretKey"|"bitcoin::secp256k1::SecretKey"
"bitcoin::hash_types::Txid"|"bitcoin::hash_types::BlockHash"|"bitcoin_hashes::sha256::Hash"
if !is_ref => Some("crate::c_types::ThirtyTwoBytes { data: "),
"bitcoin::secp256k1::Message" if !is_ref => Some("crate::c_types::ThirtyTwoBytes { data: "),
- "lightning::ln::channelmanager::PaymentHash" if is_ref => Some("&"),
- "lightning::ln::channelmanager::PaymentHash" if !is_ref => Some("crate::c_types::ThirtyTwoBytes { data: "),
- "lightning::ln::channelmanager::PaymentPreimage" if is_ref => Some("&"),
- "lightning::ln::channelmanager::PaymentPreimage" => Some("crate::c_types::ThirtyTwoBytes { data: "),
- "lightning::ln::channelmanager::PaymentSecret" if !is_ref => Some("crate::c_types::ThirtyTwoBytes { data: "),
+ "lightning::ln::PaymentHash" if is_ref => Some("&"),
+ "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::PaymentSecret" if !is_ref => Some("crate::c_types::ThirtyTwoBytes { data: "),
// 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()"),
- "String" if !is_ref => Some(".into_bytes().into()"),
"String" if is_ref => Some(".as_str().into()"),
+ "String" => Some(".into()"),
"std::time::Duration" => Some(".as_secs()"),
+ "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(")"),
"bech32::u5" => Some(".into()"),
"bitcoin::secp256k1::key::PublicKey"|"bitcoin::secp256k1::PublicKey"|"secp256k1::key::PublicKey"
=> Some(")"),
"bitcoin::secp256k1::Signature" => Some(")"),
+ "bitcoin::secp256k1::recovery::RecoverableSignature" => Some(")"),
"bitcoin::secp256k1::key::SecretKey"|"bitcoin::secp256k1::SecretKey"
if !is_ref => Some(")"),
"bitcoin::secp256k1::key::SecretKey"|"bitcoin::secp256k1::SecretKey"
"bitcoin::hash_types::Txid"|"bitcoin::hash_types::BlockHash"|"bitcoin_hashes::sha256::Hash"
if !is_ref => Some(".into_inner() }"),
"bitcoin::secp256k1::Message" if !is_ref => Some(".as_ref().clone() }"),
- "lightning::ln::channelmanager::PaymentHash" if is_ref => Some(".0"),
- "lightning::ln::channelmanager::PaymentHash" => Some(".0 }"),
- "lightning::ln::channelmanager::PaymentPreimage" if is_ref => Some(".0"),
- "lightning::ln::channelmanager::PaymentPreimage" => Some(".0 }"),
- "lightning::ln::channelmanager::PaymentSecret" if !is_ref => Some(".0 }"),
+ "lightning::ln::PaymentHash" if is_ref => Some(".0"),
+ "lightning::ln::PaymentHash" => Some(".0 }"),
+ "lightning::ln::PaymentPreimage" if is_ref => Some(".0"),
+ "lightning::ln::PaymentPreimage" => Some(".0 }"),
+ "lightning::ln::PaymentSecret" if !is_ref => Some(".0 }"),
// Override the default since Records contain an fmt with a lifetime:
"lightning::util::logger::Record" => Some(".as_ptr()"),
fn empty_val_check_suffix_from_path(&self, full_path: &str) -> Option<&str> {
match full_path {
- "lightning::ln::channelmanager::PaymentSecret" => Some(".data == [0; 32]"),
+ "lightning::ln::PaymentSecret" => Some(".data == [0; 32]"),
"secp256k1::key::PublicKey"|"bitcoin::secp256k1::key::PublicKey" => Some(".is_null()"),
"bitcoin::secp256k1::Signature" => Some(".is_null()"),
_ => None
LP: Fn(&str, bool, bool) -> Option<String>, DL: Fn(&mut W, &DeclType, &str, bool, bool), SC: Fn(bool, Option<&str>) -> String>
(&self, w: &mut W, t: &syn::Type, generics: Option<&GenericTypes>, is_ref: bool, is_mut: bool, ptr_for_ref: bool,
tupleconv: &str, prefix: bool, sliceconv: SC, path_lookup: LP, decl_lookup: DL) {
- match t {
+ match generics.resolve_type(t) {
syn::Type::Reference(r) => {
self.write_conversion_inline_intern(w, &*r.elem, generics, true, r.mutability.is_some(),
ptr_for_ref, tupleconv, prefix, sliceconv, path_lookup, decl_lookup);
}
fn write_to_c_conversion_inline_prefix_inner<W: std::io::Write>(&self, w: &mut W, t: &syn::Type, generics: Option<&GenericTypes>, is_ref: bool, ptr_for_ref: bool, from_ptr: bool) {
- self.write_conversion_inline_intern(w, t, generics, is_ref, false, ptr_for_ref, "0u8 /*", true, |_, _| "local_".to_owned(),
+ self.write_conversion_inline_intern(w, t, generics, is_ref, false, ptr_for_ref, "() /*", true, |_, _| "local_".to_owned(),
|a, b, c| self.to_c_conversion_inline_prefix_from_path(a, b, c),
|w, decl_type, decl_path, is_ref, _is_mut| {
match decl_type {
} }
}
- match t {
+ match generics.resolve_type(t) {
syn::Type::Reference(r) => {
if let syn::Type::Slice(_) = &*r.elem {
self.write_conversion_new_var_intern(w, ident, var, &*r.elem, generics, is_ref, ptr_for_ref, to_c, path_lookup, container_lookup, var_prefix, var_suffix)
}
self.write_c_mangled_container_path_intern(w, args, generics, ident, is_ref, is_mut, ptr_for_ref, false)
}
+ pub fn get_c_mangled_container_type(&self, args: Vec<&syn::Type>, generics: Option<&GenericTypes>, template_name: &str) -> Option<String> {
+ let mut out = Vec::new();
+ if !self.write_c_mangled_container_path(&mut out, args, generics, template_name, false, false, false) {
+ return None;
+ }
+ Some(String::from_utf8(out).unwrap())
+ }
// **********************************
// *** C Type Equivalent Printing ***
}
}
fn write_c_type_intern<W: std::io::Write>(&self, w: &mut W, t: &syn::Type, generics: Option<&GenericTypes>, is_ref: bool, is_mut: bool, ptr_for_ref: bool) -> bool {
- match t {
+ match generics.resolve_type(t) {
syn::Type::Path(p) => {
if p.qself.is_some() {
return false;