@@ -260,6 +260,97 @@ where
260
260
}
261
261
}
262
262
263
+ /// A null terminated ascii string.
264
+ #[ derive( DekuWrite , Default , Clone ) ]
265
+ pub struct AsciiString < const N : usize > ( pub VecWrap < u8 , N > ) ;
266
+
267
+ impl < const N : usize > AsciiString < N > {
268
+ /// Return the length of the string
269
+ ///
270
+ /// Null terminator is included.
271
+ pub fn len ( & self ) -> usize {
272
+ self . 0 . len ( )
273
+ }
274
+
275
+ /// Returns whether `len() == 0`.
276
+ pub fn is_empty ( & self ) -> bool {
277
+ self . 0 . is_empty ( )
278
+ }
279
+
280
+ /// Return the underlying bytes.
281
+ ///
282
+ /// This includes any null terminator.
283
+ pub fn as_bytes ( & self ) -> & [ u8 ] {
284
+ & self . 0
285
+ }
286
+ }
287
+
288
+ impl < const N : usize > core:: fmt:: Debug for AsciiString < N > {
289
+ fn fmt ( & self , f : & mut core:: fmt:: Formatter < ' _ > ) -> core:: fmt:: Result {
290
+ write ! ( f, "\" " ) ?;
291
+ for c in self . 0 . escape_ascii ( ) {
292
+ write ! ( f, "{}" , char :: from( c) ) ?;
293
+ }
294
+ write ! ( f, "\" " ) ?;
295
+ if !self . 0 . is_empty ( ) && !self . 0 . ends_with ( & [ 0x00 ] ) {
296
+ write ! ( f, " (missing null terminator)" ) ?;
297
+ }
298
+ Ok ( ( ) )
299
+ }
300
+ }
301
+
302
+ impl < const N : usize > TryFrom < & [ u8 ] > for AsciiString < N > {
303
+ type Error = ( ) ;
304
+
305
+ /// Convert from a byte slice.
306
+ ///
307
+ /// No null terminating byte is added, it should be provided by the caller.
308
+ fn try_from ( v : & [ u8 ] ) -> Result < Self , Self :: Error > {
309
+ Ok ( Self ( VecWrap ( heapless:: Vec :: from_slice ( v) ?) ) )
310
+ }
311
+ }
312
+
313
+ impl < const N : usize > TryFrom < & str > for AsciiString < N > {
314
+ type Error = ( ) ;
315
+
316
+ /// Convert from a `str`.
317
+ ///
318
+ /// A null terminating byte is added.
319
+ fn try_from ( v : & str ) -> Result < Self , Self :: Error > {
320
+ let mut h = heapless:: Vec :: from_slice ( v. as_bytes ( ) ) ?;
321
+ h. push ( 0x00 ) . map_err ( |_| ( ) ) ?;
322
+ Ok ( Self ( VecWrap ( h) ) )
323
+ }
324
+ }
325
+
326
+ impl < ' a , Predicate , const N : usize > DekuReader < ' a , ( Limit < u8 , Predicate > , ( ) ) >
327
+ for AsciiString < N >
328
+ where
329
+ Predicate : FnMut ( & u8 ) -> bool ,
330
+ {
331
+ fn from_reader_with_ctx <
332
+ R : deku:: no_std_io:: Read + deku:: no_std_io:: Seek ,
333
+ > (
334
+ reader : & mut deku:: reader:: Reader < R > ,
335
+ ( limit, _ctx) : ( Limit < u8 , Predicate > , ( ) ) ,
336
+ ) -> core:: result:: Result < Self , DekuError > {
337
+ let Limit :: Count ( count) = limit else {
338
+ return Err ( DekuError :: Assertion (
339
+ "Only count implemented for heapless::Vec" . into ( ) ,
340
+ ) ) ;
341
+ } ;
342
+
343
+ let mut v = heapless:: Vec :: new ( ) ;
344
+ for _ in 0 ..count {
345
+ v. push ( u8:: from_reader_with_ctx ( reader, ( ) ) ?) . map_err ( |_| {
346
+ DekuError :: InvalidParam ( "Too many elements" . into ( ) )
347
+ } ) ?
348
+ }
349
+
350
+ Ok ( AsciiString ( VecWrap ( v) ) )
351
+ }
352
+ }
353
+
263
354
#[ derive( Debug , DekuRead , DekuWrite , PartialEq , Eq , Clone , Copy ) ]
264
355
#[ deku( endian = "little" ) ]
265
356
pub struct SensorId ( pub u16 ) ;
@@ -659,17 +750,15 @@ pub struct FileDescriptorPdr {
659
750
/// File name.
660
751
///
661
752
/// A null terminated string.
662
- // TODO: null terminated string type
663
753
// TODO: max length
664
754
#[ deku( count = "file_name_len" ) ]
665
- pub file_name : VecWrap < u8 , MAX_PDR_TRANSFER > ,
755
+ pub file_name : AsciiString < MAX_PDR_TRANSFER > ,
666
756
667
757
#[ deku( temp, temp_value = "self.oem_file_name.len() as u8" ) ]
668
758
pub oem_file_name_len : u8 ,
669
759
/// OEM file name.
670
760
///
671
- /// A null terminated string.
672
- // TODO: null terminated string type
761
+ /// A null terminated string. Must be empty if `oem_file_classification == 0`.
673
762
#[ deku( count = "oem_file_name_len" ) ]
674
- pub oem_file_name : VecWrap < u8 , MAX_PDR_TRANSFER > ,
763
+ pub oem_file_name : AsciiString < MAX_PDR_TRANSFER > ,
675
764
}
0 commit comments