Skip to content

Commit 3ae49b8

Browse files
committed
[bindings] Use enum to describe deref'ing needed for Option<> inners
1 parent f92d559 commit 3ae49b8

File tree

1 file changed

+39
-22
lines changed

1 file changed

+39
-22
lines changed

c-bindings-gen/src/types.rs

Lines changed: 39 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -257,6 +257,19 @@ 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+
271+
272+
260273
impl<'a, 'c: 'a> TypeResolver<'a, 'c> {
261274
pub fn new(orig_crate: &'a str, module_path: &'a str, crate_types: &'a mut CrateTypes<'c>) -> Self {
262275
let mut imports = HashMap::new();
@@ -757,20 +770,21 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> {
757770

758771
if let Some(t) = single_contained {
759772
let mut v = Vec::new();
760-
let (needs_deref, ret_ref) = self.write_empty_rust_val_check_suffix(generics, &mut v, t);
773+
let ret_ref = self.write_empty_rust_val_check_suffix(generics, &mut v, t);
761774
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-
], ") }"));
775+
match ret_ref {
776+
EmptyValExpectedTy::ReferenceAsPointer =>
777+
return Some(("if ", vec![
778+
(format!("{} {{ None }} else {{ Some(", s), format!("unsafe {{ &mut *{} }}", var_access))
779+
], ") }")),
780+
EmptyValExpectedTy::OwnedPointer =>
781+
return Some(("if ", vec![
782+
(format!("{} {{ None }} else {{ Some(", s), format!("unsafe {{ *Box::from_raw({}) }}", var_access))
783+
], ") }")),
784+
EmptyValExpectedTy::NonPointer =>
785+
return Some(("if ", vec![
786+
(format!("{} {{ None }} else {{ Some(", s), format!("{}", var_access))
787+
], ") }")),
774788
}
775789
} else { unreachable!(); }
776790
},
@@ -1054,39 +1068,42 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> {
10541068
}
10551069
}
10561070

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) {
1071+
/// Prints a suffix to determine if a variable is empty (ie was set by write_empty_rust_val).
1072+
/// See EmptyValExpectedTy for information on return types.
1073+
/// returning two bools - the first indicates that the variable is mapped as a pointer which
1074+
/// needs to be dereferenced before use, and the second indicates the variable needs to be
1075+
/// dereferenced but is expected to be used as a reference, not moved.
1076+
fn write_empty_rust_val_check_suffix<W: std::io::Write>(&self, generics: Option<&GenericTypes>, w: &mut W, t: &syn::Type) -> EmptyValExpectedTy {
10611077
match t {
10621078
syn::Type::Path(p) => {
10631079
let resolved = self.resolve_path(&p.path, generics);
10641080
if self.crate_types.opaques.get(&resolved).is_some() {
10651081
write!(w, ".inner.is_null()").unwrap();
1066-
(false, false)
1082+
EmptyValExpectedTy::NonPointer
10671083
} else {
10681084
if let Some(suffix) = self.empty_val_check_suffix_from_path(&resolved) {
10691085
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
1086+
// We may eventually need to allow empty_val_check_suffix_from_path to specify if we need a deref or not
1087+
EmptyValExpectedTy::NonPointer
10711088
} else {
10721089
write!(w, " == std::ptr::null_mut()").unwrap();
1073-
(true, false)
1090+
EmptyValExpectedTy::OwnedPointer
10741091
}
10751092
}
10761093
},
10771094
syn::Type::Array(a) => {
10781095
if let syn::Expr::Lit(l) = &a.len {
10791096
if let syn::Lit::Int(i) = &l.lit {
10801097
write!(w, " == [0; {}]", i.base10_digits()).unwrap();
1081-
(false, false)
1098+
EmptyValExpectedTy::NonPointer
10821099
} else { unimplemented!(); }
10831100
} else { unimplemented!(); }
10841101
},
10851102
syn::Type::Slice(_) => {
10861103
// Option<[]> always implies that we want to treat len() == 0 differently from
10871104
// None, so we always map an Option<[]> into a pointer.
10881105
write!(w, " == std::ptr::null_mut()").unwrap();
1089-
(true, true)
1106+
EmptyValExpectedTy::ReferenceAsPointer
10901107
},
10911108
_ => unimplemented!(),
10921109
}

0 commit comments

Comments
 (0)