nexus-gateway 0.0.1-alpha

S3-compatible object gateway and embedded Nexus console.
use serde::{Deserialize, Serialize};

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CompressionPolicy {
    pub text_level: i32,
    pub entropy_bypass_threshold: f64,
    pub enable_bypass_for_precompressed: bool,
}

impl Default for CompressionPolicy {
    fn default() -> Self {
        Self {
            text_level: 3,
            entropy_bypass_threshold: 7.6,
            enable_bypass_for_precompressed: true,
        }
    }
}

#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum CompressionCodec {
    Zstd,
    Bypass,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CompressionDecision {
    pub codec: CompressionCodec,
    pub level: i32,
    pub bypass_reason: Option<String>,
    pub entropy_score: f64,
    pub mime: String,
}

impl CompressionDecision {
    pub fn to_json(&self) -> String {
        serde_json::to_string(self).unwrap_or_else(|_| "{}".to_string())
    }
}

pub fn decide(content_type: Option<&str>, payload: &[u8], policy: &CompressionPolicy) -> CompressionDecision {
    let mime = content_type.unwrap_or("application/octet-stream").to_ascii_lowercase();
    let entropy = shannon_entropy(payload);
    let looks_precompressed = mime.contains("zip")
        || mime.contains("gzip")
        || mime.contains("video/")
        || mime.contains("audio/")
        || mime.contains("image/")
        || mime.contains("application/pdf");

    if policy.enable_bypass_for_precompressed
        && looks_precompressed
        && entropy >= policy.entropy_bypass_threshold
    {
        return CompressionDecision {
            codec: CompressionCodec::Bypass,
            level: 0,
            bypass_reason: Some("high_entropy_or_precompressed".to_string()),
            entropy_score: entropy,
            mime,
        };
    }

    let level = if mime.contains("json") || mime.contains("text/") || mime.contains("xml") {
        policy.text_level.clamp(1, 5)
    } else {
        1
    };

    CompressionDecision {
        codec: CompressionCodec::Zstd,
        level,
        bypass_reason: None,
        entropy_score: entropy,
        mime,
    }
}

fn shannon_entropy(payload: &[u8]) -> f64 {
    if payload.is_empty() {
        return 0.0;
    }
    let mut counts = [0_u64; 256];
    for b in payload {
        counts[*b as usize] += 1;
    }
    let len = payload.len() as f64;
    let mut entropy = 0.0_f64;
    for c in counts {
        if c == 0 {
            continue;
        }
        let p = c as f64 / len;
        entropy -= p * p.log2();
    }
    entropy
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn text_payload_prefers_zstd() {
        let payload = b"{\"a\":1,\"b\":2}";
        let decision = decide(Some("application/json"), payload, &CompressionPolicy::default());
        assert!(matches!(decision.codec, CompressionCodec::Zstd));
        assert!(decision.level >= 1);
    }

    #[test]
    fn high_entropy_video_prefers_bypass() {
        let payload = (0..=255_u8).collect::<Vec<_>>();
        let decision = decide(Some("video/mp4"), &payload, &CompressionPolicy::default());
        assert!(matches!(decision.codec, CompressionCodec::Bypass));
    }
}