rivven_protocol/lib.rs
1//! Rivven Wire Protocol
2//!
3//! This crate defines the wire protocol types shared between rivven-client and rivvend.
4//! It provides serialization/deserialization for all protocol messages.
5//!
6//! # Wire Format
7//!
8//! All messages use a unified wire format with format auto-detection and correlation ID:
9//!
10//! ```text
11//! ┌─────────────────┬─────────────────┬──────────────────────────┬──────────────────────┐
12//! │ Length (4 bytes)│ Format (1 byte) │ Correlation ID (4 bytes) │ Payload (N bytes) │
13//! │ Big-endian u32 │ 0x00 = postcard │ Big-endian u32 │ Serialized message │
14//! │ │ 0x01 = protobuf │ │ │
15//! └─────────────────┴─────────────────┴──────────────────────────┴──────────────────────┘
16//! ```
17//!
18//! - **postcard** (0x00): High-performance Rust-native binary format
19//! - **protobuf** (0x01): Cross-language format for Go, Java, Python clients
20//! - **correlation_id**: Matches responses to their originating requests
21//!
22//! # Protocol Stability
23//!
24//! The enum variant order is significant for postcard serialization. Changes to variant
25//! order will break wire compatibility with existing clients/servers.
26//!
27//! # Example
28//!
29//! ```rust,ignore
30//! use rivven_protocol::{Request, Response, WireFormat};
31//!
32//! // Serialize with format prefix
33//! let request = Request::Ping;
34//! let bytes = request.to_wire(WireFormat::Postcard, 1)?;
35//!
36//! // Deserialize with auto-detection
37//! let (response, format, correlation_id) = Response::from_wire(&bytes)?;
38//! ```
39
40mod error;
41mod messages;
42mod metadata;
43pub mod serde_utils;
44mod types;
45
46// Protobuf types (optional, for cross-language clients)
47#[cfg(feature = "protobuf")]
48pub mod proto {
49 //! Protobuf-generated types for cross-language client support.
50 //!
51 //! Enable with `--features protobuf`. Used by Go, Java, and other language clients.
52 include!(concat!(env!("OUT_DIR"), "/rivven.protocol.v1.rs"));
53}
54
55// Protobuf conversion utilities
56#[cfg(feature = "protobuf")]
57mod proto_convert;
58
59pub use error::{ProtocolError, Result};
60pub use messages::{
61 DeleteRecordsResult, QuotaAlteration, QuotaEntry, Request, Response, TopicConfigDescription,
62 TopicConfigEntry, TopicConfigValue,
63};
64pub use metadata::{BrokerInfo, PartitionMetadata, TopicMetadata};
65pub use types::{MessageData, SchemaType};
66
67/// Protocol version for compatibility checking
68pub const PROTOCOL_VERSION: u32 = 2;
69
70/// Wire header size: format byte (1) + correlation_id (4)
71pub const WIRE_HEADER_SIZE: usize = 5;
72
73/// Maximum message size (10 MiB)
74///
75/// Aligned with the server default (`max_request_size` = 10 MB) and
76/// `SecureServerConfig::max_message_size` to avoid silent truncation or
77/// misleading protocol-level limits.
78pub const MAX_MESSAGE_SIZE: usize = 10 * 1024 * 1024;
79
80/// Wire format identifier
81#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
82#[repr(u8)]
83pub enum WireFormat {
84 /// Postcard format (Rust-native, fastest)
85 #[default]
86 Postcard = 0x00,
87 /// Protobuf format (cross-language)
88 Protobuf = 0x01,
89}
90
91impl WireFormat {
92 /// Parse format from byte
93 #[inline]
94 pub fn from_byte(b: u8) -> Option<Self> {
95 match b {
96 0x00 => Some(Self::Postcard),
97 0x01 => Some(Self::Protobuf),
98 _ => None,
99 }
100 }
101
102 /// Convert to byte
103 #[inline]
104 pub const fn as_byte(self) -> u8 {
105 self as u8
106 }
107}