ferrum-interfaces 0.8.4

Core trait contracts for the Ferrum LLM inference engine
Documentation
use super::{BTreeMap, Digest, DynamicStorageProfile, Serialize, Sha256, VNextError};

pub(super) fn invalid_plan(reason: impl Into<String>) -> VNextError {
    VNextError::InvalidExecutionPlan {
        reason: reason.into(),
    }
}

pub(super) fn validate_active_sequence_ceiling(
    maximum_active_sequences: u32,
) -> Result<(), VNextError> {
    if maximum_active_sequences == 0 {
        return Err(invalid_plan(
            "maximum active sequences protocol ceiling must be non-zero",
        ));
    }
    Ok(())
}

pub(super) fn validate_scheduled_token_ceiling(
    maximum_scheduled_tokens: u64,
) -> Result<(), VNextError> {
    if maximum_scheduled_tokens == 0 {
        return Err(invalid_plan(
            "maximum scheduled tokens protocol ceiling must be non-zero",
        ));
    }
    Ok(())
}

pub(super) fn canonical_json(value: serde_json::Value) -> serde_json::Value {
    match value {
        serde_json::Value::Array(values) => {
            serde_json::Value::Array(values.into_iter().map(canonical_json).collect())
        }
        serde_json::Value::Object(values) => serde_json::Value::Object(
            values
                .into_iter()
                .map(|(key, value)| (key, canonical_json(value)))
                .collect::<BTreeMap<_, _>>()
                .into_iter()
                .collect(),
        ),
        scalar => scalar,
    }
}

pub(super) fn canonical_fingerprint<T: Serialize>(
    value: &T,
    context: &'static str,
) -> Result<String, VNextError> {
    let value = serde_json::to_value(value).map_err(|error| VNextError::Serialization {
        context,
        message: error.to_string(),
    })?;
    let bytes =
        serde_json::to_vec(&canonical_json(value)).map_err(|error| VNextError::Serialization {
            context,
            message: error.to_string(),
        })?;
    Ok(format!("{:x}", Sha256::digest(bytes)))
}

pub(super) fn is_canonical_sha256(value: &str) -> bool {
    value.len() == 64
        && value
            .bytes()
            .all(|byte| byte.is_ascii_digit() || (b'a'..=b'f').contains(&byte))
}

pub(super) fn align_up(value: u64, alignment: u64) -> Result<u64, VNextError> {
    if alignment == 0 || !alignment.is_power_of_two() {
        return Err(invalid_plan(
            "allocation alignment is not a non-zero power of two",
        ));
    }
    value
        .checked_add(alignment - 1)
        .map(|rounded| rounded & !(alignment - 1))
        .ok_or_else(|| invalid_plan("aligned allocation size overflows u64"))
}

pub(super) fn quantize_storage_bytes(
    logical_bytes: u64,
    alignment_bytes: u64,
    profile: DynamicStorageProfile,
) -> Result<u64, VNextError> {
    let aligned = align_up(logical_bytes, alignment_bytes)?;
    match profile.allocator() {
        super::DynamicStorageAllocator::LinearArena => Ok(aligned),
        super::DynamicStorageAllocator::FixedBlockArena { block_bytes } => {
            align_up(aligned, block_bytes)
        }
    }
}