Skip to main content

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}