use super::*;
pub const SMALL_OBJECT_MODE_DIRECT: &str = "direct-small-object";
pub const SMALL_OBJECT_MODE_PACKED: &str = "packed-small-object";
pub const SMALL_OBJECT_MODE_INDEXED_PACK: &str = "indexed-pack";
pub const SMALL_OBJECT_MODE_AMPLIFICATION_REDUCED: &str = "amplification-reduced";
const SMALL_OBJECT_THRESHOLD_BYTES: usize = 16 * 1024;
const SMALL_OBJECT_CAPABILITIES: &[&str] = &[
"packing",
"indexing",
"metadata-amplification",
"read-amplification",
"write-amplification",
"native-support-state",
"semantic-parity",
"configuration-admin-surface",
"security-governance-impact",
"observability-evidence",
"failure-mode-behavior",
"validation-test-coverage",
"product-specific-caveats",
];
const SMALL_OBJECT_CAVEATS: &[&str] = &[
"BucketWarden supports direct small-object writes, reads, lists, metadata, and evidence under the local runtime boundary.",
"Small-object threshold classification is explicit and observable, but objects are not packed into shared containers.",
"Packed small objects, pack indexes, and read/write/metadata amplification-reduction modes are tracked but fail closed.",
"Small-object proof does not claim container packing, compaction, shared-index recovery, or reduced IO amplification.",
];
const SMALL_OBJECT_FAILURE_MODES: &[&str] = &[
"unsupported-small-object-mode-rejected",
"packed-small-object-mode-rejected",
"indexed-pack-mode-rejected",
"amplification-reduction-mode-rejected",
"invalid-small-object-threshold-rejected",
];
#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
pub struct SmallObjectOptimizationEntry {
pub mode: &'static str,
pub native_support: bool,
pub semantic_parity: &'static str,
pub storage_behavior: &'static str,
pub amplification_behavior: &'static str,
pub failure_mode: &'static str,
pub caveat: &'static str,
}
#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
pub struct SmallObjectOptimizationReport {
pub active_mode: &'static str,
pub small_object_threshold_bytes: usize,
pub supported_modes: Vec<&'static str>,
pub unsupported_modes: Vec<&'static str>,
pub capabilities: Vec<&'static str>,
pub failure_modes: Vec<&'static str>,
pub caveats: Vec<&'static str>,
pub entries: Vec<SmallObjectOptimizationEntry>,
}
#[derive(Clone, Debug, Default, Eq, PartialEq, Serialize)]
pub struct SmallObjectOptimizationPolicy {
pub mode: String,
pub threshold_bytes: Option<usize>,
pub pack_objects: bool,
pub external_index: bool,
pub reduce_read_amplification: bool,
pub reduce_write_amplification: bool,
pub reduce_metadata_amplification: bool,
}
impl BucketWarden {
pub fn small_object_optimization_report(&self) -> SmallObjectOptimizationReport {
SmallObjectOptimizationReport {
active_mode: SMALL_OBJECT_MODE_DIRECT,
small_object_threshold_bytes: SMALL_OBJECT_THRESHOLD_BYTES,
supported_modes: vec![SMALL_OBJECT_MODE_DIRECT],
unsupported_modes: vec![
SMALL_OBJECT_MODE_PACKED,
SMALL_OBJECT_MODE_INDEXED_PACK,
SMALL_OBJECT_MODE_AMPLIFICATION_REDUCED,
],
capabilities: SMALL_OBJECT_CAPABILITIES.to_vec(),
failure_modes: SMALL_OBJECT_FAILURE_MODES.to_vec(),
caveats: SMALL_OBJECT_CAVEATS.to_vec(),
entries: vec![
SmallObjectOptimizationEntry {
mode: SMALL_OBJECT_MODE_DIRECT,
native_support: true,
semantic_parity: "Small objects use the same committed object version, metadata, encryption, lock, list, and read semantics as larger objects.",
storage_behavior: "Small object bodies are stored directly as object versions rather than packed into shared containers.",
amplification_behavior: "No reduced amplification claim is made beyond direct runtime read/write/list paths.",
failure_mode: "Invalid threshold or unsupported optimization policy is rejected before claiming support.",
caveat: "Direct small-object support does not claim container packing or IO amplification reduction.",
},
SmallObjectOptimizationEntry {
mode: SMALL_OBJECT_MODE_PACKED,
native_support: false,
semantic_parity: "No packed-object container, offset table, or compaction semantics are claimed.",
storage_behavior: "Packed small-object storage is out of the current runtime boundary.",
amplification_behavior: "Packing-related amplification reductions are not claimed.",
failure_mode: "Packed small-object mode selection is rejected as unsupported.",
caveat: "Packing needs container indexes, compaction, recovery, and garbage-collection proof.",
},
SmallObjectOptimizationEntry {
mode: SMALL_OBJECT_MODE_INDEXED_PACK,
native_support: false,
semantic_parity: "No external pack index or packed-object lookup semantics are claimed.",
storage_behavior: "Indexed pack storage is out of the current runtime boundary.",
amplification_behavior: "Index-based read amplification reductions are not claimed.",
failure_mode: "Indexed pack mode selection is rejected as unsupported.",
caveat: "Pack indexing needs durable index and corruption-recovery contracts.",
},
SmallObjectOptimizationEntry {
mode: SMALL_OBJECT_MODE_AMPLIFICATION_REDUCED,
native_support: false,
semantic_parity: "No metadata, read, or write amplification reduction semantics are claimed.",
storage_behavior: "Amplification-reduced storage is out of the current runtime boundary.",
amplification_behavior: "Reduced metadata/read/write amplification modes are rejected.",
failure_mode: "Amplification-reduction mode selection is rejected as unsupported.",
caveat: "Amplification reduction needs measurable storage engine behavior and benchmarks.",
},
],
}
}
pub fn is_small_object(&self, body_len: usize) -> bool {
body_len <= SMALL_OBJECT_THRESHOLD_BYTES
}
pub fn ensure_small_object_mode_supported(&self, mode: &str) -> Result<(), RuntimeError> {
let report = self.small_object_optimization_report();
if report.supported_modes.contains(&mode) {
Ok(())
} else {
Err(RuntimeError::UnsupportedSmallObjectOptimization(
mode.to_string(),
))
}
}
pub fn validate_small_object_optimization_policy(
&self,
policy: &SmallObjectOptimizationPolicy,
) -> Result<(), RuntimeError> {
self.ensure_small_object_mode_supported(&policy.mode)?;
if policy
.threshold_bytes
.is_some_and(|threshold| threshold == 0)
{
return Err(RuntimeError::InvalidSmallObjectOptimizationPolicy(
"small-object threshold must be nonzero".to_string(),
));
}
if policy.pack_objects {
return Err(RuntimeError::InvalidSmallObjectOptimizationPolicy(
"packed small-object containers are outside the current boundary".to_string(),
));
}
if policy.external_index {
return Err(RuntimeError::InvalidSmallObjectOptimizationPolicy(
"external small-object indexes are outside the current boundary".to_string(),
));
}
if policy.reduce_read_amplification
|| policy.reduce_write_amplification
|| policy.reduce_metadata_amplification
{
return Err(RuntimeError::InvalidSmallObjectOptimizationPolicy(
"amplification reduction is outside the current small-object boundary".to_string(),
));
}
Ok(())
}
}