paddle_inference 0.4.0

paddle_inference_c的Rust封装
Documentation
use crate::call;
use crate::ctypes::{PD_OneDimArrayCstr, PD_OneDimArrayCstrDestroy};
use std::borrow::Cow;
use std::ffi::{CStr, CString, NulError};
use std::os::raw::c_char;

pub struct OneDimArrayCstr {
    ptr: *mut PD_OneDimArrayCstr,
    data: Option<Vec<*const c_char>>,
}

impl OneDimArrayCstr {
    pub fn from_ptr(ptr: *mut PD_OneDimArrayCstr) -> Self {
        Self { ptr, data: None }
    }

    pub fn new<S: AsRef<str>, I: Iterator<Item = S>>(iter: I) -> Result<Self, NulError> {
        let mut data = iter
            .map(|s| CString::new(s.as_ref()))
            .collect::<Result<Vec<_>, _>>()?
            .into_iter()
            .map(|s| s.into_raw() as *const _)
            .collect::<Vec<_>>();
        let ptr = {
            let array = PD_OneDimArrayCstr {
                size: data.len(),
                data: data.as_mut_ptr() as *mut _,
            };
            Box::into_raw(Box::new(array))
        };
        Ok(Self {
            ptr,
            data: Some(data),
        })
    }

    pub fn len(&self) -> usize {
        unsafe { (*self.ptr).size }
    }

    pub fn is_empty(&self) -> bool {
        self.len() == 0
    }

    pub fn get(&self, idx: usize) -> Option<Cow<str>> {
        if idx >= self.len() {
            return None;
        }

        let s = if let Some(data) = &self.data {
            unsafe { CStr::from_ptr(data[idx]) }
        } else if idx <= isize::MAX as usize {
            unsafe { CStr::from_ptr((*self.ptr).data.add(idx).read()) }
        } else {
            return None;
        };

        Some(s.to_string_lossy())
    }
}

impl Drop for OneDimArrayCstr {
    fn drop(&mut self) {
        if let Some(data) = &mut self.data {
            unsafe { Box::from_raw(self.ptr) };
            for ptr in data {
                let ptr = *ptr;
                unsafe { CString::from_raw((*ptr) as *mut _) };
            }
        } else {
            call! { PD_OneDimArrayCstrDestroy(self.ptr) }
        }
    }
}

impl From<OneDimArrayCstr> for Vec<String> {
    fn from(array: OneDimArrayCstr) -> Self {
        (0..array.len())
            .filter_map(|idx| array.get(idx).map(|s| s.to_string()))
            .collect()
    }
}