use super::CoreError;
use alloc::{format, string::ToString};
use core::fmt;
pub fn out_of_memory<T: fmt::Display>(context: T) -> CoreError {
CoreError::OutOfMemory(format!("{context}"))
}
#[must_use]
pub fn resource_limit_exceeded(resource: &str, current: usize, limit: usize) -> CoreError {
CoreError::ResourceLimitExceeded {
resource: resource.to_string(),
current,
limit,
}
}
#[must_use]
pub fn feature_not_supported(feature: &str, required_feature: &str) -> CoreError {
CoreError::FeatureNotSupported {
feature: feature.to_string(),
required_feature: required_feature.to_string(),
}
}
pub fn check_memory_limit(
current_bytes: usize,
additional_bytes: usize,
limit_bytes: usize,
) -> Result<(), CoreError> {
let total = current_bytes
.checked_add(additional_bytes)
.ok_or_else(|| out_of_memory("Integer overflow calculating memory usage"))?;
if total > limit_bytes {
return Err(resource_limit_exceeded("memory", total, limit_bytes));
}
Ok(())
}
pub fn check_input_size_limit(input_size: usize, max_size: usize) -> Result<(), CoreError> {
if input_size > max_size {
return Err(resource_limit_exceeded("input_size", input_size, max_size));
}
Ok(())
}
pub fn check_depth_limit(current_depth: usize, max_depth: usize) -> Result<(), CoreError> {
if current_depth > max_depth {
return Err(resource_limit_exceeded(
"nesting_depth",
current_depth,
max_depth,
));
}
Ok(())
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn out_of_memory_creation() {
let error = out_of_memory("Buffer allocation failed");
assert!(matches!(error, CoreError::OutOfMemory(_)));
}
#[test]
fn resource_limit_creation() {
let error = resource_limit_exceeded("memory", 1000, 500);
assert!(matches!(error, CoreError::ResourceLimitExceeded { .. }));
}
#[test]
fn feature_not_supported_creation() {
let error = feature_not_supported("simd", "simd");
assert!(matches!(error, CoreError::FeatureNotSupported { .. }));
}
#[test]
fn memory_limit_within_bounds() {
assert!(check_memory_limit(100, 50, 200).is_ok());
assert!(check_memory_limit(0, 100, 100).is_ok());
}
#[test]
fn memory_limit_exceeded() {
assert!(check_memory_limit(100, 150, 200).is_err());
assert!(check_memory_limit(150, 100, 200).is_err());
}
#[test]
fn memory_limit_overflow() {
let result = check_memory_limit(usize::MAX, 1, usize::MAX);
assert!(result.is_err());
assert!(matches!(result.unwrap_err(), CoreError::OutOfMemory(_)));
}
#[test]
fn input_size_limit_check() {
assert!(check_input_size_limit(500, 1000).is_ok());
assert!(check_input_size_limit(1500, 1000).is_err());
}
#[test]
fn depth_limit_check() {
assert!(check_depth_limit(5, 10).is_ok());
assert!(check_depth_limit(15, 10).is_err());
}
}