@@ -16,6 +16,9 @@ use crate::commands::measurements_rsp::MeasurementsResponse;
1616
1717#[ derive( Debug , PartialEq ) ]
1818pub enum ChunkError {
19+ /// Super hacky way to signal back the client application via [CommandError::Chunk(ChunkError::None)]
20+ /// that the chunking process has started and that it now has to retrieve the chunked data.
21+ None ,
1922 LargeResponseInitError ,
2023 NoLargeResponseInProgress ,
2124 InvalidChunkHandle ,
@@ -34,6 +37,11 @@ struct ChunkInfo {
3437}
3538
3639impl ChunkInfo {
40+ /// Reset the chunk info.
41+ ///
42+ /// # Arguments
43+ /// - `reset_handle`: If `reset_handle` is set, the handle of the chunk info
44+ /// is set to `0`. If not, it is incremented to be ready for the next chunk operation.
3745 pub fn reset ( & mut self , reset_handle : bool ) {
3846 self . chunk_in_use = false ;
3947 if reset_handle {
@@ -64,7 +72,18 @@ pub(crate) enum LargeResponse {
6472 Measurements ( MeasurementsResponse ) ,
6573}
6674
67- /// Manages the context for ongoing large message responses
75+ /// Manages the context for ongoing large message responses.
76+ /// The naming might be confusion, but we re-use this struct for both requester and responder.
77+ ///
78+ /// # Requester
79+ ///
80+ /// For the requester, this [LargeResponseCtx] is used to track the state
81+ /// of `CHUNK_SEND` commands.
82+ ///
83+ /// # Responder
84+ ///
85+ /// For the responder, this [LargeResponseCtx] is used to track the state
86+ /// of `CHUNK_RESPONSE` commands.
6887#[ derive( Default ) ]
6988pub ( crate ) struct LargeResponseCtx {
7089 chunk_info : ChunkInfo ,
@@ -127,4 +146,82 @@ impl LargeResponseCtx {
127146 pub fn bytes_transferred ( & self ) -> usize {
128147 self . chunk_info . bytes_transferred
129148 }
149+
150+ pub fn seq_no ( & self ) -> u16 {
151+ self . chunk_info . chunk_seq_num
152+ }
153+
154+ pub fn handle ( & self ) -> u8 {
155+ self . chunk_info . chunk_handle
156+ }
157+ }
158+
159+ /// Manages the context for ongoing large message retrievals on the **requester** side.
160+ ///
161+ /// Initialized when the requester receives `ERROR(LargeResponse)` and tracks
162+ /// progress across successive `CHUNK_GET` / `CHUNK_RESPONSE` exchanges until
163+ /// the last chunk has been received.
164+ #[ derive( Default ) ]
165+ pub ( crate ) struct LargeRequestCtx {
166+ chunk_info : ChunkInfo ,
167+ }
168+
169+ impl LargeRequestCtx {
170+ /// Initialize context for a new large response retrieval.
171+ ///
172+ /// Call this when `ERROR(LargeResponse)` is received.
173+ ///
174+ /// # Arguments
175+ /// * `handle` - The handle value carried in `Param2` of the `ERROR` message.
176+ pub ( crate ) fn init ( & mut self , handle : u8 ) {
177+ // Total size is unknown until the first CHUNK_RESPONSE arrives.
178+ self . chunk_info . init ( 0 , Some ( handle) ) ;
179+ }
180+
181+ /// Discard any in-progress retrieval and reset to the initial state.
182+ pub ( crate ) fn reset ( & mut self ) {
183+ self . chunk_info . reset ( true ) ;
184+ }
185+
186+ /// Returns `true` if a large response retrieval is currently in progress.
187+ pub ( crate ) fn in_progress ( & self ) -> bool {
188+ self . chunk_info . chunk_in_use
189+ }
190+
191+ /// Returns the handle identifying the current large response transfer.
192+ pub ( crate ) fn handle ( & self ) -> u8 {
193+ self . chunk_info . chunk_handle
194+ }
195+
196+ /// Returns the `ChunkSeqNo` that shall appear in the next `CHUNK_GET`.
197+ pub ( crate ) fn current_seq_num ( & self ) -> u16 {
198+ self . chunk_info . chunk_seq_num
199+ }
200+
201+ /// Returns the number of bytes successfully received so far.
202+ pub ( crate ) fn bytes_received ( & self ) -> usize {
203+ self . chunk_info . bytes_transferred
204+ }
205+
206+ /// Returns the total size of the large response.
207+ ///
208+ /// Only meaningful after the first `CHUNK_RESPONSE` (`ChunkSeqNo == 0`)
209+ /// has been processed and [`set_total_size`] has been called.
210+ pub ( crate ) fn total_size ( & self ) -> usize {
211+ self . chunk_info . large_msg_size
212+ }
213+
214+ /// Record the total response size decoded from the first `CHUNK_RESPONSE`.
215+ pub ( crate ) fn set_total_size ( & mut self , size : usize ) {
216+ self . chunk_info . large_msg_size = size;
217+ }
218+
219+ /// Advance tracking state after a chunk has been successfully received.
220+ ///
221+ /// Adds `chunk_size` to `bytes_received` and bumps the sequence number so
222+ /// that the next `CHUNK_GET` requests the following chunk.
223+ pub ( crate ) fn advance ( & mut self , chunk_size : usize ) {
224+ self . chunk_info . bytes_transferred += chunk_size;
225+ self . chunk_info . chunk_seq_num = self . chunk_info . chunk_seq_num . wrapping_add ( 1 ) ;
226+ }
130227}
0 commit comments