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