messagepack_core/decode/
str.rs1use super::{DecodeBorrowed, Error, NbyteReader};
4use crate::{Decode, formats::Format, io::IoRead};
5
6pub struct StrDecoder;
8
9impl<'de> DecodeBorrowed<'de> for StrDecoder {
10 type Value = &'de str;
11
12 fn decode_borrowed_with_format<R>(
13 format: Format,
14 reader: &mut R,
15 ) -> core::result::Result<Self::Value, Error<R::Error>>
16 where
17 R: IoRead<'de>,
18 {
19 let str_ref = ReferenceStrDecoder::decode_with_format(format, reader)?;
20 match str_ref {
21 ReferenceStr::Borrowed(s) => Ok(s),
22 ReferenceStr::Copied(_) => Err(Error::InvalidData),
23 }
24 }
25}
26
27impl<'de> DecodeBorrowed<'de> for &'de str {
28 type Value = &'de str;
29
30 fn decode_borrowed_with_format<R>(
31 format: Format,
32 reader: &mut R,
33 ) -> core::result::Result<Self::Value, Error<R::Error>>
34 where
35 R: IoRead<'de>,
36 {
37 StrDecoder::decode_borrowed_with_format(format, reader)
38 }
39}
40
41pub enum ReferenceStr<'de, 'a> {
43 Borrowed(&'de str),
45 Copied(&'a str),
47}
48
49pub struct ReferenceStrDecoder;
51
52impl<'de> Decode<'de> for ReferenceStrDecoder {
53 type Value<'a>
54 = ReferenceStr<'de, 'a>
55 where
56 Self: 'a,
57 'de: 'a;
58 fn decode_with_format<'a, R>(
59 format: Format,
60 reader: &'a mut R,
61 ) -> Result<Self::Value<'a>, Error<R::Error>>
62 where
63 R: IoRead<'de>,
64 'de: 'a,
65 {
66 let len = match format {
67 Format::FixStr(n) => n.into(),
68 Format::Str8 => NbyteReader::<1>::read(reader)?,
69 Format::Str16 => NbyteReader::<2>::read(reader)?,
70 Format::Str32 => NbyteReader::<4>::read(reader)?,
71 _ => return Err(Error::UnexpectedFormat),
72 };
73 let data = reader.read_slice(len).map_err(Error::Io)?;
74 match data {
75 crate::io::Reference::Borrowed(items) => {
76 let s = str::from_utf8(items).map_err(|_| Error::InvalidData)?;
77 Ok(ReferenceStr::Borrowed(s))
78 }
79 crate::io::Reference::Copied(items) => {
80 let s = str::from_utf8(items).map_err(|_| Error::InvalidData)?;
81 Ok(ReferenceStr::Copied(s))
82 }
83 }
84 }
85}
86
87#[cfg(feature = "alloc")]
88impl<'de> DecodeBorrowed<'de> for alloc::string::String {
89 type Value = alloc::string::String;
90
91 fn decode_borrowed_with_format<R>(
92 format: Format,
93 reader: &mut R,
94 ) -> core::result::Result<Self::Value, Error<R::Error>>
95 where
96 R: IoRead<'de>,
97 {
98 let sref = ReferenceStrDecoder::decode_with_format(format, reader)?;
99 let owned = match sref {
100 ReferenceStr::Borrowed(s) => alloc::string::String::from(s),
101 ReferenceStr::Copied(s) => alloc::string::String::from(s),
102 };
103 Ok(owned)
104 }
105}
106
107#[cfg(test)]
108mod tests {
109 use super::*;
110 use crate::decode::Decode;
111
112 #[test]
113 fn decode_str() {
114 let buf: &[u8] = &[
115 0xab, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x57, 0x6f, 0x72, 0x6c, 0x64,
116 ];
117
118 let mut r = crate::io::SliceReader::new(buf);
119 let decoded = StrDecoder::decode(&mut r).unwrap();
120 let expect = "Hello World";
121 assert_eq!(decoded, expect);
122 assert_eq!(r.rest().len(), 0);
123 }
124
125 #[test]
126 fn decode_invalid_str() {
127 let buf: &[u8] = &[0xa2, 0xc3, 0x28];
128 let mut r = crate::io::SliceReader::new(buf);
129 let err = StrDecoder::decode(&mut r).unwrap_err();
130 assert_eq!(err, Error::InvalidData);
131
132 let buf: &[u8] = &[0xa1, 0x80];
133 let mut r = crate::io::SliceReader::new(buf);
134 let err = StrDecoder::decode(&mut r).unwrap_err();
135 assert_eq!(err, Error::InvalidData);
136 }
137
138 #[cfg(feature = "alloc")]
139 #[test]
140 fn decode_string_owned() {
141 let buf: &[u8] = &[0xa3, b'f', b'o', b'o'];
142 let mut r = crate::io::SliceReader::new(buf);
143 let s = <alloc::string::String as Decode>::decode(&mut r).unwrap();
144 assert_eq!(s.as_str(), "foo");
145 assert!(r.rest().is_empty());
146 }
147}