1use core::marker::PhantomData;
4
5use crate::length::LengthField;
6use crate::parse::{ByteReader, Parse, ParseError};
7use crate::serialize::{ByteWriter, Serialize, SerializeError};
8
9#[derive(Debug, Clone, PartialEq, Eq)]
11pub struct FixedLengthString<'a, const LENGTH: usize> {
12 encoded_string: EncodedString<'a>,
13}
14
15impl<'a, const LENGTH: usize> FixedLengthString<'a, LENGTH> {
16 pub fn new(encoded_string: EncodedString<'a>) -> Self {
18 Self { encoded_string }
19 }
20
21 pub fn get_encoded(&self) -> &EncodedString<'_> {
23 &self.encoded_string
24 }
25}
26
27impl<'a, const LENGTH: usize> Parse<'a> for FixedLengthString<'a, LENGTH> {
28 fn parse_partial(reader: &mut ByteReader<'a>) -> Result<Self, ParseError> {
29 let mut string_reader = reader.sub_reader(LENGTH)?;
32 let encoded_string = EncodedString::parse_partial(&mut string_reader)?;
33
34 Ok(Self { encoded_string })
35 }
36}
37
38impl<const LENGTH: usize> Serialize for FixedLengthString<'_, LENGTH> {
39 fn required_length(&self) -> usize {
40 self.encoded_string.required_length()
41 }
42
43 fn serialize_partial(&self, byte_writer: &mut ByteWriter) -> Result<(), SerializeError> {
44 self.encoded_string.serialize_partial(byte_writer)
45 }
46}
47
48#[derive(Debug, Clone, PartialEq, Eq)]
50pub struct DynamicLengthString<'a, L> {
51 encoded_string: EncodedString<'a>,
52 _marker: PhantomData<L>,
53}
54
55impl<'a, L> DynamicLengthString<'a, L> {
56 pub fn new(encoded_string: EncodedString<'a>) -> Self {
58 Self {
59 encoded_string,
60 _marker: PhantomData,
61 }
62 }
63
64 pub fn get_encoded(&self) -> &EncodedString<'_> {
66 &self.encoded_string
67 }
68}
69
70impl<'a, L> Parse<'a> for DynamicLengthString<'a, L>
71where
72 L: LengthField,
73{
74 fn parse_partial(reader: &mut ByteReader<'a>) -> Result<Self, ParseError> {
75 let length = L::get_length(reader)?;
76
77 let mut string_reader = reader.sub_reader(length)?;
80 let encoded_string = EncodedString::parse_partial(&mut string_reader)?;
81
82 Ok(Self {
83 encoded_string,
84 _marker: PhantomData,
85 })
86 }
87}
88
89impl<L> Serialize for DynamicLengthString<'_, L>
90where
91 L: LengthField + Serialize,
92{
93 fn required_length(&self) -> usize {
94 core::mem::size_of::<L>() + self.encoded_string.required_length()
95 }
96
97 fn serialize_partial(&self, byte_writer: &mut ByteWriter) -> Result<(), SerializeError> {
98 let reserved_length = byte_writer.reserve_length()?;
99
100 let length =
101 L::from_length(byte_writer.write_counted(|byte_writer| {
102 self.encoded_string.serialize_partial(byte_writer)
103 })?)?;
104
105 byte_writer.write_length(reserved_length, &length)
106 }
107}
108
109pub trait Utf16Str {
111 fn chars_lossy(&self) -> impl Iterator<Item = char>;
113}
114
115#[derive(Debug, Clone)]
117pub struct Utf16BeStr<'a> {
118 reader: ByteReader<'a>,
119}
120
121impl Serialize for Utf16BeStr<'_> {
122 fn required_length(&self) -> usize {
123 self.reader.len() + 2
124 }
125
126 fn serialize_partial(&self, byte_writer: &mut ByteWriter) -> Result<(), SerializeError> {
127 byte_writer.write_slice(self.reader.remaining_slice())?;
128 byte_writer.write_slice(&[0x0, 0x0])
129 }
130}
131
132impl Utf16Str for Utf16BeStr<'_> {
133 fn chars_lossy(&self) -> impl Iterator<Item = char> {
134 char::decode_utf16(
135 self.reader
136 .remaining_slice()
137 .chunks_exact(2)
138 .map(|bytes| u16::from_be_bytes([bytes[0], bytes[1]])),
139 )
140 .map(|character| character.unwrap_or(char::REPLACEMENT_CHARACTER))
141 }
142}
143
144impl PartialEq for Utf16BeStr<'_> {
145 fn eq(&self, other: &Self) -> bool {
146 self.chars_lossy().eq(other.chars_lossy())
147 }
148}
149
150impl Eq for Utf16BeStr<'_> {}
151
152#[derive(Debug, Clone)]
154pub struct Utf16LeStr<'a> {
155 reader: ByteReader<'a>,
156}
157
158impl Serialize for Utf16LeStr<'_> {
159 fn required_length(&self) -> usize {
160 self.reader.len() + 2
161 }
162
163 fn serialize_partial(&self, byte_writer: &mut ByteWriter) -> Result<(), SerializeError> {
164 byte_writer.write_slice(self.reader.remaining_slice())?;
165 byte_writer.write_slice(&[0x0, 0x0])
166 }
167}
168
169impl Utf16Str for Utf16LeStr<'_> {
170 fn chars_lossy(&self) -> impl Iterator<Item = char> {
171 char::decode_utf16(
172 self.reader
173 .remaining_slice()
174 .chunks_exact(2)
175 .map(|bytes| u16::from_le_bytes([bytes[0], bytes[1]])),
176 )
177 .map(|character| character.unwrap_or(char::REPLACEMENT_CHARACTER))
178 }
179}
180
181impl PartialEq for Utf16LeStr<'_> {
182 fn eq(&self, other: &Self) -> bool {
183 self.chars_lossy().eq(other.chars_lossy())
184 }
185}
186
187impl Eq for Utf16LeStr<'_> {}
188
189pub trait Utf16StrExt {
191 fn utf8_length(&self) -> usize;
193
194 fn create_str<'a>(&'a self, buffer: &'a mut [u8]) -> Result<&'a str, SerializeError>;
196}
197
198impl<T> Utf16StrExt for T
199where
200 T: Utf16Str,
201{
202 fn utf8_length(&self) -> usize {
203 self.chars_lossy().map(char::len_utf8).sum()
204 }
205
206 fn create_str<'a>(&'a self, buffer: &'a mut [u8]) -> Result<&'a str, SerializeError> {
207 let mut offset = 0;
208
209 for character in self.chars_lossy() {
210 if character.len_utf8() > buffer[offset..].len() {
211 return Err(SerializeError::StorageBufferTooSmall);
212 }
213
214 let written = character.encode_utf8(&mut buffer[offset..]);
215 offset += written.len();
216 }
217
218 Ok(core::str::from_utf8(&buffer[..offset]).unwrap())
219 }
220}
221
222#[derive(Debug, Clone, PartialEq, Eq)]
224pub enum EncodedString<'a> {
225 Utf8(&'a str),
227 Utf16Be(Utf16BeStr<'a>),
229 Utf16Le(Utf16LeStr<'a>),
231}
232
233impl<'a> EncodedString<'a> {
234 pub fn create(text: &'a str) -> Self {
236 Self::Utf8(text)
237 }
238
239 pub fn create_utf16_be(text: &str, buffer: &'a mut [u8]) -> Result<Self, SerializeError> {
241 let mut offset = 0;
242
243 for character in text.chars() {
244 let mut character_buffer = [0u16; 2];
245 let encoded = character.encode_utf16(&mut character_buffer);
246
247 for character in encoded.iter_mut() {
248 if buffer[offset..].len() < 2 {
249 return Err(SerializeError::StorageBufferTooSmall);
250 }
251
252 buffer[offset..][..2].copy_from_slice(character.to_be_bytes().as_slice());
253 offset += 2;
254 }
255 }
256
257 let reader = ByteReader::new(&buffer[..offset]);
258 Ok(Self::Utf16Be(Utf16BeStr { reader }))
259 }
260
261 pub fn create_utf16_le(text: &str, buffer: &'a mut [u8]) -> Result<Self, SerializeError> {
263 let mut offset = 0;
264
265 for character in text.chars() {
266 let mut character_buffer = [0u16; 2];
267 let encoded = character.encode_utf16(&mut character_buffer);
268
269 for character in encoded.iter_mut() {
270 if buffer[offset..].len() < 2 {
271 return Err(SerializeError::StorageBufferTooSmall);
272 }
273
274 buffer[offset..][..2].copy_from_slice(character.to_le_bytes().as_slice());
275 offset += 2;
276 }
277 }
278
279 let reader = ByteReader::new(&buffer[..offset]);
280 Ok(Self::Utf16Le(Utf16LeStr { reader }))
281 }
282}
283
284const UTF_8_BOM: [u8; 3] = [0xEF, 0xBB, 0xBF];
288const UTF_16_BE_BOM: [u8; 2] = [0xFE, 0xFF];
289const UTF_16_LE_BOM: [u8; 2] = [0xFF, 0xFE];
290
291impl<'a> Parse<'a> for EncodedString<'a> {
292 fn parse_partial(reader: &mut ByteReader<'a>) -> Result<Self, ParseError> {
293 if reader.consume_matching_bytes(&UTF_8_BOM) {
294 let slice = reader.remaining_slice();
295
296 let Some(zero_position) = slice.iter().position(|byte| *byte == 0) else {
298 return Err(ParseError::PayloadTooShort);
299 };
300
301 let str_slice = reader.read_slice(zero_position).unwrap();
302 let _zero = reader.read_slice(1).unwrap();
303
304 let str =
305 core::str::from_utf8(str_slice).map_err(|_| ParseError::MalformedMessage {
306 failed_at: core::any::type_name::<Self>(),
307 })?;
308
309 return Ok(Self::Utf8(str));
310 }
311
312 if reader.consume_matching_bytes(&UTF_16_BE_BOM) {
313 let mut slice = reader.remaining_slice();
314
315 if slice.len() % 2 != 0 {
317 slice = &slice[..slice.len() - 1];
318 }
319
320 let Some(zero_position) = slice
322 .chunks_exact(2)
323 .map(|bytes| u16::from_be_bytes([bytes[0], bytes[1]]))
324 .position(|character| character == 0)
325 else {
326 return Err(ParseError::PayloadTooShort);
327 };
328
329 let str_reader = reader.sub_reader(zero_position * 2).unwrap();
330 let _zeroes = reader.read_slice(2).unwrap();
331
332 return Ok(Self::Utf16Be(Utf16BeStr { reader: str_reader }));
333 }
334
335 if reader.consume_matching_bytes(&UTF_16_LE_BOM) {
336 let mut slice = reader.remaining_slice();
337
338 if slice.len() % 2 != 0 {
340 slice = &slice[..slice.len() - 1];
341 }
342
343 let Some(zero_position) = slice
345 .chunks_exact(2)
346 .map(|bytes| u16::from_le_bytes([bytes[0], bytes[1]]))
347 .position(|character| character == 0)
348 else {
349 return Err(ParseError::PayloadTooShort);
350 };
351
352 let str_reader = reader.sub_reader(zero_position * 2).unwrap();
353 let _zeroes = reader.read_slice(2).unwrap();
354
355 return Ok(Self::Utf16Le(Utf16LeStr { reader: str_reader }));
356 }
357
358 Err(ParseError::MalformedMessage {
359 failed_at: core::any::type_name::<Self>(),
360 })
361 }
362}
363
364impl Serialize for EncodedString<'_> {
365 fn required_length(&self) -> usize {
366 match self {
367 EncodedString::Utf8(string) => UTF_8_BOM.len() + string.len() + 1,
368 EncodedString::Utf16Be(string) => UTF_16_BE_BOM.len() + string.required_length(),
369 EncodedString::Utf16Le(string) => UTF_16_LE_BOM.len() + string.required_length(),
370 }
371 }
372
373 fn serialize_partial(&self, byte_writer: &mut ByteWriter) -> Result<(), SerializeError> {
374 match self {
375 EncodedString::Utf8(string) => {
376 byte_writer.write_slice(&UTF_8_BOM)?;
377 byte_writer.write_slice(string.as_bytes())?;
378 byte_writer.write_byte(0x0)
379 }
380 EncodedString::Utf16Be(string) => {
381 byte_writer.write_slice(&UTF_16_BE_BOM)?;
382 string.serialize_partial(byte_writer)
383 }
384 EncodedString::Utf16Le(string) => {
385 byte_writer.write_slice(&UTF_16_LE_BOM)?;
386 string.serialize_partial(byte_writer)
387 }
388 }
389 }
390}
391
392#[cfg(test)]
393#[cfg_attr(coverage_nightly, coverage(off))]
394mod fixed_length_string {
395
396 use crate::parse::ParseExt;
397 use crate::string::{EncodedString, FixedLengthString};
398
399 #[test]
400 fn conversion() {
401 const EXPECTED_BYTES: &[u8] = &[
402 0xEF, 0xBB, 0xBF, b'T', b'E', b'S', b'T', 0x0, ];
406
407 let string = FixedLengthString::<'_, 8>::new(EncodedString::create("TEST"));
408
409 test_round_trip!(FixedLengthString::<'_, 8>, string, EXPECTED_BYTES);
410 }
411
412 #[test]
413 fn parse_invalid_encoced_string() {
414 const TEST_BYTES: &[u8] = &[
415 0xEF, 0xFF, 0xFF, b'T', b'E', b'S', b'T', 0x0, ];
419
420 assert!(matches!(
421 FixedLengthString::<'_, 8>::parse(TEST_BYTES),
422 Err(crate::parse::ParseError::MalformedMessage { .. })
423 ));
424 }
425}
426
427#[cfg(test)]
428#[cfg_attr(coverage_nightly, coverage(off))]
429mod dynamic_length_string {
430
431 use crate::parse::ParseExt;
432 use crate::serialize::{SerializeError, SerializeExt};
433 use crate::string::{DynamicLengthString, EncodedString};
434
435 #[test]
436 fn conversion() {
437 const EXPECTED_BYTES: &[u8] = &[
438 0x0, 0x0, 0x0, 0x8, 0xEF, 0xBB, 0xBF, b'T', b'E', b'S', b'T', 0x0, ];
443
444 let string = DynamicLengthString::<'_, u32>::new(EncodedString::create("TEST"));
445
446 test_round_trip!(DynamicLengthString::<'_, u32>, string, EXPECTED_BYTES);
447 }
448
449 #[test]
450 fn parse_invalid_encoced_string() {
451 const TEST_BYTES: &[u8] = &[
452 0x0, 0x0, 0x0, 0x8, 0xEF, 0xFF, 0xFF, b'T', b'E', b'S', b'T', 0x0, ];
457
458 assert!(matches!(
459 DynamicLengthString::<'_, u32>::parse(TEST_BYTES),
460 Err(crate::parse::ParseError::MalformedMessage { .. })
461 ));
462 }
463
464 #[test]
465 fn serialize_length_overflow() {
466 let long_str = core::str::from_utf8(&[b'a'; 256]).unwrap();
467
468 let string = DynamicLengthString::<'_, u8>::new(EncodedString::create(long_str));
469
470 assert_eq!(
471 string.serialize(&mut [0; 512]),
472 Err(SerializeError::LengthOverflow)
473 );
474 }
475}
476
477#[cfg(test)]
478#[cfg_attr(coverage_nightly, coverage(off))]
479mod encoded_string {
480
481 use super::Utf16StrExt;
482 use crate::parse::{ByteReader, Parse, ParseError, ParseExt};
483 use crate::serialize::SerializeError;
484 use crate::string::{EncodedString, Utf16Str};
485
486 #[test]
487 fn create_utf8() {
488 let string = EncodedString::create("TEßT");
489 assert!(matches!(string, EncodedString::Utf8("TEßT")));
490 }
491
492 #[test]
493 fn create_utf16_be() {
494 let mut buffer = [0u8; 8];
495 let string = EncodedString::create_utf16_be("TEßT", &mut buffer).unwrap();
496
497 let EncodedString::Utf16Be(string) = string else {
498 panic!("incorrect encoded string type");
499 };
500
501 let mut buffer = [0u8; 64];
502 let string = string.create_str(&mut buffer).unwrap();
503
504 assert_eq!(string, "TEßT");
505 }
506
507 #[test]
508 fn create_utf16_be_insufficient_buffer() {
509 let mut buffer = [0u8; 7];
510
511 assert_eq!(
512 EncodedString::create_utf16_be("TEßT", &mut buffer),
513 Err(SerializeError::StorageBufferTooSmall)
514 );
515 }
516
517 #[test]
518 fn create_utf16_le() {
519 let mut buffer = [0u8; 8];
520 let string = EncodedString::create_utf16_le("TEßT", &mut buffer).unwrap();
521
522 let EncodedString::Utf16Le(string) = string else {
523 panic!("incorrect encoded string type");
524 };
525
526 let mut buffer = [0u8; 64];
527 let string = string.create_str(&mut buffer).unwrap();
528
529 assert_eq!(string, "TEßT");
530 }
531
532 #[test]
533 fn create_utf16_le_insufficient_buffer() {
534 let mut buffer = [0u8; 7];
535
536 assert_eq!(
537 EncodedString::create_utf16_le("TEßT", &mut buffer),
538 Err(SerializeError::StorageBufferTooSmall)
539 );
540 }
541
542 #[test]
543 fn utf8_valid() {
544 const EXPECTED_BYTES: &[u8] = &[
545 0xEF, 0xBB, 0xBF, b'T', b'E', b'S', b'T', 0x0, ];
549
550 let encoded = EncodedString::Utf8("TEST");
551
552 test_round_trip!(EncodedString, encoded, EXPECTED_BYTES);
553 }
554
555 #[test]
556 fn parse_utf8_invalid() {
557 const BYTES: &[u8] = &[
558 0xEF, 0xBB, 0xBF, 0xE2, 0x28, 0xA1, 0x0, ];
562
563 assert!(matches!(
564 EncodedString::parse(BYTES),
565 Err(ParseError::MalformedMessage { .. })
566 ));
567 }
568
569 #[test]
570 fn utf16_be_valid() {
571 const EXPECTED_BYTES: &[u8] = &[
572 0xFE, 0xFF, 0x0, b'T', 0x0, b'E', 0x0, b'S', 0x0, b'T', 0x0, 0x0, ];
576
577 let mut buffer = [0u8; 64];
578 let encoded = EncodedString::create_utf16_be("TEST", &mut buffer).unwrap();
579
580 test_round_trip!(EncodedString, encoded, EXPECTED_BYTES);
581 }
582
583 #[test]
584 fn parse_utf16_be_uneven_length() {
585 const BYTES: &[u8] = &[
586 0xFE, 0xFF, 0x0, b'T', 0x0, b'E', 0x0, b'S', 0x0, b'T', 0x0, 0x0, 0xFF, ];
591
592 const EXPECTED_CHARACTERS: &[char] = &['T', 'E', 'S', 'T'];
593
594 let mut reader = ByteReader::new(BYTES);
595
596 let Ok(EncodedString::Utf16Be(string)) = EncodedString::parse_partial(&mut reader) else {
597 panic!("failed to parse UTF-16BE string");
598 };
599
600 assert!(
601 string.chars_lossy().eq(EXPECTED_CHARACTERS.iter().copied()),
602 "expected string doesn't match"
603 );
604 }
605
606 #[test]
607 fn parse_utf16_le_valid() {
608 const EXPECTED_BYTES: &[u8] = &[
609 0xFF, 0xFE, b'T', 0x0, b'E', 0x0, b'S', 0x0, b'T', 0x0, 0x0, 0x0, ];
613
614 let mut buffer = [0u8; 64];
615 let encoded = EncodedString::create_utf16_le("TEST", &mut buffer).unwrap();
616
617 test_round_trip!(EncodedString, encoded, EXPECTED_BYTES);
618 }
619
620 #[test]
621 fn parse_utf16_le_uneven_length() {
622 const BYTES: &[u8] = &[
623 0xFF, 0xFE, b'T', 0x0, b'E', 0x0, b'S', 0x0, b'T', 0x0, 0x0, 0x0, 0xFF, ];
628
629 const EXPECTED_CHARACTERS: &[char] = &['T', 'E', 'S', 'T'];
630
631 let mut reader = ByteReader::new(BYTES);
632
633 let Ok(EncodedString::Utf16Le(string)) = EncodedString::parse_partial(&mut reader) else {
634 panic!("failed to parse UTF-16LE string");
635 };
636
637 assert!(
638 string.chars_lossy().eq(EXPECTED_CHARACTERS.iter().copied()),
639 "expected string doesn't match"
640 );
641 }
642
643 #[test]
644 fn invali_bom() {
645 const BYTES: &[u8] = &[
646 0xEF, 0xBB, 0xBB, ];
648
649 let mut reader = ByteReader::new(BYTES);
650
651 assert!(matches!(
652 EncodedString::parse_partial(&mut reader),
653 Err(ParseError::MalformedMessage { .. })
654 ));
655 }
656}
657
658#[cfg(test)]
659#[cfg_attr(coverage_nightly, coverage(off))]
660mod utf16_ext {
661 use crate::parse::{ByteReader, Parse};
662 use crate::serialize::SerializeError;
663 use crate::string::{EncodedString, Utf16StrExt};
664
665 #[test]
666 fn utf16_required_length() {
667 const BYTES: &[u8] = &[
668 0xFE, 0xFF, 0x0, b'T', 0x0, b'E', 0x0, b'S', 0x0, b'T', 0x0, 0x0, ];
672
673 let mut reader = ByteReader::new(BYTES);
674
675 let Ok(EncodedString::Utf16Be(string)) = EncodedString::parse_partial(&mut reader) else {
676 panic!("failed to decode UTF-16BE string");
677 };
678
679 assert_eq!(string.utf8_length(), 4);
680 }
681
682 #[test]
683 fn utf16_create_str() {
684 const BYTES: &[u8] = &[
685 0xFE, 0xFF, 0x0, b'T', 0x0, b'E', 0x0, b'S', 0x0, b'T', 0x0, 0x0, ];
689
690 let mut reader = ByteReader::new(BYTES);
691
692 let Ok(EncodedString::Utf16Be(string)) = EncodedString::parse_partial(&mut reader) else {
693 panic!("failed to decode UTF-16BE string");
694 };
695
696 let mut buffer = [0u8; 4];
697 let utf8_string = string.create_str(&mut buffer).unwrap();
698
699 assert_eq!(utf8_string, "TEST");
700 }
701
702 #[test]
703 fn utf16_create_str_insufficient_buffer() {
704 const BYTES: &[u8] = &[
705 0xFE, 0xFF, 0x0, b'T', 0x0, b'E', 0x0, b'S', 0x0, b'T', 0x0, 0x0, ];
709
710 let mut reader = ByteReader::new(BYTES);
711
712 let Ok(EncodedString::Utf16Be(string)) = EncodedString::parse_partial(&mut reader) else {
713 panic!("failed to decode UTF-16BE string");
714 };
715
716 let mut buffer = [0u8; 3];
717 assert_eq!(
718 string.create_str(&mut buffer),
719 Err(SerializeError::StorageBufferTooSmall)
720 );
721 }
722}