rmp/decode/
str.rs

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