let is_inner_ref = if let Some(syn::Type::Reference(_)) = single_contained { true } else { false };
if is_ref {
return Some(("if ", vec![
- (".is_none() { std::ptr::null() } else { ".to_owned(),
+ (".is_none() { std::ptr::null() } else { ObjOps::nonnull_ptr_to_inner(".to_owned(),
format!("({}{}.unwrap())", var_access, if is_inner_ref { "" } else { ".as_ref()" }))
- ], " }", ContainerPrefixLocation::OutsideConv));
+ ], ") }", ContainerPrefixLocation::OutsideConv));
} else {
return Some(("if ", vec![
(".is_none() { std::ptr::null_mut() } else { ".to_owned(), format!("({}.unwrap())", var_access))
}
}
+ /// Constructs a reference to the given type, possibly tweaking the type if relevant to make it
+ /// convertable to C.
+ pub fn create_ownable_reference(&self, t: &syn::Type, generics: Option<&GenericTypes>) -> Option<syn::Type> {
+ let default_value = Some(syn::Type::Reference(syn::TypeReference {
+ and_token: syn::Token!(&)(Span::call_site()), lifetime: None, mutability: None,
+ elem: Box::new(t.clone()) }));
+ match t {
+ syn::Type::Path(p) => {
+ if let Some(resolved_path) = self.maybe_resolve_path(&p.path, generics) {
+ if resolved_path != "Vec" { return default_value; }
+ if p.path.segments.len() != 1 { unimplemented!(); }
+ let only_seg = p.path.segments.iter().next().unwrap();
+ if let syn::PathArguments::AngleBracketed(args) = &only_seg.arguments {
+ if args.args.len() != 1 { unimplemented!(); }
+ let inner_arg = args.args.iter().next().unwrap();
+ if let syn::GenericArgument::Type(ty) = &inner_arg {
+ let mut can_create = self.c_type_has_inner(&ty);
+ if let syn::Type::Path(inner) = ty {
+ if inner.path.segments.len() == 1 &&
+ format!("{}", inner.path.segments[0].ident) == "Vec" {
+ can_create = true;
+ }
+ }
+ if !can_create { return default_value; }
+ if let Some(inner_ty) = self.create_ownable_reference(&ty, generics) {
+ return Some(syn::Type::Reference(syn::TypeReference {
+ and_token: syn::Token![&](Span::call_site()),
+ lifetime: None,
+ mutability: None,
+ elem: Box::new(syn::Type::Slice(syn::TypeSlice {
+ bracket_token: syn::token::Bracket { span: Span::call_site() },
+ elem: Box::new(inner_ty)
+ }))
+ }));
+ } else { return default_value; }
+ } else { unimplemented!(); }
+ } else { unimplemented!(); }
+ } else { return None; }
+ },
+ _ => default_value,
+ }
+ }
+
// *************************************************
// *** Type definition during main.rs processing ***
// *************************************************
pub fn c_type_has_inner_from_path(&self, full_path: &str) -> bool {
self.crate_types.opaques.get(full_path).is_some()
}
+
/// Returns true if the object at the given path is mapped as X { inner: *mut origX, .. }.
pub fn c_type_has_inner(&self, ty: &syn::Type) -> bool {
match ty {
syn::Type::Path(p) => {
- let full_path = self.resolve_path(&p.path, None);
- self.c_type_has_inner_from_path(&full_path)
+ if let Some(full_path) = self.maybe_resolve_path(&p.path, None) {
+ self.c_type_has_inner_from_path(&full_path)
+ } else { false }
},
syn::Type::Reference(r) => {
self.c_type_has_inner(&*r.elem)
} else if let syn::Type::Reference(r) = &*s.elem {
if let syn::Type::Path(p) = &*r.elem {
write!(w, "{}", sliceconv(self.c_type_has_inner_from_path(&self.resolve_path(&p.path, generics)), None)).unwrap();
+ } else if let syn::Type::Slice(_) = &*r.elem {
+ write!(w, "{}", sliceconv(false, None)).unwrap();
} else { unimplemented!(); }
} else if let syn::Type::Tuple(t) = &*s.elem {
assert!(!t.elems.is_empty());
DeclType::MirroredEnum => write!(w, "crate::{}::native_into(", decl_path).unwrap(),
DeclType::EnumIgnored|DeclType::StructImported if is_ref && ptr_for_ref && from_ptr =>
write!(w, "crate::{} {{ inner: unsafe {{ (", decl_path).unwrap(),
- DeclType::EnumIgnored|DeclType::StructImported if is_ref && ptr_for_ref =>
- write!(w, "crate::{} {{ inner: unsafe {{ ( (&(*", decl_path).unwrap(),
- DeclType::EnumIgnored|DeclType::StructImported if is_ref =>
- write!(w, "&crate::{} {{ inner: unsafe {{ (", decl_path).unwrap(),
+ DeclType::EnumIgnored|DeclType::StructImported if is_ref => {
+ if !ptr_for_ref { write!(w, "&").unwrap(); }
+ write!(w, "crate::{} {{ inner: unsafe {{ ObjOps::nonnull_ptr_to_inner((", decl_path).unwrap()
+ },
DeclType::EnumIgnored|DeclType::StructImported if !is_ref && from_ptr =>
write!(w, "crate::{} {{ inner: ", decl_path).unwrap(),
DeclType::EnumIgnored|DeclType::StructImported if !is_ref =>
- write!(w, "crate::{} {{ inner: Box::into_raw(Box::new(", decl_path).unwrap(),
+ write!(w, "crate::{} {{ inner: ObjOps::heap_alloc(", decl_path).unwrap(),
DeclType::Trait(_) if is_ref => write!(w, "").unwrap(),
- DeclType::Trait(_) if !is_ref => {},
+ DeclType::Trait(_) if !is_ref => write!(w, "Into::into(").unwrap(),
_ => panic!("{:?}", decl_path),
}
});
DeclType::MirroredEnum => write!(w, ")").unwrap(),
DeclType::EnumIgnored|DeclType::StructImported if is_ref && ptr_for_ref && from_ptr =>
write!(w, " as *const _) as *mut _ }}, is_owned: false }}").unwrap(),
- DeclType::EnumIgnored|DeclType::StructImported if is_ref && ptr_for_ref =>
- write!(w, ") as *const _) as *mut _) }}, is_owned: false }}").unwrap(),
DeclType::EnumIgnored|DeclType::StructImported if is_ref =>
- write!(w, " as *const _) as *mut _ }}, is_owned: false }}").unwrap(),
+ write!(w, " as *const _) as *mut _) }}, is_owned: false }}").unwrap(),
DeclType::EnumIgnored|DeclType::StructImported if !is_ref && from_ptr =>
write!(w, ", is_owned: true }}").unwrap(),
- DeclType::EnumIgnored|DeclType::StructImported if !is_ref => write!(w, ")), is_owned: true }}").unwrap(),
+ DeclType::EnumIgnored|DeclType::StructImported if !is_ref => write!(w, "), is_owned: true }}").unwrap(),
DeclType::Trait(_) if is_ref => {},
DeclType::Trait(_) => {
// This is used when we're converting a concrete Rust type into a C trait
// for use when a Rust trait method returns an associated type.
// Because all of our C traits implement From<RustTypesImplementingTraits>
// we can just call .into() here and be done.
- write!(w, ".into()").unwrap()
+ write!(w, ")").unwrap()
},
_ => unimplemented!(),
});
self.write_to_c_conversion_inline_suffix_inner(w, t, generics, false, ptr_for_ref, false);
}
- fn write_from_c_conversion_prefix_inner<W: std::io::Write>(&self, w: &mut W, t: &syn::Type, generics: Option<&GenericTypes>, is_ref: bool, ptr_for_ref: bool) {
+ fn write_from_c_conversion_prefix_inner<W: std::io::Write>(&self, w: &mut W, t: &syn::Type, generics: Option<&GenericTypes>, is_ref: bool, _ptr_for_ref: bool) {
self.write_conversion_inline_intern(w, t, generics, is_ref, false, false, "() /*", true, |_, _| "&local_".to_owned(),
|a, b, _c| self.from_c_conversion_prefix_from_path(a, b),
- |w, decl_type, _full_path, is_ref, is_mut| match decl_type {
- DeclType::StructImported if is_ref && ptr_for_ref => write!(w, "unsafe {{ &*(*").unwrap(),
- DeclType::StructImported if is_mut && is_ref => write!(w, "unsafe {{ &mut *").unwrap(),
- DeclType::StructImported if is_ref => write!(w, "unsafe {{ &*").unwrap(),
+ |w, decl_type, _full_path, is_ref, _is_mut| match decl_type {
+ DeclType::StructImported if is_ref => write!(w, "").unwrap(),
DeclType::StructImported if !is_ref => write!(w, "*unsafe {{ Box::from_raw(").unwrap(),
DeclType::MirroredEnum if is_ref => write!(w, "&").unwrap(),
DeclType::MirroredEnum => {},
(true, Some(_)) => unreachable!(),
},
|a, b, _c| self.from_c_conversion_suffix_from_path(a, b),
- |w, decl_type, _full_path, is_ref, _is_mut| match decl_type {
- DeclType::StructImported if is_ref && ptr_for_ref => write!(w, ").inner }}").unwrap(),
- DeclType::StructImported if is_ref => write!(w, ".inner }}").unwrap(),
+ |w, decl_type, _full_path, is_ref, is_mut| match decl_type {
+ DeclType::StructImported if is_ref && ptr_for_ref => write!(w, "XXX unimplemented").unwrap(),
+ DeclType::StructImported if is_mut && is_ref => write!(w, ".get_native_mut_ref()").unwrap(),
+ DeclType::StructImported if is_ref => write!(w, ".get_native_ref()").unwrap(),
DeclType::StructImported if !is_ref => write!(w, ".take_inner()) }}").unwrap(),
DeclType::MirroredEnum if is_ref => write!(w, ".to_native()").unwrap(),
DeclType::MirroredEnum => write!(w, ".into_native()").unwrap(),
} else { None }
},
|w, decl_type, _full_path, is_ref, _is_mut| match decl_type {
- DeclType::StructImported if !is_ref => write!(w, "unsafe {{ &*").unwrap(),
+ DeclType::StructImported if !is_ref => write!(w, "").unwrap(),
_ => unimplemented!(),
});
}
},
|a, b, _c| self.from_c_conversion_suffix_from_path(a, b),
|w, decl_type, _full_path, is_ref, _is_mut| match decl_type {
- DeclType::StructImported if !is_ref => write!(w, ".inner }}").unwrap(),
+ DeclType::StructImported if !is_ref => write!(w, ".get_native_ref()").unwrap(),
_ => unimplemented!(),
});
}
if prefix_location == ContainerPrefixLocation::PerConv {
var_prefix(w, conv_ty, generics, is_ref && ty_has_inner, ptr_for_ref, false);
} else if !is_ref && !needs_ref_map && to_c && only_contained_has_inner {
- write!(w, "Box::into_raw(Box::new(").unwrap();
+ write!(w, "ObjOps::heap_alloc(").unwrap();
}
write!(w, "{}{}", if contains_slice { "local_" } else { "" }, if new_var { new_var_name } else { var_access }).unwrap();
if prefix_location == ContainerPrefixLocation::PerConv {
var_suffix(w, conv_ty, generics, is_ref && ty_has_inner, ptr_for_ref, false);
} else if !is_ref && !needs_ref_map && to_c && only_contained_has_inner {
- write!(w, "))").unwrap();
+ write!(w, ")").unwrap();
}
write!(w, " }}").unwrap();
}
} else { return false; };
write!(w, "{}::{}", Self::generated_container_path(), mangled_container).unwrap();
self.check_create_container(mangled_container, "Vec", vec![&*r.elem], generics, false)
+ } else if let syn::Type::Slice(sl2) = &*r.elem {
+ if let syn::Type::Reference(r2) = &*sl2.elem {
+ if let syn::Type::Path(p) = &*r2.elem {
+ // Slices with slices with opaque types (with is_owned flags) are mapped as non-ref Vecs
+ let resolved = self.resolve_path(&p.path, generics);
+ let mangled_container = if let Some(ident) = self.crate_types.opaques.get(&resolved) {
+ format!("CVec_CVec_{}ZZ", ident)
+ } else { return false; };
+ write!(w, "{}::{}", Self::generated_container_path(), mangled_container).unwrap();
+ let inner = &r2.elem;
+ let vec_ty: syn::Type = syn::parse_quote!(Vec<#inner>);
+ self.check_create_container(mangled_container, "Vec", vec![&vec_ty], generics, false)
+ } else { false }
+ } else { false }
} else { false }
} else if let syn::Type::Tuple(_) = &*s.elem {
let mut args = syn::punctuated::Punctuated::<_, syn::token::Comma>::new();