Add support for nullable slices
MODIFY
binding-generator/src/field.rs
binding-generator/src/field.rs
@@ -28,6 +28,7 @@ use crate::{
pub enum FieldTypeHint<'tu> {
None,
Slice,
+ NullableSlice,
SliceLen(&'static str, usize),
FieldSetter,
Specialized(Type<'tu>),
@@ -70,6 +71,7 @@ impl<'tu> Field<'tu> {
pub fn type_ref(&self) -> TypeRef<'tu> {
let type_hint = match self.type_hint {
FieldTypeHint::Slice => TypeRefTypeHint::Slice,
+ FieldTypeHint::NullableSlice => TypeRefTypeHint::NullableSlice,
FieldTypeHint::Specialized(typ) => TypeRefTypeHint::Specialized(typ),
_ => TypeRefTypeHint::None,
};

MODIFY
binding-generator/src/func.rs
binding-generator/src/func.rs
@@ -388,6 +388,9 @@ impl<'tu> Func<'tu> {
SliceHint::Slice => {
Field::new_ext(a, FieldTypeHint::Slice, self.gen_env)
},
+ SliceHint::NullableSlice => {
+ Field::new_ext(a, FieldTypeHint::NullableSlice, self.gen_env)
+ },
SliceHint::LenForSlice(ptr_arg, len_div) => {
Field::new_ext(a, FieldTypeHint::SliceLen(ptr_arg, len_div), self.gen_env)
}

MODIFY
binding-generator/src/settings.rs
binding-generator/src/settings.rs
@@ -839,6 +839,7 @@ pub static IMPLEMENTED_GENERICS: Lazy<HashSet<&str>> = Lazy::new(|| hashset! {
#[derive(Debug)]
pub enum SliceHint {
Slice,
+ NullableSlice,
LenForSlice(&'static str, usize),
}
@@ -851,12 +852,12 @@ pub static SLICE_ARGUMENT: Lazy<HashMap<(&str, usize), HashMap<&str, SliceHint>>
"idx" => SliceHint::Slice
},
("cv::Mat::Mat", 4) => hashmap! {
- "steps" => SliceHint::Slice,
+ "steps" => SliceHint::NullableSlice,
"sizes" => SliceHint::Slice,
"ndims" => SliceHint::LenForSlice("sizes", 1),
},
("cv::Mat::Mat", 5) => hashmap! {
- "steps" => SliceHint::Slice,
+ "steps" => SliceHint::NullableSlice,
"sizes" => SliceHint::Slice,
"ndims" => SliceHint::LenForSlice("sizes", 1),
},

MODIFY
binding-generator/src/type_ref.rs
binding-generator/src/type_ref.rs
@@ -86,6 +86,7 @@ pub enum Kind<'tu> {
pub enum TypeRefTypeHint<'tu> {
None,
Slice,
+ NullableSlice,
Specialized(Type<'tu>),
}
@@ -160,7 +161,7 @@ impl<'tu> TypeRef<'tu> {
let pointee_typeref = TypeRef::new_ext(pointee, self.type_hint, self.parent_entity, self.gen_env);
if pointee_typeref.as_function().is_some() {
pointee_typeref.kind()
- } else if matches!(self.type_hint, TypeRefTypeHint::Slice) {
+ } else if matches!(self.type_hint, TypeRefTypeHint::Slice | TypeRefTypeHint::NullableSlice) {
Kind::Array(TypeRef::new_ext(pointee, self.type_hint, self.parent_entity, self.gen_env), None)
} else {
Kind::Pointer(TypeRef::new_ext(pointee, self.type_hint, self.parent_entity, self.gen_env))
@@ -677,6 +678,10 @@ impl<'tu> TypeRef<'tu> {
}
}
+ pub fn is_nullable(&self) -> bool {
+ matches!(self.type_hint, TypeRefTypeHint::NullableSlice)
+ }
+
pub fn as_class(&self) -> Option<Class<'tu>> {
if let Kind::Class(out) = self.canonical().kind() {
Some(out)
@@ -1190,10 +1195,20 @@ impl<'tu> TypeRef<'tu> {
}
}
if self.as_variable_array().is_some() {
- return if constness.with(self.constness()).is_const() {
+ let arr = if constness.with(self.constness()).is_const() {
format!("{name}.as_ptr()", name=name)
} else {
format!("{name}.as_mut_ptr()", name=name)
+ };
+ return if self.is_nullable() {
+ let null_ptr_name = if constness.with(self.constness()).is_const() {
+ "null"
+ } else {
+ "null_mut"
+ };
+ format!("{name}.map_or(::core::ptr::{null_ptr_name}(), |{name}| {arr})", name=name, null_ptr_name=null_ptr_name, arr=arr)
+ } else {
+ arr
}
}
if let Some(func) = self.as_function() {

MODIFY
binding-generator/src/type_ref/renderer.rs
binding-generator/src/type_ref/renderer.rs
@@ -109,7 +109,13 @@ fn render_rust<'a, 't>(renderer: impl TypeRefRenderer<'a>, type_ref: &'t TypeRef
rust.into()
}
Kind::Array(elem, size) => {
- type_ref.format_as_array(&elem.render(renderer.recurse()), size).into()
+ let typ = type_ref.format_as_array(&elem.render(renderer.recurse()), size);
+ if type_ref.is_nullable() {
+ let turbo_fish = if use_turbo_fish { "::" } else { "" };
+ format!("Option{turbo_fish}<{typ}>", turbo_fish=turbo_fish, typ=typ)
+ } else {
+ typ
+ }.into()
}
Kind::StdVector(vec) => {
vec.rust_name(is_full).into_owned().into()

MODIFY
tests/mat.rs
tests/mat.rs
@@ -411,8 +411,26 @@ fn mat_from_data() -> Result<()> {
assert_eq!(PIXEL.len(), src.total()?);
let row = src.at_row::<u8>(0)?;
assert_eq!(0x89, row[0]);
+ assert_eq!(0x50, row[1]);
+ assert_eq!(0x1A, row[6]);
assert_eq!(0x0D, row[11]);
assert_eq!(0x82, row[89]);
+
+ let src = unsafe {
+ Mat::new_nd_with_data(
+ &[3, 5, 6],
+ u8::typ(),
+ bytes.as_mut_ptr() as *mut c_void,
+ None,
+ )?
+ };
+ assert_eq!(Size::new(5_, 3), src.size()?);
+ assert_eq!(PIXEL.len(), src.total()?);
+ assert_eq!(0x89, *src.at_3d::<u8>(0, 0, 0)?);
+ assert_eq!(0x50, *src.at_3d::<u8>(0, 0, 1)?);
+ assert_eq!(0x1A, *src.at_3d::<u8>(0, 1, 0)?);
+ assert_eq!(0x0D, *src.at_3d::<u8>(0, 1, 5)?);
+ assert_eq!(0x82, *src.at_3d::<u8>(2, 4, 5)?);
Ok(())
}

Add support for nullable slices