bytecodec/decode.rs
1use crate::combinator::{
2 AndThen, Collect, CollectN, Length, Map, MapErr, MaxBytes, MaybeEos, Omittable, Peekable,
3 Slice, TryMap,
4};
5use crate::tuple::TupleDecoder;
6use crate::{ByteCount, Eos, Error, ErrorKind, Result};
7
8/// This trait allows for decoding items from a byte sequence incrementally.
9pub trait Decode {
10 /// The type of items to be decoded.
11 type Item;
12
13 /// Consumes the given buffer (a part of a byte sequence), and proceeds the decoding process.
14 ///
15 /// It returns the number of bytes consumed from the input buffer.
16 ///
17 /// If an item is completely decoded, the next invocation of `is_idle` method will return `true`.
18 /// And if `is_idle` method returns `true`, `decode` method should consume no bytes.
19 ///
20 /// The decoder must consume as many bytes in the buffer as possible.
21 /// If an item is not yet decoded but the number of consumed bytes in the last `decode` invocation
22 /// is smaller than the length of `buf`, it means the decoder has been suspended its work in any reasons.
23 /// In that case the decoder may require some instructions from clients to resume the work,
24 /// but its concrete method is beyond the scope of this trait.
25 ///
26 /// # Errors
27 ///
28 /// The following errors may be returned by the decoder:
29 /// - `ErrorKind::DecoderTerminated`:
30 /// - If all decodable items have been decoded,
31 /// the decoder must return this kind of error when `decode` method is called.
32 /// - `ErrorKind::UnexpectedEos`:
33 /// - The invocation of `eos.is_reached()` returns `true` despite of
34 /// the decoder requires more bytes to decode the next item.
35 /// - `ErrorKind::InvalidInput`:
36 /// - Decoded items have invalid values
37 /// - Invalid parameters were given to decoders
38 /// - `ErrorKind::InconsistentState`:
39 /// - The state of the decoder bocame inconsistent
40 /// - This means the implementation contains a bug
41 /// - `ErrorKind::Other`:
42 /// - Other errors
43 fn decode(&mut self, buf: &[u8], eos: Eos) -> Result<usize>;
44
45 /// Finishes the current decoding process and returns the decoded item.
46 ///
47 /// # Errors
48 ///
49 /// The following errors may be returned by the decoder:
50 /// - `ErrorKind::IncompleteDecoding`:
51 /// - The decoding process has not been completed
52 /// - `ErrorKind::DecoderTerminated`:
53 /// - The decoder has terminated (i.e., cannot decode any more items)
54 /// - `ErrorKind::InconsistentState`:
55 /// - The state of the decoder bocame inconsistent
56 /// - This means the implementation contains a bug
57 /// - `ErrorKind::Other`:
58 /// - Other errors
59 fn finish_decoding(&mut self) -> Result<Self::Item>;
60
61 /// Returns the lower bound of the number of bytes needed to decode the next item.
62 ///
63 /// If the decoder does not know the value, it will return `ByteCount::Unknown`
64 /// (e.g., null-terminated strings have no pre-estimable length).
65 ///
66 /// If the decoder returns `ByteCount::Finite(0)`, it means one of the followings:
67 /// - (a) There is an already decoded item
68 /// - The next invocation of `decode()` will return it without consuming any bytes
69 /// - (b) There are no decodable items
70 /// - All decodable items have been decoded, and the decoder cannot do any further works
71 /// - In this case, the next invocation of `decode` method will fail.
72 fn requiring_bytes(&self) -> ByteCount;
73
74 /// Returns `true` if there are no items to be decoded by the decoder
75 /// at the next invocation of `decode` method, otherwise `false`.
76 ///
77 /// Typically, `true` means the decoder already has a decoded item and
78 /// it is waiting for `finish_decoding` to be called.
79 ///
80 /// The default implementation returns the result of `self.requiring_bytes() == ByteCount::Finite(0)`.
81 fn is_idle(&self) -> bool {
82 self.requiring_bytes() == ByteCount::Finite(0)
83 }
84}
85impl<'a, D: ?Sized + Decode> Decode for &'a mut D {
86 type Item = D::Item;
87
88 fn decode(&mut self, buf: &[u8], eos: Eos) -> Result<usize> {
89 (**self).decode(buf, eos)
90 }
91
92 fn finish_decoding(&mut self) -> Result<Self::Item> {
93 (**self).finish_decoding()
94 }
95
96 fn requiring_bytes(&self) -> ByteCount {
97 (**self).requiring_bytes()
98 }
99
100 fn is_idle(&self) -> bool {
101 (**self).is_idle()
102 }
103}
104impl<D: ?Sized + Decode> Decode for Box<D> {
105 type Item = D::Item;
106
107 fn decode(&mut self, buf: &[u8], eos: Eos) -> Result<usize> {
108 (**self).decode(buf, eos)
109 }
110
111 fn finish_decoding(&mut self) -> Result<Self::Item> {
112 (**self).finish_decoding()
113 }
114
115 fn requiring_bytes(&self) -> ByteCount {
116 (**self).requiring_bytes()
117 }
118
119 fn is_idle(&self) -> bool {
120 (**self).is_idle()
121 }
122}
123
124/// An extension of `Decode` trait.
125pub trait DecodeExt: Decode + Sized {
126 /// Creates a decoder that converts decoded values by calling the given function.
127 ///
128 /// # Examples
129 ///
130 /// ```
131 /// use bytecodec::{Decode, DecodeExt};
132 /// use bytecodec::fixnum::U8Decoder;
133 /// use bytecodec::io::IoDecodeExt;
134 ///
135 /// let mut decoder = U8Decoder::new().map(|b| b * 2);
136 /// let item = decoder.decode_exact([10].as_ref()).unwrap();
137 /// assert_eq!(item, 20);
138 /// ```
139 fn map<T, F>(self, f: F) -> Map<Self, T, F>
140 where
141 F: Fn(Self::Item) -> T,
142 {
143 Map::new(self, f)
144 }
145
146 /// Creates a decoder that tries to convert decoded values by calling the given function.
147 ///
148 /// # Examples
149 ///
150 /// ```
151 /// use bytecodec::{Decode, DecodeExt, ErrorKind, Result};
152 /// use bytecodec::fixnum::U8Decoder;
153 /// use bytecodec::io::IoDecodeExt;
154 /// use trackable::{track, track_assert, track_assert_ne, track_panic};
155 ///
156 /// let mut decoder = U8Decoder::new().try_map(|b| -> Result<_> {
157 /// track_assert_ne!(b, 0, ErrorKind::InvalidInput);
158 /// Ok(b * 2)
159 /// });
160 ///
161 /// let error = decoder.decode_exact([0].as_ref()).err().unwrap();
162 /// assert_eq!(*error.kind(), ErrorKind::InvalidInput);
163 ///
164 /// let item = decoder.decode_exact([4].as_ref()).unwrap();
165 /// assert_eq!(item, 8);
166 /// ```
167 fn try_map<T, E, F>(self, f: F) -> TryMap<Self, T, E, F>
168 where
169 F: Fn(Self::Item) -> std::result::Result<T, E>,
170 Error: From<E>,
171 {
172 TryMap::new(self, f)
173 }
174
175 /// Creates a decoder for modifying decoding errors produced by `self`.
176 ///
177 /// # Examples
178 ///
179 /// The following code shows the idiomatic way to track decoding errors:
180 ///
181 /// ```
182 /// use bytecodec::{Decode, DecodeExt};
183 /// use bytecodec::fixnum::U16beDecoder;
184 /// use bytecodec::io::IoDecodeExt;
185 /// use trackable::track;
186 ///
187 /// let mut decoder =
188 /// U16beDecoder::new().map_err(|e| track!(e, "oops!"));
189 /// // or `track_err!(U16beDecoder::new(), "oops!")`
190 ///
191 /// let input = [0]; // Insufficient bytes
192 /// let error = track!(decoder.decode_exact(input.as_ref())).err().unwrap();
193 ///
194 /// assert_eq!(error.to_string(), "\
195 /// UnexpectedEos (cause; assertion failed: `!eos.is_reached()`; \
196 /// self.offset=1, self.bytes.as_ref().len()=2)
197 /// HISTORY:
198 /// [0] at src/bytes.rs:152
199 /// [1] at src/fixnum.rs:200
200 /// [2] at src/decode.rs:10 -- oops!
201 /// [3] at src/io.rs:45
202 /// [4] at src/decode.rs:14\n");
203 /// ```
204 fn map_err<E, F>(self, f: F) -> MapErr<Self, E, F>
205 where
206 F: Fn(Error) -> E,
207 Error: From<E>,
208 {
209 MapErr::new(self, f)
210 }
211
212 /// Creates a decoder that enables conditional decoding.
213 ///
214 /// If the first item is successfully decoded,
215 /// it will start decoding the second item by using the decoder returned by `f` function.
216 ///
217 /// # Examples
218 ///
219 /// Decodes a length-prefixed string:
220 ///
221 /// ```
222 /// use bytecodec::{Decode, DecodeExt};
223 /// use bytecodec::bytes::Utf8Decoder;
224 /// use bytecodec::fixnum::U8Decoder;
225 /// use bytecodec::io::IoDecodeExt;
226 ///
227 /// let mut decoder = U8Decoder::new().and_then(|len| Utf8Decoder::new().length(len as u64));
228 /// let item = decoder.decode_exact(b"\x03foobar".as_ref()).unwrap();
229 /// assert_eq!(item, "foo");
230 /// ```
231 fn and_then<D, F>(self, f: F) -> AndThen<Self, D, F>
232 where
233 F: Fn(Self::Item) -> D,
234 D: Decode,
235 {
236 AndThen::new(self, f)
237 }
238
239 /// Creates a decoder for collecting decoded items.
240 ///
241 /// # Examples
242 ///
243 /// ```
244 /// use bytecodec::{Decode, DecodeExt};
245 /// use bytecodec::fixnum::U8Decoder;
246 /// use bytecodec::io::IoDecodeExt;
247 ///
248 /// let mut decoder = U8Decoder::new().collect::<Vec<_>>();
249 /// let item = decoder.decode_exact(b"foo".as_ref()).unwrap();
250 /// assert_eq!(item, vec![b'f', b'o', b'o']);
251 /// ```
252 fn collect<T>(self) -> Collect<Self, T>
253 where
254 T: Extend<Self::Item> + Default,
255 {
256 Collect::new(self)
257 }
258
259 /// Creates a decoder that decodes `n` items by using `self` and collecting the result.
260 ///
261 /// # Examples
262 ///
263 /// ```
264 /// use bytecodec::{Decode, DecodeExt};
265 /// use bytecodec::fixnum::U8Decoder;
266 /// use bytecodec::io::IoDecodeExt;
267 ///
268 /// let mut decoder = U8Decoder::new().collectn::<Vec<_>>(2);
269 /// let item = decoder.decode_exact(b"foo".as_ref()).unwrap();
270 /// assert_eq!(item, vec![b'f', b'o']);
271 /// ```
272 fn collectn<T>(self, n: usize) -> CollectN<Self, T>
273 where
274 T: Extend<Self::Item> + Default,
275 {
276 CollectN::new(self, n)
277 }
278
279 /// Creates a decoder that consumes the specified number of bytes exactly.
280 ///
281 /// # Examples
282 ///
283 /// ```
284 /// use bytecodec::{Decode, DecodeExt, ErrorKind};
285 /// use bytecodec::bytes::Utf8Decoder;
286 /// use bytecodec::io::IoDecodeExt;
287 ///
288 /// let mut decoder = Utf8Decoder::new().length(3);
289 /// let mut input = &b"foobarba"[..];
290 ///
291 /// let item = decoder.decode_exact(&mut input).unwrap();
292 /// assert_eq!(item, "foo");
293 ///
294 /// let item = decoder.decode_exact(&mut input).unwrap();
295 /// assert_eq!(item, "bar");
296 ///
297 /// let error = decoder.decode_exact(&mut input).err().unwrap();
298 /// assert_eq!(*error.kind(), ErrorKind::UnexpectedEos);
299 /// ```
300 fn length(self, expected_bytes: u64) -> Length<Self> {
301 Length::new(self, expected_bytes)
302 }
303
304 /// Creates a decoder that will omit decoding items if `do_omit = true` is specified.
305 ///
306 /// # Examples
307 ///
308 /// ```
309 /// use bytecodec::{Decode, DecodeExt};
310 /// use bytecodec::fixnum::U8Decoder;
311 /// use bytecodec::io::IoDecodeExt;
312 ///
313 /// let mut input = &b"foo"[..];
314 ///
315 /// let mut decoder = U8Decoder::new().omit(true);
316 /// let item = decoder.decode_exact(&mut input).unwrap();
317 /// assert_eq!(item, None);
318 ///
319 /// let mut decoder = U8Decoder::new().omit(false);
320 /// let item = decoder.decode_exact(&mut input).unwrap();
321 /// assert_eq!(item, Some(b'f'));
322 /// ```
323 fn omit(self, do_omit: bool) -> Omittable<Self> {
324 Omittable::new(self, do_omit)
325 }
326
327 /// Creates a decoder that will fail if the number of consumed bytes exceeds `bytes`.
328 ///
329 /// # Examples
330 ///
331 /// ```
332 /// use bytecodec::{Decode, DecodeExt, ErrorKind};
333 /// use bytecodec::bytes::Utf8Decoder;
334 /// use bytecodec::io::IoDecodeExt;
335 ///
336 /// let mut decoder = Utf8Decoder::new().max_bytes(3);
337 ///
338 /// let item = decoder.decode_exact(b"foo".as_ref()).unwrap();
339 /// assert_eq!(item, "foo"); // OK
340 ///
341 /// let error = decoder.decode_exact(b"hello".as_ref()).err();
342 /// assert_eq!(error.map(|e| *e.kind()), Some(ErrorKind::InvalidInput)); // Error
343 /// ```
344 fn max_bytes(self, bytes: u64) -> MaxBytes<Self> {
345 MaxBytes::new(self, bytes)
346 }
347
348 /// Takes two decoders and creates a new decoder that decodes both items in sequence.
349 ///
350 /// This is equivalent to call `TupleDecoder::new((self, other))`.
351 fn chain<T: Decode>(self, other: T) -> TupleDecoder<(Self, T)> {
352 TupleDecoder::new((self, other))
353 }
354
355 /// Creates a decoder that makes it possible to slice the input byte sequence in arbitrary units.
356 ///
357 /// Slicing an input byte sequence makes it easier to demultiplex multiple sequences from it.
358 ///
359 /// # Examples
360 ///
361 /// ```
362 /// use bytecodec::{Decode, DecodeExt, Eos};
363 /// use bytecodec::bytes::Utf8Decoder;
364 ///
365 /// let mut decoder0 = Utf8Decoder::new().length(3).slice();
366 /// let mut decoder1 = Utf8Decoder::new().length(3).slice();
367 ///
368 /// let eos = Eos::new(true);
369 /// let input = b"fboaor";
370 /// let mut offset = 0;
371 ///
372 /// for _ in 0..3 {
373 /// decoder0.set_consumable_bytes(1);
374 /// offset += decoder0.decode(&input[offset..], eos).unwrap();
375 ///
376 /// decoder1.set_consumable_bytes(1);
377 /// offset += decoder1.decode(&input[offset..], eos).unwrap();
378 /// }
379 ///
380 /// assert_eq!(offset, input.len());
381 /// assert_eq!(decoder0.finish_decoding().unwrap(), "foo");
382 /// assert_eq!(decoder1.finish_decoding().unwrap(), "bar");
383 /// ```
384 fn slice(self) -> Slice<Self> {
385 Slice::new(self)
386 }
387
388 /// Creates a decoder that enables to peek decoded items before calling `finish_decoding` method.
389 ///
390 /// # Examples
391 ///
392 /// ```
393 /// use bytecodec::{Decode, DecodeExt, Eos};
394 /// use bytecodec::fixnum::U8Decoder;
395 /// use bytecodec::tuple::TupleDecoder;
396 ///
397 /// let mut decoder = TupleDecoder::new((
398 /// U8Decoder::new(),
399 /// U8Decoder::new(),
400 /// U8Decoder::new(),
401 /// )).peekable();
402 /// let size = decoder.decode(b"foo", Eos::new(false)).unwrap();
403 /// assert_eq!(size, 3);
404 /// assert_eq!(decoder.peek(), Some(&(b'f', b'o', b'o')));
405 /// assert_eq!(decoder.finish_decoding().unwrap(), (b'f', b'o', b'o'));
406 /// assert_eq!(decoder.peek(), None);
407 /// ```
408 fn peekable(self) -> Peekable<Self> {
409 Peekable::new(self)
410 }
411
412 /// Creates a decoder that ignores EOS if there is no item being decoded.
413 ///
414 /// # Examples
415 ///
416 /// ```
417 /// use bytecodec::{Decode, DecodeExt, Eos};
418 /// use bytecodec::fixnum::U16beDecoder;
419 ///
420 /// let mut decoder = U16beDecoder::new();
421 /// assert!(decoder.decode(&[][..], Eos::new(true)).is_err()); // UnexpectedEos
422 ///
423 /// let mut decoder = U16beDecoder::new().maybe_eos();
424 /// assert!(decoder.decode(&[][..], Eos::new(true)).is_ok()); // EOS is ignored
425 ///
426 /// let mut decoder = U16beDecoder::new().maybe_eos();
427 /// assert!(decoder.decode(&[1][..], Eos::new(true)).is_err()); // UnexpectedEos
428 /// ```
429 fn maybe_eos(self) -> MaybeEos<Self> {
430 MaybeEos::new(self)
431 }
432
433 /// Decodes an item by consuming the whole part of the given bytes.
434 ///
435 /// # Examples
436 ///
437 /// ```
438 /// use bytecodec::DecodeExt;
439 /// use bytecodec::fixnum::U16beDecoder;
440 ///
441 /// let mut decoder = U16beDecoder::new();
442 /// assert_eq!(
443 /// decoder.decode_from_bytes(&[0x12, 0x34][..]).unwrap(),
444 /// 0x1234
445 /// );
446 /// ```
447 fn decode_from_bytes(&mut self, buf: &[u8]) -> Result<Self::Item> {
448 let size = track!(self.decode(buf, Eos::new(true)))?;
449 track_assert_eq!(size, buf.len(), ErrorKind::InvalidInput; self.is_idle());
450 track!(self.finish_decoding())
451 }
452}
453impl<T: Decode> DecodeExt for T {}
454
455/// This trait allows for decoding tagged items from a byte sequence incrementally.
456pub trait TaggedDecode: Decode {
457 /// The type of tags prefixed to the items to be decoded.
458 type Tag;
459
460 /// Prepares to start decoding an item tagged by `tag`.
461 ///
462 /// # Errors
463 ///
464 /// The following errors may be returned by the decoder:
465 /// - `ErrorKind::InvalidInput`:
466 /// - Unexpected tag was passed
467 /// - `ErrorKind::IncompleteDecoding`:
468 /// - The previous decoding process has not been completed
469 /// - `ErrorKind::DecoderTerminated`:
470 /// - The decoder has terminated (i.e., cannot decode any more items)
471 /// - `ErrorKind::Other`:
472 /// - Other errors has occurred
473 fn start_decoding(&mut self, tag: Self::Tag) -> Result<()>;
474}
475impl<'a, D: ?Sized + TaggedDecode> TaggedDecode for &'a mut D {
476 type Tag = D::Tag;
477
478 fn start_decoding(&mut self, tag: Self::Tag) -> Result<()> {
479 (**self).start_decoding(tag)
480 }
481}
482impl<D: ?Sized + TaggedDecode> TaggedDecode for Box<D> {
483 type Tag = D::Tag;
484
485 fn start_decoding(&mut self, tag: Self::Tag) -> Result<()> {
486 (**self).start_decoding(tag)
487 }
488}
489
490/// This trait allows for decoding known-tagged or unknown-tagged items from a byte sequence incrementally.
491pub trait TryTaggedDecode: Decode {
492 /// The type of tags prefixed to the items to be decoded.
493 type Tag;
494
495 /// Tries to prepare to start decoding an item tagged by `tag`.
496 ///
497 /// If the given tag is unknown, it will return `Ok(false)`.
498 ///
499 /// # Errors
500 ///
501 /// The following errors may be returned by the decoder:
502 /// - `ErrorKind::IncompleteDecoding`:
503 /// - The previous decoding process has not been completed
504 /// - `ErrorKind::DecoderTerminated`:
505 /// - The decoder has terminated (i.e., cannot decode any more items)
506 /// - `ErrorKind::Other`:
507 /// - Other errors has occurred
508 fn try_start_decoding(&mut self, tag: Self::Tag) -> Result<bool>;
509}
510impl<'a, D: ?Sized + TryTaggedDecode> TryTaggedDecode for &'a mut D {
511 type Tag = D::Tag;
512
513 fn try_start_decoding(&mut self, tag: Self::Tag) -> Result<bool> {
514 (**self).try_start_decoding(tag)
515 }
516}
517impl<D: ?Sized + TryTaggedDecode> TryTaggedDecode for Box<D> {
518 type Tag = D::Tag;
519
520 fn try_start_decoding(&mut self, tag: Self::Tag) -> Result<bool> {
521 (**self).try_start_decoding(tag)
522 }
523}
524
525#[cfg(test)]
526mod test {
527 use super::*;
528 use crate::fixnum::U16beDecoder;
529
530 #[test]
531 fn decode_from_bytes_works() {
532 let mut decoder = U16beDecoder::new();
533 assert_eq!(
534 decoder.decode_from_bytes(&[0x12, 0x34][..]).unwrap(),
535 0x1234
536 );
537 }
538}