bin_proto/impls/
string.rs

1#![cfg(feature = "alloc")]
2
3use crate::{util, BitDecode, BitEncode, Error, Result, Untagged};
4
5use alloc::{string::String, vec::Vec};
6use bitstream_io::{BitRead, BitWrite, Endianness};
7
8impl<Tag, Ctx> BitDecode<Ctx, crate::Tag<Tag>> for String
9where
10    Tag: TryInto<usize>,
11{
12    fn decode<R, E>(read: &mut R, ctx: &mut Ctx, tag: crate::Tag<Tag>) -> Result<Self>
13    where
14        R: BitRead,
15        E: Endianness,
16    {
17        let item_count = tag.0.try_into().map_err(|_| Error::TagConvert)?;
18        let mut bytes = Vec::with_capacity(item_count);
19        for _ in 0..item_count {
20            bytes.push(u8::decode::<_, E>(read, ctx, ())?);
21        }
22        Ok(Self::from_utf8(bytes)?)
23    }
24}
25
26impl<Ctx> BitEncode<Ctx, Untagged> for String {
27    fn encode<W, E>(&self, write: &mut W, ctx: &mut Ctx, _: Untagged) -> Result<()>
28    where
29        W: BitWrite,
30        E: Endianness,
31    {
32        util::encode_items::<_, E, _, _>(self.as_bytes(), write, ctx)
33    }
34}
35
36impl<Ctx> BitDecode<Ctx, Untagged> for String {
37    fn decode<R, E>(read: &mut R, ctx: &mut Ctx, _: Untagged) -> Result<Self>
38    where
39        R: BitRead,
40        E: Endianness,
41    {
42        let bytes = util::decode_items_to_eof::<_, E, _, _>(read, ctx).collect::<Result<_>>()?;
43        Ok(Self::from_utf8(bytes)?)
44    }
45}
46
47#[cfg(feature = "prepend-tags")]
48impl<Ctx> BitEncode<Ctx> for String {
49    fn encode<W, E>(&self, write: &mut W, ctx: &mut Ctx, (): ()) -> Result<()>
50    where
51        W: BitWrite,
52        E: Endianness,
53    {
54        self.len().encode::<_, E>(write, ctx, ())?;
55        self.encode::<_, E>(write, ctx, Untagged)
56    }
57}
58
59#[cfg(feature = "prepend-tags")]
60impl<Ctx> BitDecode<Ctx> for String {
61    fn decode<R, E>(read: &mut R, ctx: &mut Ctx, (): ()) -> Result<Self>
62    where
63        R: BitRead,
64        E: Endianness,
65    {
66        let tag = usize::decode::<_, E>(read, ctx, ())?;
67        Self::decode::<_, E>(read, ctx, crate::Tag(tag))
68    }
69}
70
71test_untagged_and_codec!(String| Untagged, crate::Tag(3); "abc".into() => [b'a', b'b', b'c']);
72
73#[cfg(feature = "prepend-tags")]
74test_roundtrip!(String);