Skip to content

Commit 35e48cf

Browse files
committed
[bindings] Use enum to describe deref'ing needed for Option<> inners
1 parent d773151 commit 35e48cf

File tree

1 file changed

+34
-22
lines changed

1 file changed

+34
-22
lines changed

c-bindings-gen/src/types.rs

Lines changed: 34 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -257,6 +257,17 @@ pub struct TypeResolver<'mod_lifetime, 'crate_lft: 'mod_lifetime> {
257257
pub crate_types: &'mod_lifetime mut CrateTypes<'crate_lft>,
258258
}
259259

260+
/// Returned by write_empty_rust_val_check_suffix to indicate what type of dereferencing needs to
261+
/// happen to get the inner value of a generic.
262+
enum EmptyValExpectedTy {
263+
/// A type which has a flag for being empty (eg an array where we treat all-0s as empty).
264+
NonPointer,
265+
/// A pointer that we want to dereference and move out of.
266+
OwnedPointer,
267+
/// A pointer which we want to convert to a reference.
268+
ReferenceAsPointer,
269+
}
270+
260271
impl<'a, 'c: 'a> TypeResolver<'a, 'c> {
261272
pub fn new(orig_crate: &'a str, module_path: &'a str, crate_types: &'a mut CrateTypes<'c>) -> Self {
262273
let mut imports = HashMap::new();
@@ -757,20 +768,21 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> {
757768

758769
if let Some(t) = single_contained {
759770
let mut v = Vec::new();
760-
let (needs_deref, ret_ref) = self.write_empty_rust_val_check_suffix(generics, &mut v, t);
771+
let ret_ref = self.write_empty_rust_val_check_suffix(generics, &mut v, t);
761772
let s = String::from_utf8(v).unwrap();
762-
if needs_deref && ret_ref {
763-
return Some(("if ", vec![
764-
(format!("{} {{ None }} else {{ Some(", s), format!("unsafe {{ &mut *{} }}", var_access))
765-
], ") }"));
766-
} else if needs_deref {
767-
return Some(("if ", vec![
768-
(format!("{} {{ None }} else {{ Some(", s), format!("unsafe {{ *Box::from_raw({}) }}", var_access))
769-
], ") }"));
770-
} else {
771-
return Some(("if ", vec![
772-
(format!("{} {{ None }} else {{ Some(", s), format!("{}", var_access))
773-
], ") }"));
773+
match ret_ref {
774+
EmptyValExpectedTy::ReferenceAsPointer =>
775+
return Some(("if ", vec![
776+
(format!("{} {{ None }} else {{ Some(", s), format!("unsafe {{ &mut *{} }}", var_access))
777+
], ") }")),
778+
EmptyValExpectedTy::OwnedPointer =>
779+
return Some(("if ", vec![
780+
(format!("{} {{ None }} else {{ Some(", s), format!("unsafe {{ *Box::from_raw({}) }}", var_access))
781+
], ") }")),
782+
EmptyValExpectedTy::NonPointer =>
783+
return Some(("if ", vec![
784+
(format!("{} {{ None }} else {{ Some(", s), format!("{}", var_access))
785+
], ") }")),
774786
}
775787
} else { unreachable!(); }
776788
},
@@ -1054,39 +1066,39 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> {
10541066
}
10551067
}
10561068

1057-
/// Prints a suffix to determine if a variable is empty (ie was set by write_empty_rust_val),
1058-
/// returning whether we need to dereference the inner value before using it (ie it is a
1059-
/// pointer).
1060-
pub fn write_empty_rust_val_check_suffix<W: std::io::Write>(&self, generics: Option<&GenericTypes>, w: &mut W, t: &syn::Type) -> (bool, bool) {
1069+
/// Prints a suffix to determine if a variable is empty (ie was set by write_empty_rust_val).
1070+
/// See EmptyValExpectedTy for information on return types.
1071+
fn write_empty_rust_val_check_suffix<W: std::io::Write>(&self, generics: Option<&GenericTypes>, w: &mut W, t: &syn::Type) -> EmptyValExpectedTy {
10611072
match t {
10621073
syn::Type::Path(p) => {
10631074
let resolved = self.resolve_path(&p.path, generics);
10641075
if self.crate_types.opaques.get(&resolved).is_some() {
10651076
write!(w, ".inner.is_null()").unwrap();
1066-
(false, false)
1077+
EmptyValExpectedTy::NonPointer
10671078
} else {
10681079
if let Some(suffix) = self.empty_val_check_suffix_from_path(&resolved) {
10691080
write!(w, "{}", suffix).unwrap();
1070-
(false, false) // We may eventually need to allow empty_val_check_suffix_from_path to specify if we need a deref or not
1081+
// We may eventually need to allow empty_val_check_suffix_from_path to specify if we need a deref or not
1082+
EmptyValExpectedTy::NonPointer
10711083
} else {
10721084
write!(w, " == std::ptr::null_mut()").unwrap();
1073-
(true, false)
1085+
EmptyValExpectedTy::OwnedPointer
10741086
}
10751087
}
10761088
},
10771089
syn::Type::Array(a) => {
10781090
if let syn::Expr::Lit(l) = &a.len {
10791091
if let syn::Lit::Int(i) = &l.lit {
10801092
write!(w, " == [0; {}]", i.base10_digits()).unwrap();
1081-
(false, false)
1093+
EmptyValExpectedTy::NonPointer
10821094
} else { unimplemented!(); }
10831095
} else { unimplemented!(); }
10841096
},
10851097
syn::Type::Slice(_) => {
10861098
// Option<[]> always implies that we want to treat len() == 0 differently from
10871099
// None, so we always map an Option<[]> into a pointer.
10881100
write!(w, " == std::ptr::null_mut()").unwrap();
1089-
(true, true)
1101+
EmptyValExpectedTy::ReferenceAsPointer
10901102
},
10911103
_ => unimplemented!(),
10921104
}

0 commit comments

Comments
 (0)