praxis_filter/body/builder.rs
1// SPDX-License-Identifier: MIT
2// Copyright (c) 2024 Praxis Contributors
3
4//! Pre-computed body processing capabilities for filter pipelines.
5
6use super::BodyMode;
7
8// -----------------------------------------------------------------------------
9// BodyCapabilities
10// -----------------------------------------------------------------------------
11
12/// Pre-computed body processing capabilities for a pipeline.
13///
14/// ```
15/// use praxis_filter::{BodyCapabilities, BodyMode};
16///
17/// let caps = BodyCapabilities::default();
18/// assert!(!caps.needs_request_body);
19/// assert!(!caps.needs_response_body);
20/// assert_eq!(caps.request_body_mode, BodyMode::Stream);
21/// assert_eq!(caps.response_body_mode, BodyMode::Stream);
22///
23/// let caps = BodyCapabilities {
24/// needs_request_body: true,
25/// request_body_mode: BodyMode::StreamBuffer {
26/// max_bytes: Some(4096),
27/// },
28/// ..Default::default()
29/// };
30/// assert!(caps.needs_request_body);
31/// assert!(matches!(
32/// caps.request_body_mode,
33/// BodyMode::StreamBuffer {
34/// max_bytes: Some(4096)
35/// }
36/// ));
37/// assert!(!caps.needs_response_body, "unset fields stay at default");
38/// ```
39#[derive(Debug, Clone, Default)]
40#[expect(clippy::struct_excessive_bools, reason = "capability flags")]
41pub struct BodyCapabilities {
42 /// Whether any filter writes to the request body.
43 pub any_request_body_writer: bool,
44
45 /// Whether any filter writes to the response body.
46 pub any_response_body_writer: bool,
47
48 /// Whether any response condition references headers.
49 pub any_response_condition_uses_headers: bool,
50
51 /// Whether any filter needs request body access.
52 pub needs_request_body: bool,
53
54 /// Whether any filter needs the original request context during body phases.
55 pub needs_request_context: bool,
56
57 /// Whether any filter needs response body access.
58 pub needs_response_body: bool,
59
60 /// Resolved request body mode (`StreamBuffer` if any filter requires it).
61 pub request_body_mode: BodyMode,
62
63 /// Resolved response body mode (`StreamBuffer` if any filter requires it).
64 pub response_body_mode: BodyMode,
65}
66
67// -----------------------------------------------------------------------------
68// Tests
69// -----------------------------------------------------------------------------
70
71#[cfg(test)]
72mod tests {
73 use super::*;
74
75 #[test]
76 fn body_capabilities_default_is_no_op() {
77 let caps = BodyCapabilities::default();
78
79 assert!(!caps.needs_request_body, "default caps should not need request body");
80 assert!(!caps.needs_response_body, "default caps should not need response body");
81 assert!(
82 !caps.any_request_body_writer,
83 "default caps should have no request body writer"
84 );
85 assert!(
86 !caps.any_response_body_writer,
87 "default caps should have no response body writer"
88 );
89 assert!(
90 !caps.needs_request_context,
91 "default caps should not need request context"
92 );
93 assert_eq!(
94 caps.request_body_mode,
95 BodyMode::Stream,
96 "default request mode should be Stream"
97 );
98 assert_eq!(
99 caps.response_body_mode,
100 BodyMode::Stream,
101 "default response mode should be Stream"
102 );
103 }
104}