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 BatchRecord, DeleteRecordsResult, QuotaAlteration, QuotaEntry, Request, Response,
62 SyncGroupAssignments, TopicConfigDescription, TopicConfigEntry, TopicConfigValue,
63};
64pub use metadata::{is_internal_topic, 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/// Maximum topic/group/entity name length (256 bytes).
81pub const MAX_NAME_LEN: usize = 256;
82
83/// Maximum number of items in a list field (topics, partitions, configs, etc.).
84pub const MAX_LIST_LEN: usize = 10_000;
85
86/// Maximum number of messages in a single `Response::Messages` batch.
87pub const MAX_MESSAGES_PER_RESPONSE: usize = 100_000;
88
89/// Maximum authentication / SASL payload (64 KiB).
90pub const MAX_AUTH_PAYLOAD: usize = 64 * 1024;
91
92/// Wire format identifier
93#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
94#[repr(u8)]
95pub enum WireFormat {
96 /// Postcard format (Rust-native, fastest)
97 #[default]
98 Postcard = 0x00,
99 /// Protobuf format (cross-language)
100 Protobuf = 0x01,
101}
102
103impl WireFormat {
104 /// Parse format from byte
105 #[inline]
106 pub fn from_byte(b: u8) -> Option<Self> {
107 match b {
108 0x00 => Some(Self::Postcard),
109 0x01 => Some(Self::Protobuf),
110 _ => None,
111 }
112 }
113
114 /// Convert to byte
115 #[inline]
116 pub const fn as_byte(self) -> u8 {
117 self as u8
118 }
119}