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")]
88mod alloc_impl {
89 use super::*;
90 impl<'de> DecodeBorrowed<'de> for alloc::string::String {
91 type Value = alloc::string::String;
92
93 fn decode_borrowed_with_format<R>(
94 format: Format,
95 reader: &mut R,
96 ) -> core::result::Result<Self::Value, Error<R::Error>>
97 where
98 R: IoRead<'de>,
99 {
100 let sref = ReferenceStrDecoder::decode_with_format(format, reader)?;
101 let owned = match sref {
102 ReferenceStr::Borrowed(s) => alloc::string::String::from(s),
103 ReferenceStr::Copied(s) => alloc::string::String::from(s),
104 };
105 Ok(owned)
106 }
107 }
108}
109
110#[cfg(test)]
111mod tests {
112 use super::*;
113 use crate::decode::Decode;
114
115 #[test]
116 fn decode_str() {
117 let buf: &[u8] = &[
118 0xab, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x57, 0x6f, 0x72, 0x6c, 0x64,
119 ];
120
121 let mut r = crate::io::SliceReader::new(buf);
122 let decoded = StrDecoder::decode(&mut r).unwrap();
123 let expect = "Hello World";
124 assert_eq!(decoded, expect);
125 assert_eq!(r.rest().len(), 0);
126 }
127
128 #[test]
129 fn decode_invalid_str() {
130 let buf: &[u8] = &[0xa2, 0xc3, 0x28];
131 let mut r = crate::io::SliceReader::new(buf);
132 let err = StrDecoder::decode(&mut r).unwrap_err();
133 assert_eq!(err, Error::InvalidData);
134
135 let buf: &[u8] = &[0xa1, 0x80];
136 let mut r = crate::io::SliceReader::new(buf);
137 let err = StrDecoder::decode(&mut r).unwrap_err();
138 assert_eq!(err, Error::InvalidData);
139 }
140
141 #[cfg(feature = "alloc")]
142 #[test]
143 fn decode_string_owned() {
144 let buf: &[u8] = &[0xa3, b'f', b'o', b'o'];
145 let mut r = crate::io::SliceReader::new(buf);
146 let s = <alloc::string::String as Decode>::decode(&mut r).unwrap();
147 assert_eq!(s.as_str(), "foo");
148 assert!(r.rest().is_empty());
149 }
150}