apple_vision/person_instance_mask/
mod.rs1#![allow(clippy::cast_possible_wrap, clippy::cast_sign_loss)]
2#![allow(clippy::too_long_first_doc_paragraph)]
3use std::ffi::{CStr, CString};
7use std::path::Path;
8use std::ptr;
9
10use crate::error::VisionError;
11use crate::ffi;
12
13pub struct PersonInstanceMask {
15 pub width: usize,
16 pub height: usize,
17 pub bytes_per_row: usize,
18 data: *mut u8,
19}
20
21impl PersonInstanceMask {
22 #[must_use]
24 pub const fn as_bytes(&self) -> &[u8] {
25 unsafe { core::slice::from_raw_parts(self.data, self.bytes_per_row * self.height) }
29 }
30}
31
32impl Drop for PersonInstanceMask {
33 fn drop(&mut self) {
34 if !self.data.is_null() {
35 let size = (self.bytes_per_row * self.height) as isize;
36 unsafe { ffi::vn_mask_buffer_free(self.data, size) };
39 self.data = ptr::null_mut();
40 }
41 }
42}
43
44unsafe impl Send for PersonInstanceMask {}
48unsafe impl Sync for PersonInstanceMask {}
49
50pub fn person_instance_mask(
57 path: impl AsRef<Path>,
58) -> Result<Option<PersonInstanceMask>, VisionError> {
59 let path_str = path
60 .as_ref()
61 .to_str()
62 .ok_or_else(|| VisionError::InvalidArgument("non-UTF-8 path".into()))?;
63 let cpath = CString::new(path_str)
64 .map_err(|e| VisionError::InvalidArgument(format!("path NUL byte: {e}")))?;
65 let mut w: isize = 0;
66 let mut h: isize = 0;
67 let mut bpr: isize = 0;
68 let mut data: *mut u8 = ptr::null_mut();
69 let mut err: *mut std::ffi::c_char = ptr::null_mut();
70 let status = unsafe {
73 ffi::vn_person_instance_mask_in_path(
74 cpath.as_ptr(),
75 &mut w,
76 &mut h,
77 &mut bpr,
78 &mut data,
79 &mut err,
80 )
81 };
82 if status != ffi::status::OK {
83 let msg = unsafe { take_err(err) };
85 return Err(VisionError::RequestFailed(msg));
86 }
87 if data.is_null() {
88 return Ok(None);
89 }
90 Ok(Some(PersonInstanceMask {
91 width: w.max(0) as usize,
92 height: h.max(0) as usize,
93 bytes_per_row: bpr.max(0) as usize,
94 data,
95 }))
96}
97
98unsafe fn take_err(p: *mut std::ffi::c_char) -> String {
106 if p.is_null() {
107 return String::new();
108 }
109 let s = unsafe { CStr::from_ptr(p) }.to_string_lossy().into_owned();
111 unsafe { libc::free(p.cast()) };
113 s
114}