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}