lodestone-proto 0.0.16

Versioned protocol envelopes and transport-neutral requests for Lodestone
Documentation
use serde::{Deserialize, Serialize};

/// Endpoint-declared source representation needed after shard execution.
/// Parsed JSON is always present because compatibility and coordinator paths
/// render it; exact stored bytes are carried only for native consumers that
/// promise byte-preserving source projection.
#[derive(Clone, Copy, Debug, Default, Deserialize, Eq, PartialEq, Serialize)]
#[serde(rename_all = "snake_case")]
pub enum SearchSourceProjection {
    Parsed,
    #[default]
    ParsedAndExact,
}

impl SearchSourceProjection {
    #[must_use]
    pub const fn needs_exact_source(self) -> bool {
        matches!(self, Self::ParsedAndExact)
    }
}

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

    #[test]
    fn default_preserves_existing_native_exact_source_contract() {
        assert!(SearchSourceProjection::default().needs_exact_source());
        assert!(!SearchSourceProjection::Parsed.needs_exact_source());
    }

    #[test]
    fn execution_projection_is_not_a_second_serialized_request_authority() -> Result<(), serde_json::Error> {
        let request = crate::SearchRequest {
            execution_source_projection: SearchSourceProjection::Parsed,
            ..crate::SearchRequest::default()
        };
        let bytes = serde_json::to_vec(&request)?;
        assert!(
            !bytes
                .windows(b"execution_source_projection".len())
                .any(|window| { window == b"execution_source_projection" })
        );
        let decoded: crate::SearchRequest = serde_json::from_slice(&bytes)?;
        assert_eq!(
            decoded.execution_source_projection,
            SearchSourceProjection::ParsedAndExact
        );
        Ok(())
    }
}