native_neural_network_std 0.2.1

Ergonomic std wrapper for the `native_neural_network` crate (no_std) — std-friendly re-exports and utilities.
Documentation
#[repr(C)]
#[derive(Clone, Copy)]
pub struct RnnFfiCounts {
    pub layers: u64,
    pub weights: u64,
    pub biases: u64,
}

#[repr(C)]
#[derive(Clone, Copy)]
pub struct RnnFfiModelInfo {
    pub layers: u64,
    pub weights: u64,
    pub biases: u64,
    pub input_size: u64,
    pub output_size: u64,
}

#[repr(C)]
#[derive(Clone, Copy)]
pub struct RnnFfiAbiInfo {
    pub abi_version: u32,
    pub struct_size: u32,
    pub flags: u64,
    pub reserved0: u64,
    pub reserved1: u64,
}

#[repr(C)]
pub struct RnnFfiModelHandle {
    _private: [u8; 0],
}

pub fn api_version() -> u32 {
    1
}

pub fn is_abi_compatible(requested: u32) -> bool {
    requested == 1
}

pub fn abi_info() -> RnnFfiAbiInfo {
    RnnFfiAbiInfo {
        abi_version: 1,
        struct_size: core::mem::size_of::<RnnFfiAbiInfo>() as u32,
        flags: 0,
        reserved0: 0,
        reserved1: 0,
    }
}

pub fn model_create_from_bytes(bytes: &[u8]) -> Result<*mut RnnFfiModelHandle, i32> {
    match crate::std::model_std::ModelStd::from_bytes(bytes) {
        Ok(m) => {
            let boxed = Box::new(m);
            Ok(Box::into_raw(boxed) as *mut RnnFfiModelHandle)
        }
        Err(_) => Err(-1),
    }
}

pub fn model_destroy(handle: *mut RnnFfiModelHandle) -> i32 {
    if handle.is_null() {
        return 0;
    }
    unsafe {
        let raw = handle as *mut crate::std::model_std::ModelStd;
        drop(Box::from_raw(raw));
    }
    0
}

pub fn model_get_info(handle: *const RnnFfiModelHandle) -> Result<RnnFfiModelInfo, i32> {
    if handle.is_null() {
        return Err(-1);
    }
    unsafe {
        let model = &*(handle as *const crate::std::model_std::ModelStd);
        let (layers, weights, biases) = model.info();
        Ok(RnnFfiModelInfo {
            layers: layers as u64,
            weights: weights as u64,
            biases: biases as u64,
            input_size: model.input_size as u64,
            output_size: model.output_size as u64,
        })
    }
}

pub fn model_run(handle: *const RnnFfiModelHandle, input: &[f32], output: &mut [f32]) -> i32 {
    if handle.is_null() {
        return -1;
    }
    unsafe {
        let model = &*(handle as *const crate::std::model_std::ModelStd);
        match model.run_single(input) {
            Ok(v) => {
                if v.len() != output.len() {
                    return -1;
                }
                output.copy_from_slice(&v);
                0
            }
            Err(_) => -1,
        }
    }
}

pub fn run_once(bytes: &[u8], input: &[f32], output: &mut [f32]) -> i32 {
    match crate::std::model_std::ModelStd::from_bytes(bytes) {
        Ok(m) => match m.run_single(input) {
            Ok(v) => {
                if v.len() != output.len() {
                    return -1;
                }
                output.copy_from_slice(&v);
                0
            }
            Err(_) => -1,
        },
        Err(_) => -1,
    }
}

pub fn rnn_ffi_api_version() -> u32 {
    api_version()
}

pub fn rnn_ffi_is_abi_compatible(requested: u32) -> i32 {
    if is_abi_compatible(requested) {
        1
    } else {
        0
    }
}

pub fn rnn_ffi_abi_info(out_info: &mut RnnFfiAbiInfo) -> i32 {
    *out_info = abi_info();
    0
}

fn inner_rnn_ffi_model_create_from_bytes_v1(
    bytes_ptr: *const u8,
    bytes_len: usize,
) -> *mut RnnFfiModelHandle {
    if bytes_ptr.is_null() {
        return core::ptr::null_mut();
    }
    let bytes = unsafe { core::slice::from_raw_parts(bytes_ptr, bytes_len) };
    match crate::std::model_std::ModelStd::from_bytes(bytes) {
        Ok(m) => Box::into_raw(Box::new(m)) as *mut RnnFfiModelHandle,
        Err(_) => core::ptr::null_mut(),
    }
}

pub fn rnn_ffi_model_create_from_bytes_v1(bytes: &[u8]) -> usize {
    if bytes.is_empty() {
        return 0usize;
    }
    inner_rnn_ffi_model_create_from_bytes_v1(bytes.as_ptr(), bytes.len()) as usize
}

pub fn rnn_ffi_model_create_from_bytes(bytes: &[u8]) -> usize {
    rnn_ffi_model_create_from_bytes_v1(bytes)
}

fn inner_rnn_ffi_model_destroy(handle: *mut RnnFfiModelHandle) -> i32 {
    model_destroy(handle)
}

pub fn rnn_ffi_model_destroy(handle: usize) -> i32 {
    inner_rnn_ffi_model_destroy(handle as *mut RnnFfiModelHandle)
}

fn inner_rnn_ffi_model_get_info(
    handle: *const RnnFfiModelHandle,
    out: *mut u8,
    out_len: *mut usize,
) -> i32 {
    if out_len.is_null() {
        return -1;
    }
    match model_get_info(handle) {
        Ok(info) => {
            let info_bytes_vec = unsafe {
                core::slice::from_raw_parts(
                    (&info as *const RnnFfiModelInfo) as *const u8,
                    core::mem::size_of::<RnnFfiModelInfo>(),
                )
                .to_vec()
            };
            let needed: usize = core::mem::size_of::<RnnFfiModelInfo>();
            unsafe {
                if !out.is_null() {
                    let out_cap = *out_len;
                    if out_cap < needed {
                        *out_len = needed;
                        return -1;
                    }
                    let dst = core::slice::from_raw_parts_mut(out, out_cap);
                    dst[..needed].copy_from_slice(&info_bytes_vec[..needed]);
                    *out_len = needed;
                } else {
                    *out_len = needed;
                }
            }
            0
        }
        Err(e) => e,
    }
}

pub fn rnn_ffi_model_get_info(handle: usize) -> Result<Vec<u8>, i32> {
    let mut needed: usize = core::mem::size_of::<RnnFfiModelInfo>();
    let mut buf = vec![0u8; needed];
    let rc = inner_rnn_ffi_model_get_info(
        handle as *const RnnFfiModelHandle,
        buf.as_mut_ptr(),
        &mut needed as *mut usize,
    );
    if rc != 0 {
        return Err(rc);
    }
    buf.truncate(needed);
    Ok(buf)
}

unsafe fn inner_rnn_ffi_model_run(
    handle: *const RnnFfiModelHandle,
    input_ptr: *const f32,
    input_len: usize,
    output_ptr: *mut f32,
    output_len: usize,
) -> i32 {
    if input_ptr.is_null() || output_ptr.is_null() {
        return -1;
    }
    let input = core::slice::from_raw_parts(input_ptr, input_len);
    let output = core::slice::from_raw_parts_mut(output_ptr, output_len);
    model_run(handle, input, output)
}

pub fn rnn_ffi_model_run(handle: usize, input: &[f32], output: &mut [f32]) -> i32 {
    unsafe {
        inner_rnn_ffi_model_run(
            handle as *const RnnFfiModelHandle,
            input.as_ptr(),
            input.len(),
            output.as_mut_ptr(),
            output.len(),
        )
    }
}

unsafe fn inner_rnn_ffi_run_v1(
    bytes_ptr: *const u8,
    bytes_len: usize,
    input_ptr: *const f32,
    input_len: usize,
    output_ptr: *mut f32,
    output_len: usize,
) -> i32 {
    if bytes_ptr.is_null() {
        return -1;
    }
    let bytes = core::slice::from_raw_parts(bytes_ptr, bytes_len);
    if input_ptr.is_null() || output_ptr.is_null() {
        return -1;
    }
    let input = core::slice::from_raw_parts(input_ptr, input_len);
    let output = core::slice::from_raw_parts_mut(output_ptr, output_len);
    run_once(bytes, input, output)
}

pub fn rnn_ffi_run_v1(bytes: &[u8], input: &[f32], output: &mut [f32]) -> i32 {
    unsafe {
        inner_rnn_ffi_run_v1(
            if bytes.is_empty() {
                core::ptr::null()
            } else {
                bytes.as_ptr()
            },
            bytes.len(),
            input.as_ptr(),
            input.len(),
            output.as_mut_ptr(),
            output.len(),
        )
    }
}