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
use native_neural_network_std::std::activations_std::ActivationKind;
use native_neural_network_std::std::layers_std::{DenseLayerDesc, LayerSpec};

fn make_valid_blob() -> Vec<u8> {
    use native_neural_network_std::std::model_format_std::{encode_model_v1, encoded_size_v1};

    let layers = vec![LayerSpec::Dense(DenseLayerDesc {
        input_size: 2,
        output_size: 1,
        weight_offset: 0,
        bias_offset: 0,
        activation: ActivationKind::Identity,
    })];
    let weights = vec![1.0f32, 1.0f32];
    let biases = vec![0.5f32];
    let size = encoded_size_v1(layers.len(), weights.len(), biases.len()).expect("encoded size");
    let mut out_bytes = vec![0u8; size];
    let written =
        encode_model_v1(&layers, &weights, &biases, &mut out_bytes).expect("encode valid ffi blob");
    out_bytes.truncate(written);
    out_bytes
}

#[test]
fn cpu_backend_abstraction_real() {
    let previous = native_neural_network_std::std::engine_std::get_compute_backend();
    native_neural_network_std::std::engine_std::set_compute_backend(
        native_neural_network_std::std::engine_std::ComputeBackend::Cpu,
    );
    assert_eq!(
        native_neural_network_std::std::engine_std::get_compute_backend(),
        native_neural_network_std::std::engine_std::ComputeBackend::Cpu
    );
    native_neural_network_std::std::engine_std::set_compute_backend(previous);
}

#[test]
fn ffi_api_version_real() {
    let v = native_neural_network_std::std::ffi::rnn_ffi_api_version();
    assert_eq!(v, 1, "mocked FFI should return version 1");
}

#[test]
fn ffi_api_version_threadsafe() {
    use std::thread;
    let mut handles = Vec::new();
    for _ in 0..8 {
        handles.push(thread::spawn(|| {
            native_neural_network_std::std::ffi::rnn_ffi_api_version()
        }));
    }
    for h in handles {
        let v = h.join().unwrap();
        assert_eq!(v, 1);
    }
}

#[test]
fn ffi_model_lifecycle_and_run() {
    let blob = make_valid_blob();
    let h = native_neural_network_std::std::ffi::rnn_ffi_model_create_from_bytes_v1(&blob);
    assert!(h != 0);

    let info = native_neural_network_std::std::ffi::rnn_ffi_model_get_info(h).expect("get_info");
    assert_eq!(
        info.len(),
        core::mem::size_of::<native_neural_network_std::std::ffi::RnnFfiModelInfo>()
    );

    let input = [2.0f32, 3.0f32];
    let mut out = [0f32; 1];
    let rc2 = native_neural_network_std::std::ffi::rnn_ffi_model_run(h, &input, &mut out);
    assert_eq!(rc2, 0);
    assert!((out[0] - (2.0 + 3.0 + 0.5)).abs() < 1e-6);

    native_neural_network_std::std::ffi::rnn_ffi_model_destroy(h);
}

#[test]
fn ffi_run_with_bad_buffers_errors() {
    let blob = make_valid_blob();
    let h = native_neural_network_std::std::ffi::rnn_ffi_model_create_from_bytes_v1(&blob);
    assert!(h != 0);
    let input = [0f32; 2];
    let mut out = [0f32; 0];
    let rc = native_neural_network_std::std::ffi::rnn_ffi_model_run(h, &input, &mut out);
    assert!(rc < 0);
    native_neural_network_std::std::ffi::rnn_ffi_model_destroy(h);
}

#[test]
fn ffi_concurrent_create_run_destroy() {
    use std::thread;
    let mut handles = Vec::new();
    for _ in 0..8 {
        handles.push(thread::spawn(|| {
            let blob = make_valid_blob();
            let h = native_neural_network_std::std::ffi::rnn_ffi_model_create_from_bytes_v1(&blob);
            if h == 0 {
                panic!("create failed");
            }
            let input = [1.0f32, 1.0f32];
            let mut out = [0f32; 1];
            let rc = native_neural_network_std::std::ffi::rnn_ffi_model_run(h, &input, &mut out);
            assert_eq!(rc, 0);
            native_neural_network_std::std::ffi::rnn_ffi_model_destroy(h);
        }));
    }
    for h in handles {
        h.join().unwrap();
    }
}