vox-types 0.4.0

Base types used by vox crates
Documentation
use facet::Facet;

use crate::{ConnectionSettings, Metadata, Parity, Schema, SessionResumeKey};

// r[impl session.handshake]
// r[impl session.handshake.cbor]
/// CBOR-encoded handshake message exchanged before postcard traffic begins.
#[derive(Debug, Clone, Facet)]
#[repr(u8)]
pub enum HandshakeMessage {
    Hello(Hello),
    HelloYourself(HelloYourself),
    LetsGo(LetsGo),
    Sorry(Sorry),
}

// r[impl session.handshake]
/// Sent by the initiator as the first handshake message.
#[derive(Debug, Clone, Facet)]
pub struct Hello {
    /// The identifier partition desired by the initiator.
    pub parity: Parity,
    /// Connection limits advertised by the initiator for the root connection.
    pub connection_settings: ConnectionSettings,
    // r[impl session.handshake.protocol-schema]
    /// The initiator's schema for MessagePayload — the postcard enum used
    /// for all subsequent communication.
    pub message_payload_schema: Vec<Schema>,
    /// Whether the initiator supports operation-level retry.
    #[facet(default)]
    pub supports_retry: bool,
    /// Session resume key (present only when resuming an existing session).
    #[facet(default)]
    pub resume_key: Option<ResumeKeyBytes>,
    /// Metadata sent by the initiator (e.g. `vox-service` for service routing).
    #[facet(default)]
    pub metadata: Metadata<'static>,
}

// r[impl session.handshake]
/// Sent by the acceptor in response to Hello.
#[derive(Debug, Clone, Facet)]
pub struct HelloYourself {
    /// Connection limits advertised by the acceptor for the root connection.
    pub connection_settings: ConnectionSettings,
    // r[impl session.handshake.protocol-schema]
    /// The acceptor's schema for MessagePayload.
    pub message_payload_schema: Vec<Schema>,
    /// Whether the acceptor supports operation-level retry.
    #[facet(default)]
    pub supports_retry: bool,
    /// Session resume key (generated by acceptor for future resumption).
    #[facet(default)]
    pub resume_key: Option<ResumeKeyBytes>,
    /// Metadata sent by the acceptor.
    #[facet(default)]
    pub metadata: Metadata<'static>,
}

// r[impl session.handshake]
/// Sent by the initiator to confirm schema compatibility and establish the session.
#[derive(Debug, Clone, Facet)]
pub struct LetsGo {}

// r[impl session.handshake.sorry]
/// Sent by either peer to reject the session due to schema incompatibility.
#[derive(Debug, Clone, Facet)]
pub struct Sorry {
    pub reason: String,
}

/// Fixed-size resume key bytes, CBOR-serializable.
#[derive(Debug, Clone, Facet)]
pub struct ResumeKeyBytes {
    pub bytes: Vec<u8>,
}

impl ResumeKeyBytes {
    pub fn from_key(key: &SessionResumeKey) -> Self {
        Self {
            bytes: key.0.to_vec(),
        }
    }

    pub fn to_key(&self) -> Option<SessionResumeKey> {
        if self.bytes.len() == 16 {
            let mut arr = [0u8; 16];
            arr.copy_from_slice(&self.bytes);
            Some(SessionResumeKey(arr))
        } else {
            None
        }
    }
}

/// Result of a completed CBOR handshake.
#[derive(Debug, Clone)]
pub struct HandshakeResult {
    pub role: crate::SessionRole,
    pub our_settings: ConnectionSettings,
    pub peer_settings: ConnectionSettings,
    pub peer_supports_retry: bool,
    /// The resume key for this session. For the acceptor, this is the key
    /// we generated and sent in HelloYourself. For the initiator, this is
    /// the key the acceptor sent us.
    pub session_resume_key: Option<SessionResumeKey>,
    /// The resume key the peer sent in their Hello (initiator→acceptor only).
    /// Used by the acceptor to look up existing sessions for resumption.
    pub peer_resume_key: Option<SessionResumeKey>,
    pub our_schema: Vec<Schema>,
    pub peer_schema: Vec<Schema>,
    /// Metadata received from the peer during handshake.
    pub peer_metadata: Metadata<'static>,
}