16
16
*/
17
17
18
18
use crate :: data_model:: { core:: DataModel , objects:: * } ;
19
+ use crate :: interaction_model:: core:: OpCode ;
20
+ use crate :: tlv:: FromTLV ;
19
21
use crate :: transport:: packet:: Packet ;
20
- use crate :: utils :: writebuf :: WriteBuf ;
22
+ use crate :: transport :: proto_demux :: ResponseRequired ;
21
23
use crate :: {
22
24
acl:: { AccessReq , Accessor } ,
23
25
error:: * ,
24
26
interaction_model:: {
25
27
core:: IMStatusCode ,
26
28
messages:: {
27
29
ib:: { self , DataVersionFilter } ,
28
- msg:: { self , ReadReq , ReportDataTag :: MoreChunkedMsgs } ,
30
+ msg:: { self , ReadReq , ReportDataTag :: MoreChunkedMsgs , ReportDataTag :: SupressResponse } ,
29
31
GenericPath ,
30
32
} ,
31
33
Transaction ,
32
34
} ,
33
- tlv:: { TLVArray , TLVWriter , TagType , ToTLV } ,
35
+ tlv:: { self , TLVArray , TLVWriter , TagType , ToTLV } ,
34
36
} ;
35
37
36
38
/// Encoder for generating a response to a read request
@@ -112,7 +114,21 @@ pub struct ResumeReadReq {
112
114
/// will start encoding from this attribute onwards.
113
115
/// Note that given wildcard reads, one PendingPath in the member above can generated
114
116
/// multiple encode paths. Hence this has to be maintained separately.
115
- resume_encode : Option < GenericPath > ,
117
+ resume_from : Option < GenericPath > ,
118
+ }
119
+ impl ResumeReadReq {
120
+ pub fn new ( rx_buf : & [ u8 ] , resume_from : & Option < GenericPath > ) -> Result < Self , Error > {
121
+ let mut packet = Packet :: new_rx ( ) ?;
122
+ let dst = packet. as_borrow_slice ( ) ;
123
+
124
+ let src_len = rx_buf. len ( ) ;
125
+ dst[ ..src_len] . copy_from_slice ( rx_buf) ;
126
+ packet. get_parsebuf ( ) ?. set_len ( src_len) ;
127
+ Ok ( ResumeReadReq {
128
+ pending_req : Some ( packet) ,
129
+ resume_from : * resume_from,
130
+ } )
131
+ }
116
132
}
117
133
118
134
impl DataModel {
@@ -195,9 +211,8 @@ impl DataModel {
195
211
read_req : & ReadReq ,
196
212
trans : & mut Transaction ,
197
213
tw : & mut TLVWriter ,
198
- ) -> Result < Option < ResumeReadReq > , Error > {
199
- let mut resume_read_req: ResumeReadReq = Default :: default ( ) ;
200
-
214
+ resume_from : & mut Option < GenericPath > ,
215
+ ) -> Result < ( ) , Error > {
201
216
let mut attr_encoder = AttrReadEncoder :: new ( tw) ;
202
217
if let Some ( filters) = & read_req. dataver_filters {
203
218
attr_encoder. set_data_ver_filters ( filters) ;
@@ -221,33 +236,43 @@ impl DataModel {
221
236
& accessor,
222
237
& mut attr_encoder,
223
238
& mut attr_details,
224
- & mut resume_read_req . resume_encode ,
239
+ resume_from ,
225
240
) ;
226
241
}
227
242
tw. end_container ( ) ?;
228
243
if result. is_err ( ) {
229
244
// If there was an error, indicate chunking. The resume_read_req would have been
230
245
// already populated from in the loop above.
231
246
tw. bool ( TagType :: Context ( MoreChunkedMsgs as u8 ) , true ) ?;
232
- // Retain the entire request, because we need the data-filters, and subsequent attr-reads, if any
233
- // when we resume this read in the next hop
234
- resume_read_req. pending_req = Some ( copy_read_req_to_packet ( read_req) ?) ;
235
- return Ok ( Some ( resume_read_req) ) ;
247
+ return Ok ( ( ) ) ;
236
248
}
237
249
}
238
- Ok ( None )
250
+ // A None resume_from indicates no chunking
251
+ * resume_from = None ;
252
+ Ok ( ( ) )
239
253
}
240
- }
241
254
242
- fn copy_read_req_to_packet ( read_req : & ReadReq ) -> Result < Packet < ' static > , Error > {
243
- let mut packet = Packet :: new_rx ( ) ?;
244
- let backup = packet. as_borrow_slice ( ) ;
245
- let backup_len = backup. len ( ) ;
246
- let mut wb = WriteBuf :: new ( backup, backup_len) ;
247
- let mut tw = TLVWriter :: new ( & mut wb) ;
248
- // TODO: This is unnecessarily wasteful, could directly copy &[u8] if accessible
249
- read_req. to_tlv ( & mut tw, TagType :: Anonymous ) ?;
250
- let data_len = wb. as_borrow_slice ( ) . len ( ) ;
251
- packet. get_parsebuf ( ) ?. set_len ( data_len) ;
252
- Ok ( packet)
255
+ pub fn handle_resume_read (
256
+ & self ,
257
+ resume_read_req : & mut ResumeReadReq ,
258
+ trans : & mut Transaction ,
259
+ tw : & mut TLVWriter ,
260
+ ) -> Result < ( OpCode , ResponseRequired ) , Error > {
261
+ if let Some ( packet) = resume_read_req. pending_req . as_mut ( ) {
262
+ let rx_buf = packet. get_parsebuf ( ) ?. as_borrow_slice ( ) ;
263
+ let root = tlv:: get_root_node ( rx_buf) ?;
264
+ let req = ReadReq :: from_tlv ( & root) ?;
265
+
266
+ tw. start_struct ( TagType :: Anonymous ) ?;
267
+ self . handle_read_attr_array ( & req, trans, tw, & mut resume_read_req. resume_from ) ?;
268
+
269
+ if resume_read_req. resume_from . is_none ( ) {
270
+ tw. bool ( TagType :: Context ( SupressResponse as u8 ) , true ) ?;
271
+ // Mark transaction complete, if not chunked
272
+ trans. complete ( ) ;
273
+ }
274
+ tw. end_container ( ) ?;
275
+ }
276
+ Ok ( ( OpCode :: ReportData , ResponseRequired :: Yes ) )
277
+ }
253
278
}
0 commit comments