veecle_os_data_support_someip/
string.rs

1//! SOME/IP string types.
2
3use core::marker::PhantomData;
4
5use crate::length::LengthField;
6use crate::parse::{ByteReader, Parse, ParseError};
7use crate::serialize::{ByteWriter, Serialize, SerializeError};
8
9/// A fixed length string.
10#[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    /// Creates a new [`FixedLengthString`].
17    pub fn new(encoded_string: EncodedString<'a>) -> Self {
18        Self { encoded_string }
19    }
20
21    /// Returns the encoded inner string.
22    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        // TODO: Parse an optional string length. We don't know how this is determined yet.
30        // TODO: Assert that the read length is the same as LENGTH.
31        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/// A dynamic length string.
49#[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    /// Creates a new [`DynamicLengthString`].
57    pub fn new(encoded_string: EncodedString<'a>) -> Self {
58        Self {
59            encoded_string,
60            _marker: PhantomData,
61        }
62    }
63
64    /// Returns the encoded inner string.
65    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        // TODO: <https://veecle.atlassian.net/browse/DEV-242>
78
79        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
109/// Trait for working with UTF-16BE and UTF-16LE strings.
110pub trait Utf16Str {
111    /// Returns a lossy iterator over the characters of the string.
112    fn chars_lossy(&self) -> impl Iterator<Item = char>;
113}
114
115/// A UTF-16BE encoded string.
116#[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/// A UTF-16LE encoded string.
153#[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
189/// Extension trait for creating UTF-8 strings from UTF-16 strings.
190pub trait Utf16StrExt {
191    /// Returns the number of bytes required to store this string as UTF-8.
192    fn utf8_length(&self) -> usize;
193
194    /// Create a UTF-8 string from the UTF-16 encoded string in the provided buffer.
195    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/// A string encoded as either UTF-8, UTF-16-BE or UTF-16-LE.
223#[derive(Debug, Clone, PartialEq, Eq)]
224pub enum EncodedString<'a> {
225    /// A UTF-8 encoded string.
226    Utf8(&'a str),
227    /// A UTF-16-BE encoded string.
228    Utf16Be(Utf16BeStr<'a>),
229    /// A UTF-16-LE encoded string.
230    Utf16Le(Utf16LeStr<'a>),
231}
232
233impl<'a> EncodedString<'a> {
234    /// Creates a UTF-8 encoded string.
235    pub fn create(text: &'a str) -> Self {
236        Self::Utf8(text)
237    }
238
239    /// Creates a UTF-16-BE encoded string.
240    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    /// Creates a UTF-16-LE encoded string.
262    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
284// Byte order mark for UTF-8 and UTF-16.
285//
286// See: https://en.wikipedia.org/wiki/Byte_order_mark
287const 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            // UTF-8 strings must be null-terminated.
297            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            // Odd-length UTF-16 strings: ignore last byte.
316            if slice.len() % 2 != 0 {
317                slice = &slice[..slice.len() - 1];
318            }
319
320            // UTF-16 strings must end with 0x0000 (two null bytes).
321            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            // Odd-length UTF-16 strings: ignore last byte.
339            if slice.len() % 2 != 0 {
340                slice = &slice[..slice.len() - 1];
341            }
342
343            // UTF-16 strings must end with 0x0000 (two null bytes).
344            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, // BOM
403            b'T', b'E', b'S', b'T', // Message
404            0x0,  // Zero for termination
405        ];
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, // Invalid BOM
416            b'T', b'E', b'S', b'T', // Message
417            0x0,  // Zero for termination
418        ];
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, // Length (u32)
439            0xEF, 0xBB, 0xBF, // BOM
440            b'T', b'E', b'S', b'T', // Message
441            0x0,  // Zero for termination
442        ];
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, // Length (u32)
453            0xEF, 0xFF, 0xFF, // Invalid BOM
454            b'T', b'E', b'S', b'T', // Message
455            0x0,  // Zero for termination
456        ];
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, // BOM
546            b'T', b'E', b'S', b'T', // Message
547            0x0,  // Zero for termination
548        ];
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, // BOM
559            0xE2, 0x28, 0xA1, // Invalid UTF-8 sequence
560            0x0,  // Zero for termination
561        ];
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, // BOM
573            0x0, b'T', 0x0, b'E', 0x0, b'S', 0x0, b'T', // Message
574            0x0, 0x0, // Zero for termination
575        ];
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, // BOM
587            0x0, b'T', 0x0, b'E', 0x0, b'S', 0x0, b'T', // Message
588            0x0, 0x0,  // Zero for termination
589            0xFF, // Incorrect bytes
590        ];
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, // BOM
610            b'T', 0x0, b'E', 0x0, b'S', 0x0, b'T', 0x0, // Message
611            0x0, 0x0, // Zero for termination
612        ];
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, // BOM
624            b'T', 0x0, b'E', 0x0, b'S', 0x0, b'T', 0x0, // Message
625            0x0, 0x0,  // Zero for termination
626            0xFF, // Incorrect bytes
627        ];
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, // BOM
647        ];
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, // BOM
669            0x0, b'T', 0x0, b'E', 0x0, b'S', 0x0, b'T', // Message
670            0x0, 0x0, // Zero for termination
671        ];
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, // BOM
686            0x0, b'T', 0x0, b'E', 0x0, b'S', 0x0, b'T', // Message
687            0x0, 0x0, // Zero for termination
688        ];
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, // BOM
706            0x0, b'T', 0x0, b'E', 0x0, b'S', 0x0, b'T', // Message
707            0x0, 0x0, // Zero for termination
708        ];
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}