nerve-ipc 0.2.0

Binary framing protocol for local IPC over Unix Domain Sockets
Documentation
//! Shared protocol types and enums.
//!
//! Defines `MessageType`, `FrameFlags`, `RequestId`, and
//! `ProtocolErrorKind`, plus conversions like `TryFrom<u8>`.

/// Wire-level message type discriminant.
///
/// New types will be added as the protocol evolves; match arms should
/// always include a wildcard (`_`) or use `TryFrom<u8>` rather than
/// directly matching on the integer value.
#[non_exhaustive]
#[repr(u8)]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum MessageType {
    Ping = 0x01,
    SearchQuery = 0x02,
    SearchResult = 0x03,
    AiToken = 0x04,
    Cancel = 0x05,

    // agentic scaffolding
    AgentTaskStart = 0x10,
    AgentTaskEvent = 0x11,
    AgentTaskDone = 0x12,
}

// frame flags
bitflags::bitflags! {
    #[derive(Debug, Clone, Copy, PartialEq, Eq)]
    pub struct FrameFlags: u8 {
        // More frames will follow for this request
        const STREAM = 0b0000_0001;

        // final frame for this request
        const FINAL = 0b0000_0010;
    }
}

// request id
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[repr(transparent)]
pub struct RequestId(pub u64);

/// Internal classification of protocol-level errors.
///
/// New variants will be added as error handling evolves; downstream
/// matches should include a wildcard arm.
#[non_exhaustive]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum ProtocolErrorKind {
    /// The frame magic bytes do not match `0x4E455256` ("NERV").
    InvalidMagic,
    /// The frame version field does not match the supported version.
    UnsupportedVersion,
    /// The frame header or payload cannot be parsed.
    MalformedFrame,
    /// The `payload_length` field exceeds `MAX_PAYLOAD_SIZE`.
    PayloadTooLarge,
    /// The `msg_type` field does not correspond to a known `MessageType`.
    UnknownMessageType,
    /// An implementation-level failure unrelated to wire data.
    InternalError,
}

impl TryFrom<u8> for MessageType {
    type Error = ();

    fn try_from(value: u8) -> Result<Self, Self::Error> {
        match value {
            0x01 => Ok(MessageType::Ping),
            0x02 => Ok(MessageType::SearchQuery),
            0x03 => Ok(MessageType::SearchResult),
            0x04 => Ok(MessageType::AiToken),
            0x05 => Ok(MessageType::Cancel),
            0x10 => Ok(MessageType::AgentTaskStart),
            0x11 => Ok(MessageType::AgentTaskEvent),
            0x12 => Ok(MessageType::AgentTaskDone),
            _ => Err(()),
        }
    }
}