Skip to main content

cloud_sdk/transport/
workspace.rs

1//! Fixed response decode and continuation staging owned by a checked guard.
2
3use core::fmt;
4
5use cloud_sdk_sanitization::sanitize_bytes;
6
7/// Decoder scratch bytes available to checked provider decoders.
8pub const RESPONSE_DECODER_SCRATCH_BYTES: usize = 256;
9/// Cursor staging bytes available to checked pagination decoders.
10pub const RESPONSE_CURSOR_SCRATCH_BYTES: usize = 1024;
11/// Provider-link staging bytes available to checked pagination decoders.
12pub const RESPONSE_PROVIDER_LINK_SCRATCH_BYTES: usize = 2048;
13
14/// Complete fixed response workspace cleared with its checked guard.
15///
16/// The workspace is intentionally neither `Copy` nor `Clone`. Providers may
17/// use only the exact staging slice needed for one decode operation.
18///
19/// ```compile_fail
20/// use cloud_sdk::transport::ResponseDecodeWorkspace;
21///
22/// fn require_copy<T: Copy>() {}
23/// require_copy::<ResponseDecodeWorkspace>();
24/// ```
25pub struct ResponseDecodeWorkspace {
26    decoder: [u8; RESPONSE_DECODER_SCRATCH_BYTES],
27    cursor: [u8; RESPONSE_CURSOR_SCRATCH_BYTES],
28    provider_link: [u8; RESPONSE_PROVIDER_LINK_SCRATCH_BYTES],
29}
30
31impl ResponseDecodeWorkspace {
32    pub(crate) const fn new() -> Self {
33        Self {
34            decoder: [0; RESPONSE_DECODER_SCRATCH_BYTES],
35            cursor: [0; RESPONSE_CURSOR_SCRATCH_BYTES],
36            provider_link: [0; RESPONSE_PROVIDER_LINK_SCRATCH_BYTES],
37        }
38    }
39
40    /// Creates an independently cleanup-owning provider decode workspace.
41    #[must_use]
42    pub const fn new_for_provider() -> Self {
43        Self::new()
44    }
45
46    /// Returns decoder scratch storage.
47    pub fn decoder_scratch_mut(&mut self) -> &mut [u8] {
48        &mut self.decoder
49    }
50
51    /// Returns reserved cursor staging for the bounded pagination strategies.
52    ///
53    /// v0.38 establishes cleanup ownership; the first consumer is planned for
54    /// the v0.44 pagination strategy family.
55    pub fn cursor_scratch_mut(&mut self) -> &mut [u8] {
56        &mut self.cursor
57    }
58
59    /// Returns reserved provider-link staging for validated continuation links.
60    ///
61    /// v0.38 establishes cleanup ownership; the first consumer is planned for
62    /// the v0.44 pagination strategy family.
63    pub fn provider_link_scratch_mut(&mut self) -> &mut [u8] {
64        &mut self.provider_link
65    }
66
67    fn clear(&mut self) {
68        sanitize_bytes(&mut self.decoder);
69        sanitize_bytes(&mut self.cursor);
70        sanitize_bytes(&mut self.provider_link);
71    }
72}
73
74impl Drop for ResponseDecodeWorkspace {
75    fn drop(&mut self) {
76        self.clear();
77    }
78}
79
80impl fmt::Debug for ResponseDecodeWorkspace {
81    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
82        formatter.write_str("ResponseDecodeWorkspace([redacted])")
83    }
84}
85
86#[cfg(test)]
87mod tests {
88    use super::ResponseDecodeWorkspace;
89
90    #[test]
91    fn complete_workspace_uses_one_clear_path() {
92        let mut workspace = ResponseDecodeWorkspace::new();
93        workspace.decoder.fill(0x11);
94        workspace.cursor.fill(0x22);
95        workspace.provider_link.fill(0x33);
96        workspace.clear();
97        assert!(workspace.decoder.iter().all(|byte| *byte == 0));
98        assert!(workspace.cursor.iter().all(|byte| *byte == 0));
99        assert!(workspace.provider_link.iter().all(|byte| *byte == 0));
100    }
101}