Skip to main content

cloud_sdk/transport/response/
attempt.rs

1use super::{ResponseMetadata, ResponseWriter, ResponseWriterError};
2use crate::transport::{ResponseHeaders, StatusCode};
3
4/// Completion metadata returned by an asynchronous transport.
5///
6/// This value does not commit a response. The SDK validates and commits it
7/// only after the transport future returns successfully.
8pub struct ResponseCompletion {
9    status: StatusCode,
10    initialized_len: usize,
11    metadata: ResponseMetadata,
12}
13
14impl ResponseCompletion {
15    /// Describes one completely initialized response.
16    #[must_use]
17    pub const fn new(
18        status: StatusCode,
19        initialized_len: usize,
20        metadata: ResponseMetadata,
21    ) -> Self {
22        Self {
23            status,
24            initialized_len,
25            metadata,
26        }
27    }
28}
29
30/// Non-committing response view supplied to an asynchronous transport.
31///
32/// Implementations may initialize body and header storage, but this type
33/// deliberately exposes no commit operation. Cancellation drops the
34/// SDK-owned outer attempt and clears all partial state.
35///
36/// ```compile_fail
37/// use cloud_sdk::transport::{AsyncResponseStaging, ResponseMetadata, StatusCode};
38/// fn cannot_commit(mut staging: AsyncResponseStaging<'_, '_>) {
39///     staging.commit(StatusCode::OK, 0, ResponseMetadata::EMPTY);
40/// }
41/// ```
42pub struct AsyncResponseStaging<'staging, 'buffer> {
43    writer: &'staging mut ResponseWriter<'buffer>,
44}
45
46impl<'buffer> AsyncResponseStaging<'_, 'buffer> {
47    /// Returns the admitted response-body capacity.
48    #[must_use]
49    pub const fn body_capacity(&self) -> usize {
50        self.writer.body_capacity()
51    }
52
53    /// Returns exclusive access to the admitted response-body prefix.
54    pub fn body_mut(&mut self) -> Result<&mut [u8], ResponseWriterError> {
55        self.writer.body_mut()
56    }
57
58    /// Returns mutable caller-owned response-header storage.
59    pub fn headers_mut(&mut self) -> Result<&mut ResponseHeaders<'buffer>, ResponseWriterError> {
60        self.writer.headers_mut()
61    }
62
63    /// Returns response headers captured so far.
64    #[must_use]
65    pub const fn headers(&self) -> &ResponseHeaders<'buffer> {
66        self.writer.headers()
67    }
68}
69
70/// Cleanup-owning transaction around one response write attempt.
71pub struct ResponseAttempt<'writer, 'buffer> {
72    pub(super) writer: &'writer mut ResponseWriter<'buffer>,
73    pub(super) completed: bool,
74}
75
76impl<'buffer> ResponseAttempt<'_, 'buffer> {
77    /// Returns the admitted response-body capacity.
78    #[must_use]
79    pub const fn body_capacity(&self) -> usize {
80        self.writer.body_capacity()
81    }
82
83    /// Returns exclusive access to the admitted response-body prefix.
84    pub fn body_mut(&mut self) -> Result<&mut [u8], ResponseWriterError> {
85        self.writer.body_mut()
86    }
87
88    /// Returns mutable caller-owned response-header storage.
89    pub fn headers_mut(&mut self) -> Result<&mut ResponseHeaders<'buffer>, ResponseWriterError> {
90        self.writer.headers_mut()
91    }
92
93    /// Returns response headers captured by this attempt.
94    #[must_use]
95    pub const fn headers(&self) -> &ResponseHeaders<'buffer> {
96        self.writer.headers()
97    }
98
99    /// Commits this synchronous attempt exactly once.
100    pub fn commit(
101        &mut self,
102        status: StatusCode,
103        initialized_len: usize,
104        metadata: ResponseMetadata,
105    ) -> Result<(), ResponseWriterError> {
106        self.writer.commit(status, initialized_len, metadata)?;
107        self.completed = true;
108        Ok(())
109    }
110
111    pub(crate) fn staging(&mut self) -> AsyncResponseStaging<'_, 'buffer> {
112        AsyncResponseStaging {
113            writer: self.writer,
114        }
115    }
116
117    /// Commits completion metadata after an asynchronous stage is ready.
118    pub fn commit_completion(
119        &mut self,
120        completion: ResponseCompletion,
121    ) -> Result<(), ResponseWriterError> {
122        self.commit(
123            completion.status,
124            completion.initialized_len,
125            completion.metadata,
126        )
127    }
128}
129
130impl Drop for ResponseAttempt<'_, '_> {
131    fn drop(&mut self) {
132        if !self.completed {
133            self.writer.rollback_attempt();
134        }
135    }
136}