self.clonable_types.borrow_mut().insert(object);
}
pub fn is_clonable(&self, object: &str) -> bool {
+ object.starts_with("&'static ") ||
self.clonable_types.borrow().contains(object)
}
pub fn write_new_template(&self, mangled_container: String, has_destructor: bool, created_container: &[u8]) {
// Returns prefix + Vec<(prefix, var-name-to-inline-convert)> + suffix
// expecting one element in the vec per generic type, each of which is inline-converted
-> Option<(&'b str, Vec<(String, String)>, &'b str, ContainerPrefixLocation)> {
+ let mut only_contained_has_inner = false;
+ let only_contained_resolved = if let Some(syn::Type::Path(p)) = single_contained {
+ let res = self.resolve_path(&p.path, generics);
+ only_contained_has_inner = self.c_type_has_inner_from_path(&res);
+ Some(res)
+ } else { None };
match full_path {
"Result" if !is_ref => {
Some(("match ",
("), false => Err(".to_string(), format!("(*unsafe {{ Box::from_raw(<*mut _>::take_ptr(&mut {}.contents.err)) }})", var_access))],
")}", ContainerPrefixLocation::PerConv))
},
- "Slice" if is_ref => {
+ "Slice" if is_ref && only_contained_has_inner => {
Some(("Vec::new(); for mut item in ", vec![(format!(".as_slice().iter() {{ local_{}.push(", var_name), "item".to_string())], "); }", ContainerPrefixLocation::PerConv))
},
"Vec"|"Slice" => {
Some(("Vec::new(); for mut item in ", vec![(format!(".into_rust().drain(..) {{ 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);
- if self.is_primitive(&inner_path) {
+ if let Some(resolved) = only_contained_resolved {
+ if self.is_primitive(&resolved) {
return Some(("if ", vec![(".is_some() { Some(".to_string(), format!("{}.take()", var_access))], ") } else { None }", ContainerPrefixLocation::NoPrefix))
- } else if self.c_type_has_inner_from_path(&inner_path) {
+ } else if only_contained_has_inner {
if is_ref {
return Some(("if ", vec![(".inner.is_null() { None } else { Some((*".to_string(), format!("{}", var_access))], ").clone()) }", ContainerPrefixLocation::PerConv))
} else {
write!(w, ">").unwrap();
}
pub fn write_rust_type<W: std::io::Write>(&self, w: &mut W, generics: Option<&GenericTypes>, t: &syn::Type) {
- match t {
+ match generics.resolve_type(t) {
syn::Type::Path(p) => {
if p.qself.is_some() {
unimplemented!();
}
}
- if let Some((prefix, conversions, suffix, prefix_location)) = container_lookup(&$container_type, is_ref && ty_has_inner, only_contained_type, ident, var) {
+ if let Some((prefix, conversions, suffix, prefix_location)) = container_lookup(&$container_type, is_ref, only_contained_type, ident, var) {
assert_eq!(conversions.len(), $args_len);
write!(w, "let mut local_{}{} = ", ident,
if (!to_c && needs_ref_map) || (to_c && $container_type == "Option" && contains_slice) {"_base"} else { "" }).unwrap();
}
write!(w, "let mut local_{} = (", ident).unwrap();
for (idx, elem) in t.elems.iter().enumerate() {
+ let real_elem = generics.resolve_type(&elem);
let ty_has_inner = {
if to_c {
// "To C ptr_for_ref" means "return the regular object with
// if we're about to set ty_has_inner.
ptr_for_ref = true;
}
- if let syn::Type::Reference(t) = elem {
+ if let syn::Type::Reference(t) = real_elem {
if let syn::Type::Path(p) = &*t.elem {
self.c_type_has_inner_from_path(&self.resolve_path(&p.path, generics))
} else { false }
- } else if let syn::Type::Path(p) = elem {
+ } else if let syn::Type::Path(p) = real_elem {
self.c_type_has_inner_from_path(&self.resolve_path(&p.path, generics))
} else { false }
};
if idx != 0 { write!(w, ", ").unwrap(); }
- var_prefix(w, elem, generics, is_ref && ty_has_inner, ptr_for_ref, false);
+ var_prefix(w, real_elem, generics, is_ref && ty_has_inner, ptr_for_ref, false);
if is_ref && ty_has_inner {
// For ty_has_inner, the regular var_prefix mapping will take a
// reference, so deref once here to make sure we keep the original ref.
// hope the type is Clonable and use that.
write!(w, ".clone()").unwrap();
}
- var_suffix(w, elem, generics, is_ref && ty_has_inner, ptr_for_ref, false);
+ var_suffix(w, real_elem, generics, is_ref && ty_has_inner, ptr_for_ref, false);
}
write!(w, "){};", if to_c { ".into()" } else { "" }).unwrap();
true