/rust/registry/src/index.crates.io-1949cf8c6b5b557f/rmp-0.8.14/src/decode/str.rs
Line | Count | Source |
1 | | #[cfg(feature = "std")] |
2 | | use std::error; |
3 | | use core::fmt::{self, Display, Formatter}; |
4 | | use core::str::{from_utf8, Utf8Error}; |
5 | | |
6 | | use super::{read_marker, RmpRead, RmpReadErr, ValueReadError}; |
7 | | use crate::Marker; |
8 | | |
9 | | #[derive(Debug)] |
10 | | #[allow(deprecated)] // Only for compatibility |
11 | | pub enum DecodeStringError<'a, E: RmpReadErr = super::Error> { |
12 | | InvalidMarkerRead(E), |
13 | | InvalidDataRead(E), |
14 | | TypeMismatch(Marker), |
15 | | /// The given buffer is not large enough to accumulate the specified amount of bytes. |
16 | | BufferSizeTooSmall(u32), |
17 | | InvalidUtf8(&'a [u8], Utf8Error), |
18 | | } |
19 | | |
20 | | #[cfg(feature = "std")] |
21 | | impl<'a, E: RmpReadErr> error::Error for DecodeStringError<'a, E> { |
22 | | #[cold] |
23 | 0 | fn source(&self) -> Option<&(dyn error::Error + 'static)> { |
24 | 0 | match *self { |
25 | 0 | DecodeStringError::InvalidMarkerRead(ref err) | |
26 | 0 | DecodeStringError::InvalidDataRead(ref err) => Some(err), |
27 | | DecodeStringError::TypeMismatch(..) | |
28 | 0 | DecodeStringError::BufferSizeTooSmall(..) => None, |
29 | 0 | DecodeStringError::InvalidUtf8(_, ref err) => Some(err), |
30 | | } |
31 | 0 | } |
32 | | } |
33 | | |
34 | | impl<'a, E: RmpReadErr> Display for DecodeStringError<'a, E> { |
35 | | #[cold] |
36 | 0 | fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> { |
37 | 0 | f.write_str("error while decoding string") |
38 | 0 | } |
39 | | } |
40 | | |
41 | | impl<'a, E: RmpReadErr> From<ValueReadError<E>> for DecodeStringError<'a, E> { |
42 | | #[cold] |
43 | 0 | fn from(err: ValueReadError<E>) -> DecodeStringError<'a, E> { |
44 | 0 | match err { |
45 | 0 | ValueReadError::InvalidMarkerRead(err) => DecodeStringError::InvalidMarkerRead(err), |
46 | 0 | ValueReadError::InvalidDataRead(err) => DecodeStringError::InvalidDataRead(err), |
47 | 0 | ValueReadError::TypeMismatch(marker) => DecodeStringError::TypeMismatch(marker), |
48 | | } |
49 | 0 | } |
50 | | } |
51 | | |
52 | | /// Attempts to read up to 9 bytes from the given reader and to decode them as a string `u32` size |
53 | | /// value. |
54 | | /// |
55 | | /// According to the MessagePack specification, the string format family stores an byte array in 1, |
56 | | /// 2, 3, or 5 bytes of extra bytes in addition to the size of the byte array. |
57 | | /// |
58 | | /// # Errors |
59 | | /// |
60 | | /// This function will return `ValueReadError` on any I/O error while reading either the marker or |
61 | | /// the data. |
62 | | /// |
63 | | /// It also returns `ValueReadError::TypeMismatch` if the actual type is not equal with the |
64 | | /// expected one, indicating you with the actual type. |
65 | | #[inline] |
66 | 0 | pub fn read_str_len<R: RmpRead>(rd: &mut R) -> Result<u32, ValueReadError<R::Error>> { |
67 | 0 | Ok(read_str_len_with_nread(rd)?.0) |
68 | 0 | } |
69 | | |
70 | 0 | fn read_str_len_with_nread<R>(rd: &mut R) -> Result<(u32, usize), ValueReadError<R::Error>> |
71 | 0 | where R: RmpRead |
72 | | { |
73 | 0 | match read_marker(rd)? { |
74 | 0 | Marker::FixStr(size) => Ok((u32::from(size), 1)), |
75 | 0 | Marker::Str8 => Ok((u32::from(rd.read_data_u8()?), 2)), |
76 | 0 | Marker::Str16 => Ok((u32::from(rd.read_data_u16()?), 3)), |
77 | 0 | Marker::Str32 => Ok((rd.read_data_u32()?, 5)), |
78 | 0 | marker => Err(ValueReadError::TypeMismatch(marker)), |
79 | | } |
80 | 0 | } |
81 | | |
82 | | /// Attempts to read a string data from the given reader and copy it to the buffer provided. |
83 | | /// |
84 | | /// On success returns a borrowed string type, allowing to view the copied bytes as properly utf-8 |
85 | | /// string. |
86 | | /// According to the spec, the string's data must to be encoded using utf-8. |
87 | | /// |
88 | | /// # Errors |
89 | | /// |
90 | | /// Returns `Err` in the following cases: |
91 | | /// |
92 | | /// - if any IO error (including unexpected EOF) occurs, while reading an `rd`, except the EINTR, |
93 | | /// which is handled internally. |
94 | | /// - if the `out` buffer size is not large enough to keep all the data copied. |
95 | | /// - if the data is not utf-8, with a description as to why the provided data is not utf-8 and |
96 | | /// with a size of bytes actually copied to be able to get them from `out`. |
97 | | /// |
98 | | /// # Examples |
99 | | /// ``` |
100 | | /// use rmp::decode::read_str; |
101 | | /// |
102 | | /// let buf = [0xaa, 0x6c, 0x65, 0x20, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65]; |
103 | | /// let mut out = [0u8; 16]; |
104 | | /// |
105 | | /// assert_eq!("le message", read_str(&mut &buf[..], &mut &mut out[..]).unwrap()); |
106 | | /// ``` |
107 | | /// |
108 | | /// # Unstable |
109 | | /// |
110 | | /// This function is **unstable**, because it needs review. |
111 | | // TODO: Stabilize. Mark error values for each error case (in docs). |
112 | 0 | pub fn read_str<'r, R>(rd: &mut R, buf: &'r mut [u8]) -> Result<&'r str, DecodeStringError<'r, R::Error>> |
113 | 0 | where |
114 | 0 | R: RmpRead, |
115 | | { |
116 | 0 | let len = read_str_len(rd)?; |
117 | 0 | let ulen = len as usize; |
118 | | |
119 | 0 | if buf.len() < ulen { |
120 | 0 | return Err(DecodeStringError::BufferSizeTooSmall(len)); |
121 | 0 | } |
122 | | |
123 | 0 | read_str_data(rd, len, &mut buf[0..ulen]) |
124 | 0 | } |
125 | | |
126 | 0 | pub fn read_str_data<'r, R>(rd: &mut R, |
127 | 0 | len: u32, |
128 | 0 | buf: &'r mut [u8]) |
129 | 0 | -> Result<&'r str, DecodeStringError<'r, R::Error>> |
130 | 0 | where R: RmpRead |
131 | | { |
132 | 0 | debug_assert_eq!(len as usize, buf.len()); |
133 | | |
134 | | // Trying to copy exact `len` bytes. |
135 | 0 | match rd.read_exact_buf(buf) { |
136 | 0 | Ok(()) => match from_utf8(buf) { |
137 | 0 | Ok(decoded) => Ok(decoded), |
138 | 0 | Err(err) => Err(DecodeStringError::InvalidUtf8(buf, err)), |
139 | | }, |
140 | 0 | Err(err) => Err(DecodeStringError::InvalidDataRead(err)), |
141 | | } |
142 | 0 | } |
143 | | |
144 | | /// Attempts to read and decode a string value from the reader, returning a borrowed slice from it. |
145 | | /// |
146 | | // TODO: Also it's possible to implement all borrowing functions for all `BufRead` implementors. |
147 | | #[deprecated(since = "0.8.6", note = "useless, use `read_str_from_slice` instead")] |
148 | 0 | pub fn read_str_ref(rd: &[u8]) -> Result<&[u8], DecodeStringError<'_, super::bytes::BytesReadError>> { |
149 | 0 | let mut cur = super::Bytes::new(rd); |
150 | 0 | let len = read_str_len(&mut cur)?; |
151 | 0 | Ok(&cur.remaining_slice()[..len as usize]) |
152 | 0 | } |
153 | | |
154 | | /// Attempts to read and decode a string value from the reader, returning a borrowed slice from it. |
155 | | /// |
156 | | /// # Examples |
157 | | /// |
158 | | /// ``` |
159 | | /// use rmp::encode::write_str; |
160 | | /// use rmp::decode::read_str_from_slice; |
161 | | /// |
162 | | /// let mut buf = Vec::new(); |
163 | | /// write_str(&mut buf, "Unpacking").unwrap(); |
164 | | /// write_str(&mut buf, "multiple").unwrap(); |
165 | | /// write_str(&mut buf, "strings").unwrap(); |
166 | | /// |
167 | | /// let mut chunks = Vec::new(); |
168 | | /// let mut unparsed = &buf[..]; |
169 | | /// while let Ok((chunk, tail)) = read_str_from_slice(unparsed) { |
170 | | /// chunks.push(chunk); |
171 | | /// unparsed = tail; |
172 | | /// } |
173 | | /// |
174 | | /// assert_eq!(vec!["Unpacking", "multiple", "strings"], chunks); |
175 | | /// ``` |
176 | 0 | pub fn read_str_from_slice<T: ?Sized + AsRef<[u8]>>( |
177 | 0 | buf: &T, |
178 | 0 | ) -> Result<(&str, &[u8]), DecodeStringError<'_, super::bytes::BytesReadError>> { |
179 | 0 | let buf = buf.as_ref(); |
180 | 0 | let (len, nread) = read_str_len_with_nread(&mut super::Bytes::new(buf))?; |
181 | 0 | let ulen = len as usize; |
182 | | |
183 | 0 | if buf[nread..].len() >= ulen { |
184 | 0 | let (head, tail) = buf.split_at(nread + ulen); |
185 | 0 | match from_utf8(&head[nread..]) { |
186 | 0 | Ok(val) => Ok((val, tail)), |
187 | 0 | Err(err) => Err(DecodeStringError::InvalidUtf8(buf, err)), |
188 | | } |
189 | | } else { |
190 | 0 | Err(DecodeStringError::BufferSizeTooSmall(len)) |
191 | | } |
192 | 0 | } |