Skip to main content

braid_http/protocol/
constants.rs

1//! Protocol constants for Braid-HTTP.
2//!
3//! This module defines standard header names, status codes, merge type identifiers,
4//! and other protocol constants used throughout the Braid-HTTP implementation.
5//!
6//! # Organization
7//!
8//! ```text
9//! constants/
10//! ├── Top-level    - Common status codes (STATUS_SUBSCRIPTION, etc.)
11//! ├── status       - All HTTP status codes used by Braid
12//! ├── headers      - All Braid protocol header names (typed)
13//! └── merge_types  - Merge type identifiers
14//! ```
15//!
16//! # Status Codes
17//!
18//! | Code | Constant | Description |
19//! |------|----------|-------------|
20//! | 200 | `status::OK` | Standard response |
21//! | 206 | `status::PARTIAL_CONTENT` | Range-based patches |
22//! | 209 | `STATUS_SUBSCRIPTION` | Subscription update |
23//! | 293 | `STATUS_MERGE_CONFLICT` | Version conflicts |
24//! | 410 | `STATUS_GONE` | History dropped |
25//! | 416 | `STATUS_RANGE_NOT_SATISFIABLE` | Invalid range |
26//!
27//! # Examples
28//!
29//! ```
30//! use crate::protocol;
31//! use crate::protocol::constants::{headers, merge_types};
32//!
33//! // Use top-level constants
34//! let status = 209u16;
35//! if status == protocol::STATUS_SUBSCRIPTION {
36//!     println!("Subscription response");
37//! }
38//!
39//! // Use module constants
40//! if status == protocol::status::SUBSCRIPTION {
41//!     println!("Same as above");
42//! }
43//!
44//! // Use header name constants
45//! let header_name = headers::VERSION;
46//! assert_eq!(header_name, "Version");
47//!
48//! // Use merge type constants
49//! let merge_type = merge_types::DIAMOND;
50//! assert_eq!(merge_type, "diamond");
51//! ```
52//!
53//! # Specification
54//!
55//! See [draft-toomim-httpbis-braid-http-04]:
56//!
57//! - **Section 2**: Versioning and merge types
58//! - **Section 3**: Patches and Content-Range
59//! - **Section 4**: Subscriptions and status codes
60//!
61//! [draft-toomim-httpbis-braid-http-04]: https://datatracker.ietf.org/doc/html/draft-toomim-httpbis-braid-http
62
63// =============================================================================
64// Top-Level Status Code Constants
65// =============================================================================
66
67/// HTTP status code for subscription updates (Section 4).
68///
69/// The server sends this status code (209) when responding to a subscription
70/// request. The connection remains open and updates are streamed as they occur.
71///
72/// # Example
73///
74/// ```
75/// use crate::protocol::STATUS_SUBSCRIPTION;
76///
77/// assert_eq!(STATUS_SUBSCRIPTION, 209);
78/// ```
79pub const STATUS_SUBSCRIPTION: u16 = 209;
80
81/// HTTP status code for merge conflicts (Section 2.2).
82///
83/// The server sends this status code (293) when it detects conflicting versions
84/// during a merge operation. The client should apply the merge strategy specified
85/// by the Merge-Type header to resolve the conflict.
86///
87/// # Example
88///
89/// ```
90/// use crate::protocol::STATUS_MERGE_CONFLICT;
91///
92/// assert_eq!(STATUS_MERGE_CONFLICT, 293);
93/// ```
94pub const STATUS_MERGE_CONFLICT: u16 = 293;
95
96/// HTTP status code for history dropped (Section 4.5).
97///
98/// The server sends this status code (410 Gone) when it has discarded version
99/// history before the requested version. The client must restart synchronization
100/// from scratch by clearing its local state.
101pub const STATUS_GONE: u16 = 410;
102
103/// HTTP status code for range not satisfiable.
104///
105/// The server sends this status code (416) when the requested Content-Range
106/// is invalid or cannot be satisfied (e.g., range exceeds resource size).
107pub const STATUS_RANGE_NOT_SATISFIABLE: u16 = 416;
108
109// =============================================================================
110// Status Code Module
111// =============================================================================
112
113/// Standard HTTP status codes used by Braid-HTTP.
114///
115/// # Example
116///
117/// ```
118/// use crate::protocol::status;
119///
120/// assert_eq!(status::OK, 200);
121/// assert_eq!(status::SUBSCRIPTION, 209);
122/// ```
123pub mod status {
124    /// 200 OK - Standard response
125    pub const OK: u16 = 200;
126
127    /// 206 Partial Content - Range-based patches (RFC 7233)
128    pub const PARTIAL_CONTENT: u16 = 206;
129
130    /// 209 Subscription - Subscription update (Braid-HTTP)
131    pub const SUBSCRIPTION: u16 = 209;
132
133    /// 293 Merge Conflict - Version conflicts detected (Braid-HTTP)
134    pub const MERGE_CONFLICT: u16 = 293;
135
136    /// 410 Gone - History dropped, client must restart
137    pub const GONE: u16 = 410;
138
139    /// 416 Range Not Satisfiable - Invalid range request (RFC 7233)
140    pub const RANGE_NOT_SATISFIABLE: u16 = 416;
141
142    /// 293 Responded via Multiplex (Braid-HTTP extension)
143    pub const RESPONDED_VIA_MULTIPLEX: u16 = 293;
144
145    /// Helper to create a 209 Subscription status code.
146    pub fn subscription_response() -> http::StatusCode {
147        http::StatusCode::from_u16(209).unwrap()
148    }
149
150    /// Helper to create a 293 Multiplex status code.
151    pub fn multiplex_response() -> http::StatusCode {
152        http::StatusCode::from_u16(293).unwrap()
153    }
154}
155
156// =============================================================================
157// Header Names Module
158// =============================================================================
159
160/// Braid protocol header names.
161///
162/// Use these constants when setting or reading Braid-specific headers.
163/// These are typed `axum::http::HeaderName` constants for zero-copy usage.
164///
165/// # Example
166///
167/// ```
168/// use crate::protocol::constants::headers;
169///
170/// assert_eq!(headers::VERSION, "version");
171/// assert_eq!(headers::SUBSCRIBE, "subscribe");
172/// ```
173pub mod headers {
174    use http::HeaderName;
175
176    /// Version header - identifies the version of the resource.
177    pub const VERSION: HeaderName = HeaderName::from_static("version");
178
179    /// Parents header - identifies parent version(s) in the DAG.
180    pub const PARENTS: HeaderName = HeaderName::from_static("parents");
181
182    /// Current-Version header - latest version for catch-up signaling.
183    pub const CURRENT_VERSION: HeaderName = HeaderName::from_static("current-version");
184
185    /// Subscribe header - requests subscription mode.
186    pub const SUBSCRIBE: HeaderName = HeaderName::from_static("subscribe");
187
188    /// Heartbeats header - keep-alive interval for subscriptions.
189    pub const HEARTBEATS: HeaderName = HeaderName::from_static("heartbeats");
190
191    /// Peer header - identifies the client peer.
192    pub const PEER: HeaderName = HeaderName::from_static("peer");
193
194    /// Merge-Type header - conflict resolution strategy.
195    pub const MERGE_TYPE: HeaderName = HeaderName::from_static("merge-type");
196
197    /// Content-Range header - range specification for patches.
198    pub const CONTENT_RANGE: HeaderName = http::header::CONTENT_RANGE;
199
200    /// Patches header - number of patches in multi-patch format.
201    pub const PATCHES: HeaderName = HeaderName::from_static("patches");
202
203    /// Multiplex-Version header - version of the multiplexing protocol.
204    pub const MULTIPLEX_VERSION: HeaderName = HeaderName::from_static("multiplex-version");
205
206    /// Multiplex-Through header - path for multiplexing.
207    pub const MULTIPLEX_THROUGH: HeaderName = HeaderName::from_static("multiplex-through");
208
209    /// Retry-After header - suggested retry delay.
210    pub const RETRY_AFTER: HeaderName = http::header::RETRY_AFTER;
211
212    /// Content-Length header - body length.
213    pub const CONTENT_LENGTH: HeaderName = http::header::CONTENT_LENGTH;
214
215    /// Content-Type header - body media type.
216    pub const CONTENT_TYPE: HeaderName = http::header::CONTENT_TYPE;
217}
218
219// =============================================================================
220// Merge Types Module
221// =============================================================================
222
223/// Merge type identifiers for conflict resolution.
224///
225/// # Example
226///
227/// ```
228/// use crate::protocol::merge_types;
229///
230/// assert_eq!(merge_types::DIAMOND, "diamond");
231/// ```
232pub mod merge_types {
233
234    /// Diamond-types CRDT merge type for collaborative text editing.
235    pub const DIAMOND: &str = "diamond";
236}
237
238// =============================================================================
239// Media Types Module
240// =============================================================================
241
242/// Braid protocol media types.
243pub mod media_types {
244    /// application/braid-patch media type for patch updates (Section 3).
245    pub const BRAID_PATCH: &str = "application/braid-patch";
246}
247
248#[cfg(test)]
249mod tests {
250    use super::*;
251
252    #[test]
253    fn test_status_codes() {
254        assert_eq!(STATUS_SUBSCRIPTION, 209);
255        assert_eq!(STATUS_MERGE_CONFLICT, 293);
256        assert_eq!(STATUS_GONE, 410);
257        assert_eq!(STATUS_RANGE_NOT_SATISFIABLE, 416);
258    }
259
260    #[test]
261    fn test_status_module() {
262        assert_eq!(status::OK, 200);
263        assert_eq!(status::PARTIAL_CONTENT, 206);
264        assert_eq!(status::SUBSCRIPTION, 209);
265        assert_eq!(status::MERGE_CONFLICT, 293);
266    }
267
268    #[test]
269    fn test_header_names() {
270        assert_eq!(headers::VERSION.as_str(), "version");
271        assert_eq!(headers::PARENTS.as_str(), "parents");
272        assert_eq!(headers::SUBSCRIBE.as_str(), "subscribe");
273        assert_eq!(headers::MERGE_TYPE.as_str(), "merge-type");
274    }
275
276    #[test]
277    fn test_merge_types() {
278        assert_eq!(merge_types::DIAMOND, "diamond");
279    }
280}