Skip to main content

rsomeip_bytes/
string.rs

1//! Dynamic and static strings.
2//!
3//! This module provides the [`DynamicString`] and [`StaticString`] types from serializing and
4//! deserializing strings from the SOME/IP on-wire format. It also provides the [`Encoding`] trait
5//! and types for specifying the string encoding.
6
7use crate::{Deserialize, DeserializeError, Serialize, SerializeError};
8use alloc::{string::String, vec::Vec};
9use bytes::{Buf, BufMut};
10use core::marker::PhantomData;
11
12/// Size of the string encoding in bytes.
13///
14/// Includes the size of the Byte Order Mark and the Delimiter.
15///
16/// It's the same for UTF-8 and UTF-16.
17const ENCODING_SIZE: usize = 4;
18
19/// String encoding according to the SOME/IP on-wire format.
20pub trait Encoding: Sealed {
21    /// Serializes the `value` into the given `buffer`.
22    ///
23    /// Includes a Byte Order Mark and a Delimiter before and after the actual string, respectively.
24    ///
25    /// The string must not contain any null characters.
26    ///
27    /// Returns the length of the serialized data.
28    ///
29    /// # Errors
30    ///
31    /// Returns a [`SerializeError`] if the serialization fails. Some data may still be written to
32    /// the buffer if an error occurs.
33    ///
34    /// # Examples
35    ///
36    /// ```rust
37    /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
38    /// use rsomeip_bytes::{Encoding as _, Utf8};
39    ///
40    /// // The buffer can be any type that implements `BufMut`.
41    /// let mut buffer = [0_u8; 11];
42    /// let size = Utf8::serialize("rsomeip", &mut buffer.as_mut_slice())?;
43    ///
44    /// // Size includes the size of the Byte Order Mark, string and delimiter.
45    /// assert_eq!(size, 11);
46    /// assert_eq!(buffer.as_slice(), [
47    ///         0xef_u8, 0xbb, 0xbf, // UTF-8 BOM
48    ///         0x72, 0x73, 0x6f, 0x6d, 0x65, 0x69, 0x70, // "rsomeip"
49    ///         0x00, // Delimiter
50    ///     ].as_slice());
51    /// # Ok(()) }
52    /// ```
53    fn serialize<Value, Buffer>(value: Value, buffer: &mut Buffer) -> Result<usize, SerializeError>
54    where
55        Value: AsRef<str>,
56        Buffer: BufMut + ?Sized;
57
58    /// Returns the size of the `value` when serialized.
59    ///
60    /// Includes the size of the Byte Order Mark and the Delimiter.
61    ///
62    /// Returns [`None`] if the size is out of bounds.
63    ///
64    /// # Examples
65    ///
66    /// ```rust
67    /// use rsomeip_bytes::{Encoding as _, Utf8, Utf16BE, Utf16LE};
68    ///
69    /// // Size includes the size of the Byte Order Mark, string and delimiter.
70    /// assert_eq!(Utf8::size("rsomeip"), Some(11));
71    /// assert_eq!(Utf16BE::size("rsomeip"), Some(18));
72    /// assert_eq!(Utf16LE::size("rsomeip"), Some(18));
73    /// ```
74    fn size<Value>(value: &Value) -> Option<usize>
75    where
76        Value: AsRef<str> + ?Sized;
77
78    /// Deserializes a null-terminated [`String`] from the given `buffer`.
79    ///
80    /// Expects a Byte Order Mark and a Delimiter at the start and end of the string, respectively.
81    ///
82    /// # Errors
83    ///
84    /// Returns a [`DeserializeError`] if the deserialization fails.
85    ///
86    /// Specifically, deserialization fails if the string is not null-terminated or if there is a
87    /// null character before the end of the string.
88    ///
89    /// # Examples
90    ///
91    /// ```rust
92    /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
93    /// use rsomeip_bytes::{Encoding as _, Utf8};
94    ///
95    /// // The buffer can be any type that implements `Buf`.
96    /// let buffer = [
97    ///     0xef_u8, 0xbb, 0xbf, // UTF-8 BOM
98    ///     0x72, 0x73, 0x6f, 0x6d, 0x65, 0x69, 0x70, // "rsomeip"
99    ///     0x00, // Delimiter
100    /// ];
101    ///
102    /// let string = Utf8::deserialize(&mut buffer.as_slice())?;
103    /// assert_eq!(&string, "rsomeip");
104    /// # Ok(()) }
105    /// ```
106    fn deserialize<Buffer>(buffer: &mut Buffer) -> Result<String, DeserializeError>
107    where
108        Buffer: Buf + ?Sized;
109}
110
111/// Sealed trait to prevent external implementations.
112pub trait Sealed {}
113
114/// UTF-8 encoding for strings.
115///
116/// Normally, used with [`StaticString`] and [`DynamicString`].
117///
118/// # Examples
119///
120/// ```rust
121/// # fn main() -> Result<(), Box<dyn std::error::Error>> {
122/// use rsomeip_bytes::{StaticString, Utf8, Serialize as _, Deserialize as _};
123///
124/// // A `StaticString` can be used to always write the same amount of data regardless
125/// // of the size of the string.
126/// let value = String::from("rsomeip");
127/// let string = StaticString::<11, Utf8, _>::from(&value);
128///
129/// // Buffer can be any type that implements `BufMut`.
130/// let mut buffer = [0_u8; 11];
131///
132/// // Serialized data includes Byte Order Mark and Delimiter.
133/// assert_eq!(Ok(11), string.serialize(&mut buffer.as_mut_slice()));
134/// assert_eq!(buffer, [
135///         0xef_u8, 0xbb, 0xbf, // UTF-8 BOM
136///         0x72, 0x73, 0x6f, 0x6d, 0x65, 0x69, 0x70, // "rsomeip"
137///         0x00, // Delimiter
138///     ]);
139///
140/// // Deserialization automatically strips the BOM and Delimiter.
141/// let output = StaticString::<11, Utf8, String>::deserialize(&mut buffer.as_slice())?;
142/// assert_eq!(output, value);
143/// # Ok(()) }
144/// ```
145#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
146pub struct Utf8;
147
148impl Encoding for Utf8 {
149    fn serialize<Value, Buffer>(value: Value, buffer: &mut Buffer) -> Result<usize, SerializeError>
150    where
151        Value: AsRef<str>,
152        Buffer: BufMut + ?Sized,
153    {
154        let string = value.as_ref();
155
156        // UTF-8 Byte Order Mark + String + Delimiter
157        buffer.put_slice(&[0xef_u8, 0xbb, 0xbf]);
158        buffer.put_slice(string.as_bytes()); // The string is already UTF-8 encoded.
159        buffer.put_u8(0x00);
160
161        // Total size.
162        Self::size(&string).ok_or(SerializeError::SizeOverflow)
163    }
164
165    fn size<Value>(value: &Value) -> Option<usize>
166    where
167        Value: AsRef<str> + ?Sized,
168    {
169        // The string is already UTF-8 encoded.
170        value.as_ref().len().checked_add(ENCODING_SIZE)
171    }
172
173    fn deserialize<Buffer>(buffer: &mut Buffer) -> Result<String, DeserializeError>
174    where
175        Buffer: Buf + ?Sized,
176    {
177        // Extract the Byte Order Mark.
178        if <[u8; 3]>::deserialize(buffer)? != [0xef_u8, 0xbb, 0xbf] {
179            return Err(DeserializeError::invariant("invalid UTF-8 Byte Order Mark"));
180        }
181        // Extract the remainder of the buffer to a vector.
182        let mut raw = Vec::new();
183        raw.put(buffer);
184        // Check if the string is correctly null terminated.
185        let trimmed = remove_delimiters(raw, 0)?;
186        // Convert the vector into an UTF-8 string.
187        String::from_utf8(trimmed)
188            .map_err(|_err| DeserializeError::invariant("invalid UTF-8 string"))
189    }
190}
191
192impl Sealed for Utf8 {}
193
194/// UTF-16 Little Endian encoding for strings.
195///
196/// Normally, used with [`StaticString`] and [`DynamicString`].
197///
198/// # Examples
199///
200/// ```rust
201/// # fn main() -> Result<(), Box<dyn std::error::Error>> {
202/// use rsomeip_bytes::{StaticString, Utf16LE, Serialize as _, Deserialize as _};
203///
204/// // A `StaticString` can be used to always write the same amount of data regardless
205/// // of the size of the string.
206/// let value = String::from("rsomeip");
207/// let string = StaticString::<18, Utf16LE, _>::from(&value);
208///
209/// // Buffer can be any type that implements `BufMut`.
210/// let mut buffer = [0_u8; 18];
211///
212/// // Serialized data includes Byte Order Mark and Delimiter.
213/// assert_eq!(Ok(18), string.serialize(&mut buffer.as_mut_slice()));
214/// assert_eq!(buffer, [
215///         0xff, 0xfe, // UTF-16LE BOM
216///         0x72, 0, 0x73, 0, 0x6f, 0, 0x6d, 0, 0x65, 0, 0x69, 0, 0x70, 0, // "rsomeip"
217///         0x00, 0x00 // Delimiter
218///     ]);
219///
220/// // Deserialization automatically strips the BOM and Delimiter.
221/// let output = StaticString::<18, Utf16LE, String>::deserialize(&mut buffer.as_slice())?;
222/// assert_eq!(output, value);
223/// # Ok(()) }
224/// ```
225#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
226pub struct Utf16LE;
227
228impl Encoding for Utf16LE {
229    fn serialize<Value, Buffer>(value: Value, buffer: &mut Buffer) -> Result<usize, SerializeError>
230    where
231        Value: AsRef<str>,
232        Buffer: BufMut + ?Sized,
233    {
234        let string = value.as_ref();
235        let mut size = ENCODING_SIZE; // BOM + Delimiter
236
237        // UTF-16 Byte Order Mark + String + Delimiter
238        buffer.put_u16_le(0xfeff);
239        for charater in string.encode_utf16() {
240            buffer.put_u16_le(charater);
241            // Update the total size of the string.
242            size = size
243                .checked_add(size_of::<u16>())
244                .ok_or(SerializeError::SizeOverflow)?;
245        }
246        buffer.put_u16_le(0x0000);
247
248        // Return the total size.
249        Ok(size)
250    }
251
252    fn size<Value>(value: &Value) -> Option<usize>
253    where
254        Value: AsRef<str> + ?Sized,
255    {
256        value
257            .as_ref()
258            .encode_utf16()
259            .count()
260            .checked_mul(size_of::<u16>())
261            .and_then(|size| size.checked_add(ENCODING_SIZE))
262    }
263
264    fn deserialize<Buffer>(buffer: &mut Buffer) -> Result<String, DeserializeError>
265    where
266        Buffer: Buf + ?Sized,
267    {
268        // Extract the Byte Order Mark.
269        if 0xfffe != u16::deserialize(buffer)? {
270            return Err(DeserializeError::invariant(
271                "invalid UTF-16LE Byte Order Mark",
272            ));
273        }
274        // Extract the remainder of the buffer to a vector.
275        let raw = deserialize_raw_utf16(buffer, |buffer| {
276            buffer
277                .try_get_u16_le()
278                .map_err(|_err| DeserializeError::InsufficientData)
279        })?;
280        // Check if the string is correctly null terminated.
281        let trimmed = remove_delimiters(raw, 0)?;
282        // Convert the vector into an UTF-16 string.
283        String::from_utf16(&trimmed)
284            .map_err(|_err| DeserializeError::invariant("invalid UTF-16LE string"))
285    }
286}
287
288impl Sealed for Utf16LE {}
289
290/// UTF-16 Big Endian encoding for strings.
291///
292/// Normally, used with [`StaticString`] and [`DynamicString`].
293///
294/// # Examples
295///
296/// ```rust
297/// # fn main() -> Result<(), Box<dyn std::error::Error>> {
298/// use rsomeip_bytes::{StaticString, Utf16BE, Serialize as _, Deserialize as _};
299///
300/// // A `StaticString` can be used to always write the same amount of data regardless
301/// // of the size of the string.
302/// let value = String::from("rsomeip");
303/// let string = StaticString::<18, Utf16BE, _>::from(&value);
304///
305/// // Buffer can be any type that implements `BufMut`.
306/// let mut buffer = [0_u8; 18];
307///
308/// // Serialized data includes Byte Order Mark and Delimiter.
309/// assert_eq!(Ok(18), string.serialize(&mut buffer.as_mut_slice()));
310/// assert_eq!(buffer, [
311///         0xfe, 0xff, // UTF-16BE BOM
312///         0, 0x72, 0, 0x73, 0, 0x6f, 0, 0x6d, 0, 0x65, 0, 0x69, 0, 0x70, // "rsomeip"
313///         0x00, 0x00 // Delimiter
314///     ]);
315///
316/// // Deserialization automatically strips the BOM and Delimiter.
317/// let output = StaticString::<18, Utf16BE, String>::deserialize(&mut buffer.as_slice())?;
318/// assert_eq!(output, value);
319/// # Ok(()) }
320/// ```
321#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
322pub struct Utf16BE;
323
324impl Encoding for Utf16BE {
325    fn serialize<Value, Buffer>(value: Value, buffer: &mut Buffer) -> Result<usize, SerializeError>
326    where
327        Value: AsRef<str>,
328        Buffer: BufMut + ?Sized,
329    {
330        let string = value.as_ref();
331        let mut size = 4_usize; // BOM + Delimiter
332
333        // UTF-16 Byte Order Mark + String + Delimiter
334        buffer.put_u16(0xfeff);
335        for charater in string.encode_utf16() {
336            buffer.put_u16(charater);
337            // Update the total size of the string.
338            size = size
339                .checked_add(size_of::<u16>())
340                .ok_or(SerializeError::SizeOverflow)?;
341        }
342        buffer.put_u16(0x0000);
343
344        // Return the total size.
345        Ok(size)
346    }
347
348    fn size<Value>(value: &Value) -> Option<usize>
349    where
350        Value: AsRef<str> + ?Sized,
351    {
352        // Same as Little Endian.
353        Utf16LE::size(value)
354    }
355
356    fn deserialize<Buffer>(buffer: &mut Buffer) -> Result<String, DeserializeError>
357    where
358        Buffer: Buf + ?Sized,
359    {
360        // Extract the Byte Order Mark.
361        if 0xfeff != u16::deserialize(buffer)? {
362            return Err(DeserializeError::invariant(
363                "invalid UTF-16BE Byte Order Mark",
364            ));
365        }
366        // Extract the remainder of the buffer to a vector.
367        let raw = deserialize_raw_utf16(buffer, u16::deserialize)?;
368        // Check if the string is correctly null terminated.
369        let trimmed = remove_delimiters(raw, 0)?;
370        // Convert the vector into an UTF-16 string.
371        String::from_utf16(&trimmed)
372            .map_err(|_err| DeserializeError::invariant("invalid UTF-16BE string"))
373    }
374}
375
376impl Sealed for Utf16BE {}
377
378/// Extracts a raw UTF-16 string from the given `buffer`.
379///
380/// Removes odd padding from the end of the string.
381///
382/// # Errors
383///
384/// Returns a [`DeserializeError`] if the deserialization fails or if the odd byte isn't null.
385fn deserialize_raw_utf16<Buffer, Deserializer>(
386    buffer: &mut Buffer,
387    deserialize: Deserializer,
388) -> Result<Vec<u16>, DeserializeError>
389where
390    Buffer: Buf + ?Sized,
391    Deserializer: Fn(&mut Buffer) -> Result<u16, DeserializeError>,
392{
393    let mut raw = Vec::new();
394    loop {
395        match buffer.remaining() {
396            // Nothing to extract.
397            0 => break,
398            // Only one byte remaining.
399            1 => {
400                // Must be padding.
401                if u8::deserialize(buffer)? != 0 {
402                    return Err(DeserializeError::invariant("not null terminated"));
403                }
404            }
405            // Two or more bytes remaining. Put them in the Vec.
406            _ => raw.push(deserialize(buffer)?),
407        }
408    }
409    Ok(raw)
410}
411
412/// Extracts the raw string from the given `input` and removes any trailing `delimiter`.
413///
414/// # Errors
415///
416/// Returns a [`DeserializeError::InvariantFailed`] if the string doesn't have a delimiter or if
417/// there is a delimiter in the middle of the string.
418fn remove_delimiters<T>(mut input: Vec<T>, delimiter: T) -> Result<Vec<T>, DeserializeError>
419where
420    T: PartialEq + Copy,
421{
422    input
423        .iter()
424        .position(|&elem| elem == delimiter)
425        .ok_or_else(|| DeserializeError::invariant("not null terminated"))
426        .and_then(|position| {
427            // Trim the delimiter.
428            let remainder = input.split_off(position);
429            // Check for non-null data after the delimiter.
430            if !remainder.is_empty() && remainder.iter().any(|&elem| elem != delimiter) {
431                return Err(DeserializeError::invariant(
432                    "null byte before end of string",
433                ));
434            }
435            Ok(input)
436        })
437}
438
439/// Dynamically sized string.
440///
441/// Encodes the size of the string in a preceding length field.
442///
443/// # Examples
444///
445/// ```rust
446/// # fn main() -> Result<(), Box<dyn std::error::Error>> {
447/// use rsomeip_bytes::{DynamicString, LengthU32, Utf8, Serialize as _, Deserialize as _};
448///
449/// // A `DynamicString` encodes the size of the string in a preceeding length field.
450/// let value = String::from("rsomeip");
451/// let string = DynamicString::<LengthU32, Utf8, _>::from(&value);
452///
453/// // Size includes the length field, BOM, string, and delimiter.
454/// assert_eq!(Some(15), string.size());
455/// // Size hint only includes the length field.
456/// assert_eq!(Some(4), DynamicString::<LengthU32, Utf8, String>::size_hint());
457///
458/// // Buffer can be any type that implements `BufMut`.
459/// let mut buffer = [0_u8; 15];
460///
461/// // Serialized data includes Length, Byte Order Mark and Delimiter.
462/// assert_eq!(Ok(15), string.serialize(&mut buffer.as_mut_slice()));
463/// assert_eq!(buffer, [
464///         0x00_u8, 0x00, 0x00, 0x0b, // Length
465///         0xef, 0xbb, 0xbf, // UTF-8 BOM
466///         0x72, 0x73, 0x6f, 0x6d, 0x65, 0x69, 0x70, // "rsomeip"
467///         0x00, // Delimiter
468///     ]);
469///
470/// // Deserialization automatically strips the length, BOM, and delimiters.
471/// let output = DynamicString::<LengthU32, Utf8, String>::deserialize(&mut buffer.as_slice())?;
472/// assert_eq!(output, value);
473/// # Ok(()) }
474/// ```
475pub struct DynamicString<Length, Encoding, Value> {
476    /// String to serialize.
477    inner: Value,
478    /// Length to include before the string.
479    _length: PhantomData<Length>,
480    /// Encoding to use when serializing/deserializing the string.
481    _encoding: PhantomData<Encoding>,
482}
483
484impl<Length, Encoding, Value> From<Value> for DynamicString<Length, Encoding, Value>
485where
486    Length: crate::Length,
487    Encoding: crate::Encoding,
488    Value: AsRef<str>,
489{
490    fn from(value: Value) -> Self {
491        Self {
492            inner: value,
493            _length: PhantomData,
494            _encoding: PhantomData,
495        }
496    }
497}
498
499impl<Length, Encoding, Value> Serialize for DynamicString<Length, Encoding, Value>
500where
501    Length: crate::Length,
502    Encoding: crate::Encoding,
503    Value: AsRef<str>,
504{
505    fn serialize<Buffer>(&self, buffer: &mut Buffer) -> Result<usize, crate::SerializeError>
506    where
507        Buffer: bytes::BufMut + ?Sized,
508    {
509        let wrapper = crate::SerializeWithFn::new(
510            &self.inner,
511            |value: &Value, buf: &mut dyn bytes::BufMut| Encoding::serialize(value, buf),
512            |value: &Value| Encoding::size(value),
513        );
514        Length::serialize(&wrapper, buffer)
515    }
516
517    fn size(&self) -> Option<usize> {
518        Encoding::size(&self.inner).and_then(|size| size.checked_add(Length::size()))
519    }
520}
521
522impl<Length, Encoding, Value> Deserialize for DynamicString<Length, Encoding, Value>
523where
524    Length: crate::Length,
525    Encoding: crate::Encoding,
526    Value: From<String>,
527{
528    type Output = Value;
529
530    fn deserialize<Buffer>(buffer: &mut Buffer) -> Result<Self::Output, crate::DeserializeError>
531    where
532        Buffer: bytes::Buf + ?Sized,
533    {
534        Length::deserialize_with(
535            |buffer| Encoding::deserialize(buffer).map(|value| Value::from(value)),
536            buffer,
537        )
538    }
539
540    fn size_hint() -> Option<usize> {
541        Some(Length::size())
542    }
543}
544
545/// Statically sizes string.
546///
547/// Serialized static strings always have the same length regardless of the size of the actual
548/// string.
549///
550/// Extra space is padded with delimiters.
551///
552/// # Examples
553///
554/// ```rust
555/// # fn main() -> Result<(), Box<dyn std::error::Error>> {
556/// use rsomeip_bytes::{StaticString, Utf8, Serialize as _, Deserialize as _};
557///
558/// // A `StaticString` can be used to always write the same amount of data regardless
559/// // of the size of the string.
560/// let value = String::from("rsomeip");
561/// let string = StaticString::<15, Utf8, _>::from(&value);
562///
563/// // Size is the capacity of the underlying array.
564/// assert_eq!(Some(15), string.size());
565/// assert_eq!(Some(15), StaticString::<15, Utf8, String>::size_hint());
566///
567/// // Buffer can be any type that implements `BufMut`.
568/// let mut buffer = [0_u8; 15];
569///
570/// // Serialized data includes Byte Order Mark, delimiter, and padding.
571/// assert_eq!(Ok(15), string.serialize(&mut buffer.as_mut_slice()));
572/// assert_eq!(buffer, [
573///         0xef_u8, 0xbb, 0xbf, // UTF-8 BOM
574///         0x72, 0x73, 0x6f, 0x6d, 0x65, 0x69, 0x70, // "rsomeip"
575///         0x00, // Delimiter
576///         0x00, 0x00, 0x00, 0x00, // Padding
577///     ]);
578///
579/// // Deserialization automatically strips the BOM, delimiter, and padding.
580/// let output = StaticString::<15, Utf8, String>::deserialize(&mut buffer.as_slice())?;
581/// assert_eq!(output, value);
582/// # Ok(()) }
583/// ```
584pub struct StaticString<const N: usize, Encoding, Value> {
585    /// String to serialize.
586    value: Value,
587    /// Size of the array.
588    _length: PhantomData<[(); N]>,
589    /// Encoding to use when serializing/deserializing the string.
590    _encoding: PhantomData<Encoding>,
591}
592
593impl<Encoding, Value, const N: usize> From<Value> for StaticString<N, Encoding, Value>
594where
595    Encoding: crate::Encoding,
596    Value: AsRef<str>,
597{
598    fn from(value: Value) -> Self {
599        Self {
600            value,
601            _length: PhantomData,
602            _encoding: PhantomData,
603        }
604    }
605}
606
607impl<Encoding, Value, const N: usize> Serialize for StaticString<N, Encoding, Value>
608where
609    Encoding: crate::Encoding,
610    Value: AsRef<str>,
611{
612    fn serialize<Buffer>(&self, buffer: &mut Buffer) -> Result<usize, SerializeError>
613    where
614        Buffer: BufMut + ?Sized,
615    {
616        // Check if the string fits in the array.
617        if Encoding::size(&self.value).ok_or(SerializeError::SizeOverflow)? > N {
618            return Err(SerializeError::invariant(
619                "string exceeds static array capacity",
620            ));
621        }
622        // Limit the amount that can be written into the buffer.
623        let mut limit = buffer.limit(N);
624        // Write the string into the buffer.
625        _ = Encoding::serialize(&self.value, &mut limit)?;
626        // Fill the remaining space with '0'.
627        limit.put_bytes(0, limit.remaining_mut());
628        // Return the size of the array.
629        Ok(N)
630    }
631
632    fn size(&self) -> Option<usize> {
633        Some(N)
634    }
635}
636
637impl<Encoding, Value, const N: usize> Deserialize for StaticString<N, Encoding, Value>
638where
639    Encoding: crate::Encoding,
640    Value: From<String>,
641{
642    type Output = Value;
643
644    fn deserialize<Buffer>(buffer: &mut Buffer) -> Result<Self::Output, DeserializeError>
645    where
646        Buffer: Buf + ?Sized,
647    {
648        Encoding::deserialize(buffer).map(Value::from)
649    }
650
651    fn size_hint() -> Option<usize> {
652        Some(N)
653    }
654}
655
656#[cfg(test)]
657#[expect(clippy::inline_modules, reason = "rust-clippy#17342")]
658mod tests {
659    use super::*;
660    use bytes::BytesMut;
661
662    #[test]
663    fn utf8_delimiter_checks() {
664        let buffer = [
665            0xef_u8, 0xbb, 0xbf, // UTF-8 BOM
666            0x72, 0x73, 0x6f, 0x6d, 0x65, 0x69, 0x70, // "rsomeip"
667            0x00, // Delimiter
668            0x62, 0x79, 0x74, 0x65, 0x73, // "bytes"
669            0x00, // Delimiter
670        ];
671        assert_eq!(
672            <Utf8>::deserialize(&mut buffer.get(0..10).expect("should slice the buffer")),
673            Err(DeserializeError::invariant("not null terminated"))
674        );
675        assert_eq!(
676            <Utf8>::deserialize(&mut buffer.as_slice()),
677            Err(DeserializeError::invariant(
678                "null byte before end of string"
679            ))
680        );
681    }
682
683    #[test]
684    fn utf16be_delimiter_checks() {
685        let buffer = [
686            0xfe_u8, 0xff, // UTF-16 BE BOM
687            0, 0x72, 0, 0x73, 0, 0x6f, 0, 0x6d, 0, 0x65, 0, 0x69, 0, 0x70, // "rsomeip"
688            0x00, 0x00, // Delimiter
689            0, 0x62, 0, 0x79, 0, 0x74, 0, 0x65, 0, 0x73, // "bytes"
690            0x00, 0x00, // Delimiter
691        ];
692        assert_eq!(
693            <Utf16BE>::deserialize(&mut buffer.get(0..16).expect("should slice the buffer")),
694            Err(DeserializeError::invariant("not null terminated"))
695        );
696        assert_eq!(
697            <Utf16BE>::deserialize(&mut buffer.as_slice()),
698            Err(DeserializeError::invariant(
699                "null byte before end of string"
700            ))
701        );
702    }
703
704    #[test]
705    fn utf16le_delimiter_checks() {
706        let buffer = [
707            0xff_u8, 0xfe, // UTF-16LE BOM
708            0x72, 0, 0x73, 0, 0x6f, 0, 0x6d, 0, 0x65, 0, 0x69, 0, 0x70, 0, // "rsomeip"
709            0x00, 0x00, // Delimiter
710            0x62, 0, 0x79, 0, 0x74, 0, 0x65, 0, 0x73, 0, // "bytes"
711            0x00, 0x00, // Delimiter
712        ];
713        assert_eq!(
714            <Utf16LE>::deserialize(&mut buffer.get(0..16).expect("should slice the buffer")),
715            Err(DeserializeError::invariant("not null terminated"))
716        );
717        assert_eq!(
718            <Utf16LE>::deserialize(&mut buffer.as_slice()),
719            Err(DeserializeError::invariant(
720                "null byte before end of string"
721            ))
722        );
723    }
724
725    #[test]
726    fn utf16be_odd_padding() {
727        let buffer = [
728            0xfe_u8, 0xff, // UTF-16 BE BOM
729            0, 0x72, 0, 0x73, 0, 0x6f, 0, 0x6d, 0, 0x65, 0, 0x69, 0, 0x70, // "rsomeip"
730            0x00, 0x00, // Delimiter
731            0x00, // Padding
732        ];
733        assert_eq!(
734            Utf16BE::deserialize(&mut buffer.as_slice()),
735            Ok(String::from("rsomeip"))
736        );
737    }
738
739    #[test]
740    fn utf16le_odd_padding() {
741        let buffer = [
742            0xff_u8, 0xfe, // UTF-16LE BOM
743            0x72, 0, 0x73, 0, 0x6f, 0, 0x6d, 0, 0x65, 0, 0x69, 0, 0x70, 0, // "rsomeip"
744            0x00, 0x00, // Delimiter
745            0x00, // Padding
746        ];
747        assert_eq!(
748            Utf16LE::deserialize(&mut buffer.as_slice()),
749            Ok(String::from("rsomeip"))
750        );
751    }
752
753    #[test]
754    fn utf16be_invalid_padding() {
755        let buffer = [
756            0xfe_u8, 0xff, // UTF-16 BE BOM
757            0, 0x72, 0, 0x73, 0, 0x6f, 0, 0x6d, 0, 0x65, 0, 0x69, 0, 0x70, // "rsomeip"
758            0x00, 0x00, // Delimiter
759            0x01, // Padding
760        ];
761        assert_eq!(
762            Utf16BE::deserialize(&mut buffer.as_slice()),
763            Err(DeserializeError::invariant("not null terminated"))
764        );
765    }
766
767    #[test]
768    fn utf16le_invalid_padding() {
769        let buffer = [
770            0xff_u8, 0xfe, // UTF-16LE BOM
771            0x72, 0, 0x73, 0, 0x6f, 0, 0x6d, 0, 0x65, 0, 0x69, 0, 0x70, 0, // "rsomeip"
772            0x00, 0x00, // Delimiter
773            0x01, // Padding
774        ];
775        assert_eq!(
776            Utf16LE::deserialize(&mut buffer.as_slice()),
777            Err(DeserializeError::invariant("not null terminated"))
778        );
779    }
780
781    #[test]
782    fn utf8_bom_check() {
783        let buffer = [
784            0xef_u8, 0x00, 0xbf, // Invalid BOM
785            0x00, // Delimiter
786        ];
787        assert_eq!(
788            Utf8::deserialize(&mut buffer.as_slice()),
789            Err(DeserializeError::invariant("invalid UTF-8 Byte Order Mark"))
790        );
791    }
792
793    #[test]
794    fn utf16be_bom_check() {
795        let buffer = [
796            0xff_u8, 0x00, // Invalid BOM
797            0x00, 0x00, // Delimiter
798        ];
799        assert_eq!(
800            Utf16BE::deserialize(&mut buffer.as_slice()),
801            Err(DeserializeError::invariant(
802                "invalid UTF-16BE Byte Order Mark"
803            ))
804        );
805    }
806
807    #[test]
808    fn utf16le_bom_check() {
809        let buffer = [
810            0xfe_u8, 0x00, // Invalid BOM
811            0x00, 0x00, // Delimiter
812        ];
813        assert_eq!(
814            Utf16LE::deserialize(&mut buffer.as_slice()),
815            Err(DeserializeError::invariant(
816                "invalid UTF-16LE Byte Order Mark"
817            ))
818        );
819    }
820
821    #[test]
822    fn utf8_empty_string() {
823        let buffer = [
824            0xef_u8, 0xbb, 0xbf, // UTF-8 BOM
825            0x00, // Delimiter
826        ];
827        assert_eq!(Utf8::deserialize(&mut buffer.as_slice()), Ok(String::new()));
828    }
829
830    #[test]
831    fn utf16be_empty_string() {
832        let buffer = [
833            0xfe_u8, 0xff, // UTF-16 BE BOM
834            0x00, 0x00, // Delimiter
835        ];
836        assert_eq!(
837            Utf16BE::deserialize(&mut buffer.as_slice()),
838            Ok(String::new())
839        );
840    }
841
842    #[test]
843    fn utf16le_empty_string() {
844        let buffer = [
845            0xff_u8, 0xfe, // UTF-16LE BOM
846            0x00, 0x00, // Delimiter
847        ];
848        assert_eq!(
849            Utf16LE::deserialize(&mut buffer.as_slice()),
850            Ok(String::new())
851        );
852    }
853
854    #[test]
855    fn static_string_exceeds_capacity() {
856        assert_eq!(
857            StaticString::<4, Utf8, _>::from("rsomeip").serialize(&mut BytesMut::with_capacity(11)),
858            Err(SerializeError::invariant(
859                "string exceeds static array capacity"
860            ))
861        );
862    }
863}