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 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
51pub 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
80pub 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 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#[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
154pub 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}