1#[cfg(feature = "std")]
2use std::error;
3use core::fmt::{self, Display, Formatter};
4use core::str::{from_utf8, Utf8Error};
5
6use super::{read_marker, RmpRead, RmpReadErr, ValueReadError};
7use crate::Marker;
8
9#[derive(Debug)]
10#[allow(deprecated)] pub enum DecodeStringError<'a, E: RmpReadErr = super::Error> {
12 InvalidMarkerRead(E),
13 InvalidDataRead(E),
14 TypeMismatch(Marker),
15 BufferSizeTooSmall(u32),
17 InvalidUtf8(&'a [u8], Utf8Error),
18}
19
20#[cfg(feature = "std")]
21impl<'a, E: RmpReadErr> error::Error for DecodeStringError<'a, E> {
22 #[cold]
23 fn source(&self) -> Option<&(dyn error::Error + 'static)> {
24 match *self {
25 DecodeStringError::InvalidMarkerRead(ref err) |
26 DecodeStringError::InvalidDataRead(ref err) => Some(err),
27 DecodeStringError::TypeMismatch(..) |
28 DecodeStringError::BufferSizeTooSmall(..) => None,
29 DecodeStringError::InvalidUtf8(_, ref err) => Some(err),
30 }
31 }
32}
33
34impl<'a, E: RmpReadErr> Display for DecodeStringError<'a, E> {
35 #[cold]
36 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> {
37 f.write_str("error while decoding string")
38 }
39}
40
41impl<'a, E: RmpReadErr> From<ValueReadError<E>> for DecodeStringError<'a, E> {
42 #[cold]
43 fn from(err: ValueReadError<E>) -> DecodeStringError<'a, E> {
44 match err {
45 ValueReadError::InvalidMarkerRead(err) => DecodeStringError::InvalidMarkerRead(err),
46 ValueReadError::InvalidDataRead(err) => DecodeStringError::InvalidDataRead(err),
47 ValueReadError::TypeMismatch(marker) => DecodeStringError::TypeMismatch(marker),
48 }
49 }
50}
51
52#[inline]
66pub fn read_str_len<R: RmpRead>(rd: &mut R) -> Result<u32, ValueReadError<R::Error>> {
67 Ok(read_str_len_with_nread(rd)?.0)
68}
69
70fn read_str_len_with_nread<R>(rd: &mut R) -> Result<(u32, usize), ValueReadError<R::Error>>
71 where R: RmpRead
72{
73 match read_marker(rd)? {
74 Marker::FixStr(size) => Ok((u32::from(size), 1)),
75 Marker::Str8 => Ok((u32::from(rd.read_data_u8()?), 2)),
76 Marker::Str16 => Ok((u32::from(rd.read_data_u16()?), 3)),
77 Marker::Str32 => Ok((rd.read_data_u32()?, 5)),
78 marker => Err(ValueReadError::TypeMismatch(marker)),
79 }
80}
81
82pub fn read_str<'r, R>(rd: &mut R, buf: &'r mut [u8]) -> Result<&'r str, DecodeStringError<'r, R::Error>>
113where
114 R: RmpRead,
115{
116 let len = read_str_len(rd)?;
117 let ulen = len as usize;
118
119 if buf.len() < ulen {
120 return Err(DecodeStringError::BufferSizeTooSmall(len));
121 }
122
123 read_str_data(rd, len, &mut buf[0..ulen])
124}
125
126pub fn read_str_data<'r, R>(rd: &mut R,
127 len: u32,
128 buf: &'r mut [u8])
129 -> Result<&'r str, DecodeStringError<'r, R::Error>>
130 where R: RmpRead
131{
132 debug_assert_eq!(len as usize, buf.len());
133
134 match rd.read_exact_buf(buf) {
136 Ok(()) => match from_utf8(buf) {
137 Ok(decoded) => Ok(decoded),
138 Err(err) => Err(DecodeStringError::InvalidUtf8(buf, err)),
139 },
140 Err(err) => Err(DecodeStringError::InvalidDataRead(err)),
141 }
142}
143
144#[deprecated(since = "0.8.6", note = "useless, use `read_str_from_slice` instead")]
148pub fn read_str_ref(rd: &[u8]) -> Result<&[u8], DecodeStringError<'_, super::bytes::BytesReadError>> {
149 let mut cur = super::Bytes::new(rd);
150 let len = read_str_len(&mut cur)?;
151 Ok(&cur.remaining_slice()[..len as usize])
152}
153
154pub fn read_str_from_slice<T: ?Sized + AsRef<[u8]>>(
177 buf: &T,
178) -> Result<(&str, &[u8]), DecodeStringError<'_, super::bytes::BytesReadError>> {
179 let buf = buf.as_ref();
180 let (len, nread) = read_str_len_with_nread(&mut super::Bytes::new(buf))?;
181 let ulen = len as usize;
182
183 if buf[nread..].len() >= ulen {
184 let (head, tail) = buf.split_at(nread + ulen);
185 match from_utf8(&head[nread..]) {
186 Ok(val) => Ok((val, tail)),
187 Err(err) => Err(DecodeStringError::InvalidUtf8(buf, err)),
188 }
189 } else {
190 Err(DecodeStringError::BufferSizeTooSmall(len))
191 }
192}