#![cfg_attr(not(feature = "std"), no_std)]
#![cfg_attr(test, allow(clippy::unwrap_used))]
#![cfg_attr(test, allow(clippy::expect_used))]
#![cfg_attr(test, allow(clippy::arithmetic_side_effects))]
#![cfg_attr(test, allow(clippy::indexing_slicing))]
#![cfg_attr(test, allow(clippy::panic))]
#![cfg_attr(test, allow(clippy::panic_in_result_fn))]
#![cfg_attr(test, allow(clippy::as_conversions))]
#![cfg_attr(test, allow(clippy::float_cmp))]
#![cfg_attr(test, allow(clippy::float_cmp_const))]
#![cfg_attr(test, allow(clippy::cast_possible_truncation))]
#![cfg_attr(test, allow(clippy::cast_possible_wrap))]
#![cfg_attr(test, allow(clippy::cast_precision_loss))]
#![cfg_attr(test, allow(clippy::cast_sign_loss))]
#![cfg_attr(test, allow(clippy::integer_division))]
#![cfg_attr(test, allow(clippy::shadow_reuse))]
#![cfg_attr(test, allow(clippy::shadow_same))]
#![cfg_attr(test, allow(clippy::shadow_unrelated))]
#![cfg_attr(test, allow(clippy::missing_errors_doc))]
#![cfg_attr(test, allow(clippy::missing_panics_doc))]
#![cfg_attr(test, allow(clippy::trivially_copy_pass_by_ref))]
#![cfg_attr(test, allow(clippy::needless_pass_by_value))]
#![cfg_attr(test, allow(unused_results))]
#[cfg(not(feature = "std"))]
use core::panic::PanicInfo;
#[cfg(not(feature = "std"))]
#[panic_handler]
fn panic(_info: &PanicInfo) -> ! {
loop {}
}
pub mod control_types;
pub mod llmosafe_classifier;
pub mod llmosafe_detection;
pub mod llmosafe_integration;
pub mod llmosafe_kernel;
pub mod llmosafe_memory;
pub mod llmosafe_pid;
pub mod llmosafe_pipeline;
pub mod llmosafe_sifter;
#[cfg(feature = "std")]
pub mod llmosafe_body;
pub use control_types::{ControlSignal, DesignAssuranceLevel, OverrideFlags, PidInput};
#[cfg(feature = "std")]
pub use llmosafe_body::BodyOutput;
#[cfg(feature = "std")]
pub use llmosafe_body::ResourceGuard;
#[cfg(feature = "std")]
pub use llmosafe_detection::DetectionResult;
pub use llmosafe_detection::{
AdversarialDetector, ConfidenceTracker, CusumDetector, DriftDetector, RepetitionDetector,
};
#[cfg(feature = "std")]
pub use llmosafe_integration::SafetyContext;
pub use llmosafe_integration::{EscalationPolicy, EscalationReason, PressureLevel, SafetyDecision};
pub use llmosafe_kernel::KernelOutput;
pub use llmosafe_kernel::{
CognitiveEntropy, CognitiveStability, DynamicStabilityMonitor, KernelError, ReasoningLoop,
SiftedProof, SiftedSynapse, StabilityResult, Synapse, ValidatedProof, ValidatedSynapse,
DETECTION_FLAGS_MASK, FLAG_ADVERSARIAL, FLAG_ANOMALY, FLAG_DECAYING, FLAG_DRIFTING,
FLAG_LOW_CONFIDENCE, FLAG_STUCK, PRESSURE_THRESHOLD, STABILITY_THRESHOLD,
};
pub use llmosafe_memory::MemoryOutput;
pub use llmosafe_memory::WorkingMemory;
pub use llmosafe_pid::{
apply_safety_overrides, compute_pid_score, compute_pid_score_pure, PidConfig, PidState,
};
#[cfg(feature = "std")]
pub use llmosafe_pipeline::STAGE_BODY;
pub use llmosafe_pipeline::{
CognitivePipeline, MemoryStats, PipelineConfig, PipelineResult, STAGE_DETECTION, STAGE_KERNEL,
STAGE_MEMORY, STAGE_MONITOR, STAGE_SIFT,
};
pub use llmosafe_sifter::SifterOutput;
pub use llmosafe_sifter::{
calculate_halo_signal, calculate_utility, get_bias_breakdown, sift_perceptions, sift_text,
BiasBreakdown,
};
#[cfg(feature = "std")]
#[allow(unsafe_code)]
#[allow(clippy::missing_safety_doc)]
#[allow(clippy::as_conversions, clippy::indexing_slicing)]
pub mod c_abi {
use std::sync::Mutex;
use crate::llmosafe_body::ResourceGuard;
use crate::llmosafe_integration::SafetyDecision;
use crate::llmosafe_kernel::KernelError;
use crate::llmosafe_kernel::Synapse;
use crate::llmosafe_memory;
use crate::llmosafe_pipeline::{CognitivePipeline, PipelineConfig, PipelineResult};
const ARENA_SIZE: usize = 16;
const MAX_OBJECTIVE_LEN: usize = 1024;
const ARENA_INDEX_MASK: usize = 0xF;
const GEN_SHIFT: usize = 4;
#[allow(dead_code)]
struct PipelineSlot {
pipeline: CognitivePipeline<'static, 64, 10>,
objective_buf: Box<[u8; MAX_OBJECTIVE_LEN]>,
last_result: Option<PipelineResult>,
generation: u64,
}
static NEXT_GENERATION: std::sync::atomic::AtomicU64 = std::sync::atomic::AtomicU64::new(0);
fn pack_handle(index: usize, generation: u64) -> usize {
index | ((generation as usize) << GEN_SHIFT)
}
fn unpack_handle(handle: usize) -> (usize, u64) {
let index = handle & ARENA_INDEX_MASK;
let generation = (handle >> GEN_SHIFT) as u64;
(index, generation)
}
static PIPELINE_ARENA: Mutex<[Option<PipelineSlot>; ARENA_SIZE]> = Mutex::new([
None, None, None, None, None, None, None, None, None, None, None, None, None, None, None,
None,
]);
unsafe fn store_objective(buf: &mut Box<[u8; MAX_OBJECTIVE_LEN]>, input: &str) -> &'static str {
let mut len = input.len().min(MAX_OBJECTIVE_LEN - 1);
while !input.is_char_boundary(len) {
len = len.saturating_sub(1);
}
buf[..len].copy_from_slice(&input.as_bytes()[..len]);
buf[len] = 0;
let len_val = len;
core::str::from_utf8_unchecked(core::slice::from_raw_parts(buf.as_ptr(), len_val))
}
fn decision_to_code(decision: &SafetyDecision) -> i32 {
match decision {
SafetyDecision::Proceed => 0,
SafetyDecision::Warn(_) => 1,
SafetyDecision::Escalate { .. } => 2,
SafetyDecision::Halt(err, _) => match err {
KernelError::DepthExceeded => -1,
KernelError::CognitiveInstability => -2,
KernelError::BiasHaloDetected => -3,
KernelError::HallucinationDetected => -4,
KernelError::ResourceExhaustion => -5,
KernelError::SelfMemoryExceeded => -6,
KernelError::DeadlineExceeded => -7,
},
SafetyDecision::Exit(_) => -8,
}
}
#[no_mangle]
#[allow(clippy::not_unsafe_ptr_arg_deref)]
pub extern "C" fn llmosafe_create(objective_ptr: *const u8, objective_len: usize) -> usize {
if objective_ptr.is_null() || objective_len == 0 || objective_len > MAX_OBJECTIVE_LEN {
return usize::MAX;
}
let slice = unsafe { core::slice::from_raw_parts(objective_ptr, objective_len) };
let input_str = std::str::from_utf8(slice).unwrap_or("safety");
let mut objective_buf = Box::new([0u8; MAX_OBJECTIVE_LEN]);
let objective = unsafe { store_objective(&mut objective_buf, input_str) };
let config = PipelineConfig::default();
let pipeline = match CognitivePipeline::<'static, 64, 10>::with_config(objective, config) {
Ok(p) => p,
Err(_) => return usize::MAX,
};
let gen = NEXT_GENERATION.fetch_add(1, std::sync::atomic::Ordering::Relaxed);
let mut arena = PIPELINE_ARENA
.lock()
.unwrap_or_else(std::sync::PoisonError::into_inner);
for (i, slot) in arena.iter_mut().enumerate() {
if slot.is_none() {
*slot = Some(PipelineSlot {
pipeline,
objective_buf,
last_result: None,
generation: gen,
});
return pack_handle(i, gen);
}
}
usize::MAX
}
fn get_validated_slot(
arena: &mut [Option<PipelineSlot>; ARENA_SIZE],
handle: usize,
) -> Option<&mut PipelineSlot> {
let (index, generation) = unpack_handle(handle);
if index >= ARENA_SIZE {
return None;
}
match &mut arena[index] {
Some(slot) if slot.generation == generation => Some(slot),
_ => None,
}
}
#[no_mangle]
#[allow(clippy::not_unsafe_ptr_arg_deref)]
pub extern "C" fn llmosafe_sift_and_process(
handle: usize,
text_ptr: *const u8,
text_len: usize,
) -> i32 {
if text_ptr.is_null()
|| text_len == 0
|| text_len > isize::MAX as usize
|| text_len > 10 * 1024 * 1024
{
return -9;
}
let slice = unsafe { core::slice::from_raw_parts(text_ptr, text_len) };
let text = String::from_utf8_lossy(slice);
let mut arena = PIPELINE_ARENA
.lock()
.unwrap_or_else(std::sync::PoisonError::into_inner);
let slot = match get_validated_slot(&mut arena, handle) {
Some(s) => s,
None => return -9,
};
let result = slot.pipeline.process(&text);
let code = decision_to_code(&result.decision);
slot.last_result = Some(result);
code
}
#[no_mangle]
pub extern "C" fn llmosafe_get_decision(handle: usize) -> i32 {
let arena = PIPELINE_ARENA
.lock()
.unwrap_or_else(std::sync::PoisonError::into_inner);
let (index, generation) = unpack_handle(handle);
if index >= ARENA_SIZE {
return -9;
}
arena[index]
.as_ref()
.filter(|s| s.generation == generation)
.map_or(-9, |slot| {
slot.last_result
.as_ref()
.map_or(-9, |r| decision_to_code(&r.decision))
})
}
#[no_mangle]
pub extern "C" fn llmosafe_get_classifier_score(instance_id: u32) -> f64 {
let arena = PIPELINE_ARENA
.lock()
.unwrap_or_else(std::sync::PoisonError::into_inner);
if (instance_id as usize) >= ARENA_SIZE {
return -1.0;
}
arena[instance_id as usize].as_ref().map_or_else(
|| -1.0,
|slot| {
slot.last_result
.as_ref()
.map_or_else(|| -1.0, |r| f64::from(r.classifier_score))
},
)
}
#[no_mangle]
#[allow(clippy::not_unsafe_ptr_arg_deref)]
pub extern "C" fn llmosafe_get_pid_state(
instance_id: u32,
acute: *mut f64,
chronic: *mut f64,
pressure: *mut f64,
) -> u32 {
if acute.is_null() || chronic.is_null() || pressure.is_null() {
return 1;
}
let arena = PIPELINE_ARENA
.lock()
.unwrap_or_else(std::sync::PoisonError::into_inner);
let handle = instance_id as usize;
if handle >= ARENA_SIZE {
return 1;
}
let slot = match &arena[handle] {
Some(s) => s,
None => return 1,
};
let state = slot.pipeline.pid_state();
unsafe {
std::ptr::write_unaligned(acute, state.acute_entropy as f64);
std::ptr::write_unaligned(chronic, state.chronic_entropy as f64);
std::ptr::write_unaligned(pressure, state.prev_pressure_norm as f64);
}
0
}
#[no_mangle]
pub extern "C" fn llmosafe_destroy(handle: usize) {
let (index, generation) = unpack_handle(handle);
if index >= ARENA_SIZE {
return;
}
let mut arena = PIPELINE_ARENA
.lock()
.unwrap_or_else(std::sync::PoisonError::into_inner);
match &arena[index] {
Some(slot) if slot.generation == generation => {
arena[index] = None;
}
_ => {}
}
}
#[no_mangle]
pub extern "C" fn llmosafe_process_synapse(synapse_bits: u128) -> i32 {
llmosafe_memory::cognitive_memory::process_state_update(synapse_bits)
}
#[no_mangle]
#[allow(clippy::not_unsafe_ptr_arg_deref)]
pub extern "C" fn llmosafe_calculate_halo(text_ptr: *const u8, text_len: usize) -> u16 {
let max_text_len = 10 * 1024 * 1024;
if text_ptr.is_null()
|| text_len == 0
|| text_len > isize::MAX as usize
|| text_len > max_text_len
{
return 0;
}
let slice = unsafe { core::slice::from_raw_parts(text_ptr, text_len) };
let text = String::from_utf8_lossy(slice);
let (sifted, _proof) = crate::llmosafe_sifter::sift_text(&text);
sifted.raw_entropy()
}
#[no_mangle]
pub extern "C" fn llmosafe_check_resources(ceiling_mb: u32) -> i32 {
let ceiling_bytes = (ceiling_mb as usize).saturating_mul(1024 * 1024);
let guard = ResourceGuard::new(ceiling_bytes);
match guard.check() {
Ok(_) => 0,
Err(KernelError::ResourceExhaustion) => -5,
Err(KernelError::DepthExceeded) => -1,
Err(KernelError::CognitiveInstability) => -2,
Err(KernelError::BiasHaloDetected) => -3,
Err(KernelError::HallucinationDetected) => -4,
Err(KernelError::SelfMemoryExceeded) => -6,
Err(KernelError::DeadlineExceeded) => -7,
}
}
#[no_mangle]
pub extern "C" fn llmosafe_get_resource_pressure(ceiling_mb: u32) -> u8 {
let ceiling_bytes = (ceiling_mb as usize).saturating_mul(1024 * 1024);
if ceiling_bytes == 0 {
return 100;
}
let guard = ResourceGuard::new(ceiling_bytes);
guard.pressure()
}
#[no_mangle]
pub extern "C" fn llmosafe_get_stability(synapse_bits: u128) -> i32 {
let synapse = Synapse::from_raw_u128(synapse_bits);
match synapse.validate() {
Ok(()) => 0,
Err(KernelError::CognitiveInstability) => -2,
Err(KernelError::BiasHaloDetected) => -3,
Err(KernelError::DepthExceeded) => -1,
Err(KernelError::HallucinationDetected) => -4,
Err(KernelError::ResourceExhaustion) => -5,
Err(KernelError::SelfMemoryExceeded) => -6,
Err(KernelError::DeadlineExceeded) => -7,
}
}
#[no_mangle]
#[allow(clippy::not_unsafe_ptr_arg_deref)]
pub extern "C" fn llmosafe_get_memory_stats(
instance_id: u32,
mean: *mut f64,
variance: *mut f64,
trend: *mut f64,
drifting: *mut u32,
) -> u32 {
if mean.is_null() || variance.is_null() || trend.is_null() || drifting.is_null() {
return 1;
}
let arena = PIPELINE_ARENA
.lock()
.unwrap_or_else(std::sync::PoisonError::into_inner);
let idx = instance_id as usize;
if idx >= ARENA_SIZE {
return 1;
}
let slot = match &arena[idx] {
Some(s) => s,
None => return 1,
};
let stats = slot.pipeline.memory_stats();
unsafe {
std::ptr::write_unaligned(mean, stats.mean);
std::ptr::write_unaligned(variance, stats.variance);
std::ptr::write_unaligned(trend, stats.trend);
std::ptr::write_unaligned(drifting, stats.is_drifting as u32);
}
0
}
#[no_mangle]
pub extern "C" fn llmosafe_get_system_cpu_load() -> u8 {
ResourceGuard::system_cpu_load()
}
#[no_mangle]
#[allow(clippy::not_unsafe_ptr_arg_deref)]
pub extern "C" fn llmosafe_get_kernel_output(
instance_id: u32,
error_out: *mut f32,
is_stable_out: *mut u8,
depth_out: *mut u32,
) -> i32 {
if error_out.is_null() || is_stable_out.is_null() || depth_out.is_null() {
return -9;
}
let arena = PIPELINE_ARENA
.lock()
.unwrap_or_else(std::sync::PoisonError::into_inner);
if (instance_id as usize) >= ARENA_SIZE {
return -9;
}
arena[instance_id as usize]
.as_ref()
.and_then(|slot| slot.last_result.as_ref())
.and_then(|r| r.kernel_output())
.map_or(-9, |ko| {
unsafe {
std::ptr::write_unaligned(error_out, ko.error_kernel);
std::ptr::write_unaligned(is_stable_out, if ko.is_stable { 1 } else { 0 });
std::ptr::write_unaligned(depth_out, ko.depth as u32);
}
0
})
}
#[no_mangle]
pub extern "C" fn llmosafe_get_body_pressure(instance_id: u32) -> u32 {
let arena = PIPELINE_ARENA
.lock()
.unwrap_or_else(std::sync::PoisonError::into_inner);
if (instance_id as usize) >= ARENA_SIZE {
return u32::MAX;
}
arena[instance_id as usize]
.as_ref()
.map_or(u32::MAX, |slot| {
slot.last_result
.as_ref()
.map_or(u32::MAX, |r| u32::from(r.body_pressure()))
})
}
#[no_mangle]
pub extern "C" fn llmosafe_combined_risk_bits(synapse_bits: u128) -> u16 {
let synapse = Synapse::from_raw_u128(synapse_bits);
synapse.combined_risk_bits()
}
#[no_mangle]
pub extern "C" fn llmosafe_get_entropy(instance_id: u32) -> u16 {
let arena = PIPELINE_ARENA
.lock()
.unwrap_or_else(std::sync::PoisonError::into_inner);
if (instance_id as usize) >= ARENA_SIZE {
return 0;
}
arena[instance_id as usize]
.as_ref()
.map_or(0, |slot| slot.last_result.as_ref().map_or(0, |r| r.entropy))
}
#[no_mangle]
pub extern "C" fn llmosafe_get_surprise(instance_id: u32) -> u16 {
let arena = PIPELINE_ARENA
.lock()
.unwrap_or_else(std::sync::PoisonError::into_inner);
if (instance_id as usize) >= ARENA_SIZE {
return 0;
}
arena[instance_id as usize].as_ref().map_or(0, |slot| {
slot.last_result.as_ref().map_or(0, |r| r.surprise)
})
}
#[no_mangle]
pub extern "C" fn llmosafe_get_detection_flags(instance_id: u32) -> u8 {
let arena = PIPELINE_ARENA
.lock()
.unwrap_or_else(std::sync::PoisonError::into_inner);
if (instance_id as usize) >= ARENA_SIZE {
return 0;
}
arena[instance_id as usize].as_ref().map_or(0, |slot| {
slot.last_result.as_ref().map_or(0, |r| r.detection_flags)
})
}
#[no_mangle]
pub extern "C" fn llmosafe_get_oov_ratio(instance_id: u32) -> u8 {
let arena = PIPELINE_ARENA
.lock()
.unwrap_or_else(std::sync::PoisonError::into_inner);
if (instance_id as usize) >= ARENA_SIZE {
return 0;
}
arena[instance_id as usize].as_ref().map_or(0, |slot| {
slot.last_result.as_ref().map_or(0, |r| r.oov_ratio)
})
}
#[no_mangle]
pub extern "C" fn llmosafe_get_stages_executed(instance_id: u32) -> u8 {
let arena = PIPELINE_ARENA
.lock()
.unwrap_or_else(std::sync::PoisonError::into_inner);
if (instance_id as usize) >= ARENA_SIZE {
return 0;
}
arena[instance_id as usize].as_ref().map_or(0, |slot| {
slot.last_result.as_ref().map_or(0, |r| r.stages_executed)
})
}
#[no_mangle]
pub extern "C" fn llmosafe_get_step_count(instance_id: u32) -> u32 {
let arena = PIPELINE_ARENA
.lock()
.unwrap_or_else(std::sync::PoisonError::into_inner);
if (instance_id as usize) >= ARENA_SIZE {
return 0;
}
arena[instance_id as usize].as_ref().map_or(0, |slot| {
slot.last_result.as_ref().map_or(0, |r| r.step_count as u32)
})
}
#[no_mangle]
#[allow(clippy::not_unsafe_ptr_arg_deref)]
pub extern "C" fn llmosafe_process_with_pressure(
handle: usize,
text_ptr: *const u8,
text_len: usize,
body_entropy: u16,
pressure: u8,
) -> i32 {
if text_ptr.is_null()
|| text_len == 0
|| text_len > isize::MAX as usize
|| text_len > 10 * 1024 * 1024
{
return -9;
}
let slice = unsafe { core::slice::from_raw_parts(text_ptr, text_len) };
let text = String::from_utf8_lossy(slice);
let mut arena = PIPELINE_ARENA
.lock()
.unwrap_or_else(std::sync::PoisonError::into_inner);
let slot = match get_validated_slot(&mut arena, handle) {
Some(s) => s,
None => return -9,
};
let result = slot
.pipeline
.process_with_pressure(&text, body_entropy, pressure);
let code = decision_to_code(&result.decision);
slot.last_result = Some(result);
code
}
#[no_mangle]
pub extern "C" fn llmosafe_reset_detectors(handle: usize) -> u32 {
let mut arena = PIPELINE_ARENA
.lock()
.unwrap_or_else(std::sync::PoisonError::into_inner);
match get_validated_slot(&mut arena, handle) {
Some(s) => {
s.pipeline.reset_detectors();
0
}
None => 1,
}
}
#[no_mangle]
pub extern "C" fn llmosafe_reset_full(handle: usize) -> u32 {
let mut arena = PIPELINE_ARENA
.lock()
.unwrap_or_else(std::sync::PoisonError::into_inner);
match get_validated_slot(&mut arena, handle) {
Some(s) => {
s.pipeline.reset_full();
0
}
None => 1,
}
}
#[no_mangle]
pub extern "C" fn llmosafe_configure(
instance_id: u32,
dal_level: u8,
use_detection_gate: u32,
_memory_depth: u32,
) -> u32 {
let dal = match dal_level {
0 => crate::control_types::DesignAssuranceLevel::A,
1 => crate::control_types::DesignAssuranceLevel::B,
2 => crate::control_types::DesignAssuranceLevel::C,
3 => crate::control_types::DesignAssuranceLevel::D,
_ => crate::control_types::DesignAssuranceLevel::E,
};
let mut arena = PIPELINE_ARENA
.lock()
.unwrap_or_else(std::sync::PoisonError::into_inner);
let handle = instance_id as usize;
if handle >= ARENA_SIZE {
return 1;
}
match arena[handle].as_mut() {
Some(s) => {
s.pipeline.esc_policy.dal = dal;
s.pipeline.use_detection_gate = use_detection_gate != 0;
0
}
None => 1,
}
}
}
#[cfg(test)]
mod tests {
#[cfg(feature = "std")]
#[test]
fn test_c_abi_process_synapse_valid_bits() {
let bits = 400u128;
let result = crate::c_abi::llmosafe_process_synapse(bits);
assert_eq!(result, 0);
}
#[cfg(feature = "std")]
#[test]
fn test_c_abi_calculate_halo_null_pointer() {
let result = crate::c_abi::llmosafe_calculate_halo(std::ptr::null(), 10);
assert_eq!(result, 0);
}
#[cfg(feature = "std")]
#[test]
fn test_c_abi_calculate_halo_zero_length() {
let data = b"Hello";
let result = crate::c_abi::llmosafe_calculate_halo(data.as_ptr(), 0);
assert_eq!(result, 0);
}
#[cfg(feature = "std")]
#[test]
fn test_c_abi_calculate_halo_large_length() {
let data = b"Hello";
let result =
crate::c_abi::llmosafe_calculate_halo(data.as_ptr(), (isize::MAX as usize) + 1);
assert_eq!(result, 0);
}
#[cfg(feature = "std")]
#[test]
fn test_c_abi_check_resources_ceiling_zero() {
let result = crate::c_abi::llmosafe_check_resources(0);
assert_eq!(result, -5);
}
#[cfg(feature = "std")]
#[test]
fn test_c_abi_invalid_utf8() {
let invalid_data = b"Hello\\xFFWorld\\0";
let result =
crate::c_abi::llmosafe_calculate_halo(invalid_data.as_ptr(), invalid_data.len());
let _ = result;
}
#[cfg(feature = "std")]
#[test]
fn test_c_abi_get_resource_pressure() {
let pressure = crate::c_abi::llmosafe_get_resource_pressure(1024);
assert!(pressure <= 100);
}
#[cfg(feature = "std")]
#[test]
fn test_c_abi_get_stability_valid() {
let valid_bits = 400u128;
let result = crate::c_abi::llmosafe_get_stability(valid_bits);
assert_eq!(result, 0);
}
#[cfg(feature = "std")]
#[test]
fn test_c_abi_get_stability_unstable() {
let unstable_bits = 50001u128;
let result = crate::c_abi::llmosafe_get_stability(unstable_bits);
assert_eq!(result, -2);
}
#[cfg(feature = "std")]
#[test]
fn test_c_abi_get_system_cpu_load() {
let load = crate::c_abi::llmosafe_get_system_cpu_load();
assert!(load <= 100);
}
#[cfg(feature = "std")]
#[test]
fn test_c_abi_get_environmental_entropy() {
let entropy = crate::llmosafe_body::llmosafe_get_environmental_entropy();
let _ = entropy;
}
#[cfg(feature = "std")]
#[test]
fn test_c_abi_create_valid() {
let objective = b"test objective";
let handle = crate::c_abi::llmosafe_create(objective.as_ptr(), objective.len());
assert!(handle != usize::MAX);
crate::c_abi::llmosafe_destroy(handle);
}
#[cfg(feature = "std")]
#[test]
fn test_c_abi_create_null_pointer() {
let handle = crate::c_abi::llmosafe_create(std::ptr::null(), 10);
assert_eq!(handle, usize::MAX);
}
#[cfg(feature = "std")]
#[test]
fn test_c_abi_create_zero_length() {
let objective = b"test";
let handle = crate::c_abi::llmosafe_create(objective.as_ptr(), 0);
assert_eq!(handle, usize::MAX);
}
#[cfg(feature = "std")]
#[test]
fn test_c_abi_create_overflow_length() {
let objective = b"test";
let handle = crate::c_abi::llmosafe_create(objective.as_ptr(), (isize::MAX as usize) + 1);
assert_eq!(handle, usize::MAX);
}
#[cfg(feature = "std")]
#[test]
fn test_c_abi_create_invalid_utf8_truncation() {
let mut s = String::new();
for _ in 0..1020 {
s.push('a');
}
s.push('🌍'); assert_eq!(s.len(), 1024);
let handle = crate::c_abi::llmosafe_create(s.as_bytes().as_ptr(), s.len());
assert!(handle != usize::MAX);
crate::c_abi::llmosafe_destroy(handle);
}
#[cfg(feature = "std")]
#[test]
fn test_c_abi_sift_and_process_valid() {
let objective = b"safety analysis";
let handle = crate::c_abi::llmosafe_create(objective.as_ptr(), objective.len());
assert!(handle != usize::MAX);
let text = b"a completely normal sentence about everyday topics";
let code = crate::c_abi::llmosafe_sift_and_process(handle, text.as_ptr(), text.len());
assert!((-8..=2).contains(&code));
crate::c_abi::llmosafe_destroy(handle);
}
#[cfg(feature = "std")]
#[test]
fn test_c_abi_sift_and_process_invalid_handle() {
let text = b"some text";
let code = crate::c_abi::llmosafe_sift_and_process(999, text.as_ptr(), text.len());
assert_eq!(code, -9);
}
#[cfg(feature = "std")]
#[test]
fn test_c_abi_sift_and_process_null_pointer() {
let objective = b"test";
let handle = crate::c_abi::llmosafe_create(objective.as_ptr(), objective.len());
assert!(handle != usize::MAX);
let code = crate::c_abi::llmosafe_sift_and_process(handle, std::ptr::null(), 10);
assert_eq!(code, -9);
crate::c_abi::llmosafe_destroy(handle);
}
#[cfg(feature = "std")]
#[test]
fn test_c_abi_sift_and_process_zero_length() {
let objective = b"test";
let handle = crate::c_abi::llmosafe_create(objective.as_ptr(), objective.len());
assert!(handle != usize::MAX);
let text = b"data";
let code = crate::c_abi::llmosafe_sift_and_process(handle, text.as_ptr(), 0);
assert_eq!(code, -9);
crate::c_abi::llmosafe_destroy(handle);
}
#[cfg(feature = "std")]
#[test]
fn test_c_abi_get_decision_after_process() {
let objective = b"test objective";
let handle = crate::c_abi::llmosafe_create(objective.as_ptr(), objective.len());
assert!(handle != usize::MAX);
let text = b"checking safety of input data here";
let _ = crate::c_abi::llmosafe_sift_and_process(handle, text.as_ptr(), text.len());
let decision = crate::c_abi::llmosafe_get_decision(handle);
assert!((-8..=2).contains(&decision));
crate::c_abi::llmosafe_destroy(handle);
}
#[cfg(feature = "std")]
#[test]
fn test_c_abi_get_decision_before_process() {
let objective = b"test";
let handle = crate::c_abi::llmosafe_create(objective.as_ptr(), objective.len());
assert!(handle != usize::MAX);
let decision = crate::c_abi::llmosafe_get_decision(handle);
assert_eq!(decision, -9);
crate::c_abi::llmosafe_destroy(handle);
}
#[cfg(feature = "std")]
#[test]
fn test_c_abi_get_decision_invalid_handle() {
let decision = crate::c_abi::llmosafe_get_decision(999);
assert_eq!(decision, -9);
}
#[cfg(feature = "std")]
#[test]
fn test_c_abi_destroy_valid() {
let objective = b"test";
let handle = crate::c_abi::llmosafe_create(objective.as_ptr(), objective.len());
assert!(handle != usize::MAX);
crate::c_abi::llmosafe_destroy(handle);
let decision = crate::c_abi::llmosafe_get_decision(handle);
assert_eq!(decision, -9);
}
#[cfg(feature = "std")]
#[test]
fn test_c_abi_destroy_invalid_handle_no_crash() {
crate::c_abi::llmosafe_destroy(999);
}
#[cfg(feature = "std")]
#[test]
fn test_c_abi_destroy_double_no_crash() {
let objective = b"test double destroy";
let handle = crate::c_abi::llmosafe_create(objective.as_ptr(), objective.len());
assert!(handle != usize::MAX);
crate::c_abi::llmosafe_destroy(handle);
crate::c_abi::llmosafe_destroy(handle); }
#[cfg(feature = "std")]
#[test]
fn test_c_abi_create_process_destroy_cycle() {
let objective = b"cycle test";
let handle = crate::c_abi::llmosafe_create(objective.as_ptr(), objective.len());
assert!(handle != usize::MAX);
let text1 = b"first observation for the pipeline test";
let code1 = crate::c_abi::llmosafe_sift_and_process(handle, text1.as_ptr(), text1.len());
assert!((-8..=2).contains(&code1));
let decision1 = crate::c_abi::llmosafe_get_decision(handle);
assert_eq!(code1, decision1);
let text2 = b"second observation for continued testing";
let code2 = crate::c_abi::llmosafe_sift_and_process(handle, text2.as_ptr(), text2.len());
assert!((-8..=2).contains(&code2));
let decision2 = crate::c_abi::llmosafe_get_decision(handle);
assert_eq!(code2, decision2);
crate::c_abi::llmosafe_destroy(handle);
}
#[cfg(feature = "std")]
#[test]
fn test_c_abi_arena_slot_reuse() {
let obj = b"reuse";
let h1 = crate::c_abi::llmosafe_create(obj.as_ptr(), obj.len());
assert!(h1 != usize::MAX);
crate::c_abi::llmosafe_destroy(h1);
let h2 = crate::c_abi::llmosafe_create(obj.as_ptr(), obj.len());
assert!(h2 != usize::MAX);
let text = b"test observation for stale handle check";
let code = crate::c_abi::llmosafe_sift_and_process(h1, text.as_ptr(), text.len());
assert_eq!(code, -9);
crate::c_abi::llmosafe_destroy(h2);
}
#[cfg(feature = "std")]
#[test]
fn test_c_abi_arena_exhaustion() {
let objective = b"exhaust";
let mut handles = Vec::new();
for _ in 0..16 {
let handle = crate::c_abi::llmosafe_create(objective.as_ptr(), objective.len());
assert!(handle != usize::MAX);
handles.push(handle);
}
let fail = crate::c_abi::llmosafe_create(objective.as_ptr(), objective.len());
assert_eq!(fail, usize::MAX);
for h in handles {
crate::c_abi::llmosafe_destroy(h);
}
}
#[cfg(feature = "std")]
#[test]
fn test_c_abi_decision_code_correspondence() {
let objective = b"mapping test objective string";
let handle = crate::c_abi::llmosafe_create(objective.as_ptr(), objective.len());
assert!(handle != usize::MAX);
let safe_text = b"the weather forecast indicates mild temperatures";
let code =
crate::c_abi::llmosafe_sift_and_process(handle, safe_text.as_ptr(), safe_text.len());
assert!((-8..=2).contains(&code));
crate::c_abi::llmosafe_destroy(handle);
}
}