bitcoin_io/
lib.rs

1// SPDX-License-Identifier: CC0-1.0
2
3//! Rust Bitcoin I/O Library
4//!
5//! The [`std::io`] module is not exposed in `no-std` Rust so building `no-std` applications which
6//! require reading and writing objects via standard traits is not generally possible. Thus, this
7//! library exists to export a minimal version of `std::io`'s traits which we use in `rust-bitcoin`
8//! so that we can support `no-std` applications.
9//!
10//! These traits are not one-for-one drop-ins, but are as close as possible while still implementing
11//! `std::io`'s traits without unnecessary complexity.
12//!
13//! For examples of how to use and implement the types and traits in this crate see `io.rs` in the
14//! `github.com/rust-bitcoin/rust-bitcoin/bitcoin/examples/` directory.
15
16#![cfg_attr(not(feature = "std"), no_std)]
17// Coding conventions.
18#![warn(missing_docs)]
19#![doc(test(attr(warn(unused))))]
20// Pedantic lints that we enforce.
21#![warn(clippy::return_self_not_must_use)]
22// Exclude lints we don't think are valuable.
23#![allow(clippy::needless_question_mark)] // https://github.com/rust-bitcoin/rust-bitcoin/pull/2134
24#![allow(clippy::manual_range_contains)] // More readable than clippy's format.
25#![allow(clippy::uninlined_format_args)] // Allow `format!("{}", x)` instead of enforcing `format!("{x}")`
26
27#[cfg(feature = "alloc")]
28extern crate alloc;
29
30#[cfg(feature = "hashes")]
31pub extern crate hashes;
32
33#[cfg(feature = "std")]
34mod bridge;
35mod error;
36
37#[cfg(feature = "hashes")]
38mod hash;
39
40#[cfg(all(not(feature = "std"), feature = "alloc"))]
41use alloc::vec::Vec;
42use core::cmp;
43
44use encoding::{Decodable, Decoder, Encoder};
45
46#[rustfmt::skip]                // Keep public re-exports separate.
47pub use self::error::{Error, ErrorKind};
48#[cfg(feature = "hashes")]
49pub use self::hash::hash_reader;
50#[cfg(feature = "std")]
51pub use self::bridge::{FromStd, ToStd};
52
53/// Result type returned by functions in this crate.
54pub type Result<T> = core::result::Result<T, Error>;
55
56/// A generic trait describing an input stream.
57///
58/// See [`std::io::Read`] for more information.
59pub trait Read {
60    /// Reads bytes from source into `buf`.
61    ///
62    /// # Returns
63    ///
64    /// The number of bytes read if successful or an [`Error`] if reading fails.
65    fn read(&mut self, buf: &mut [u8]) -> Result<usize>;
66
67    /// Reads bytes from source until `buf` is full.
68    ///
69    /// # Errors
70    ///
71    /// If the exact number of bytes required to fill `buf` cannot be read.
72    #[inline]
73    fn read_exact(&mut self, mut buf: &mut [u8]) -> Result<()> {
74        while !buf.is_empty() {
75            match self.read(buf) {
76                Ok(0) => return Err(ErrorKind::UnexpectedEof.into()),
77                Ok(len) => buf = &mut buf[len..],
78                Err(e) if e.kind() == ErrorKind::Interrupted => {}
79                Err(e) => return Err(e),
80            }
81        }
82        Ok(())
83    }
84
85    /// Constructs a new adapter which will read at most `limit` bytes.
86    #[inline]
87    fn take(self, limit: u64) -> Take<Self>
88        where Self: Sized,
89    { Take { reader: self, remaining: limit } }
90
91    /// Attempts to read up to limit bytes from the reader, allocating space in `buf` as needed.
92    ///
93    /// `limit` is used to prevent a denial of service attack vector since an unbounded reader will
94    /// exhaust all memory.
95    ///
96    /// Similar to [`std::io::Read::read_to_end`] but with the DOS protection.
97    ///
98    /// # Returns
99    ///
100    /// The number of bytes read if successful or an [`Error`] if reading fails.
101    #[doc(alias = "read_to_end")]
102    #[cfg(feature = "alloc")]
103    #[inline]
104    fn read_to_limit(&mut self, buf: &mut Vec<u8>, limit: u64) -> Result<usize> {
105        self.take(limit).read_to_end(buf)
106    }
107}
108
109/// A trait describing an input stream that uses an internal buffer when reading.
110pub trait BufRead: Read {
111    /// Returns data read from this reader, filling the internal buffer if needed.
112    ///
113    /// # Errors
114    ///
115    /// May error if reading fails.
116    fn fill_buf(&mut self) -> Result<&[u8]>;
117
118    /// Marks the buffered data up to amount as consumed.
119    ///
120    /// # Panics
121    ///
122    /// May panic if `amount` is greater than amount of data read by `fill_buf`.
123    fn consume(&mut self, amount: usize);
124}
125
126/// Reader adapter which limits the bytes read from an underlying reader.
127///
128/// Created by calling `[Read::take]`.
129#[derive(Debug)]
130pub struct Take<R> {
131    reader: R,
132    remaining: u64,
133}
134
135impl<R: Read> Take<R> {
136    /// Reads all bytes until EOF from the underlying reader into `buf`.
137    ///
138    /// Allocates space in `buf` as needed.
139    ///
140    /// # Returns
141    ///
142    /// The number of bytes read if successful or an [`Error`] if reading fails.
143    #[cfg(feature = "alloc")]
144    #[inline]
145    pub fn read_to_end(&mut self, buf: &mut Vec<u8>) -> Result<usize> {
146        let mut read: usize = 0;
147        let mut chunk = [0u8; 64];
148        loop {
149            match self.read(&mut chunk) {
150                Ok(0) => break,
151                Ok(n) => {
152                    buf.extend_from_slice(&chunk[0..n]);
153                    read += n;
154                }
155                Err(ref e) if e.kind() == ErrorKind::Interrupted => {}
156                Err(e) => return Err(e),
157            };
158        }
159        Ok(read)
160    }
161}
162
163impl<R: Read> Read for Take<R> {
164    #[inline]
165    fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
166        let len = cmp::min(buf.len(), self.remaining.try_into().unwrap_or(buf.len()));
167        let read = self.reader.read(&mut buf[..len])?;
168        self.remaining -= read.try_into().unwrap_or(self.remaining);
169        Ok(read)
170    }
171}
172
173// Impl copied from Rust stdlib.
174impl<R: BufRead> BufRead for Take<R> {
175    #[inline]
176    fn fill_buf(&mut self) -> Result<&[u8]> {
177        // Don't call into inner reader at all at EOF because it may still block
178        if self.remaining == 0 {
179            return Ok(&[]);
180        }
181
182        let buf = self.reader.fill_buf()?;
183        // Cast length to a u64 instead of casting `remaining` to a `usize`
184        // (in case `remaining > u32::MAX` and we are on a 32 bit machine).
185        let cap = cmp::min(buf.len() as u64, self.remaining) as usize;
186        Ok(&buf[..cap])
187    }
188
189    #[inline]
190    fn consume(&mut self, amount: usize) {
191        assert!(amount as u64 <= self.remaining);
192        self.remaining -= amount as u64;
193        self.reader.consume(amount);
194    }
195}
196
197impl<T: Read + ?Sized> Read for &'_ mut T {
198    #[inline]
199    fn read(&mut self, buf: &mut [u8]) -> Result<usize> { (**self).read(buf) }
200
201    #[inline]
202    fn read_exact(&mut self, buf: &mut [u8]) -> Result<()> { (**self).read_exact(buf) }
203}
204
205impl<T: BufRead + ?Sized> BufRead for &'_ mut T {
206    #[inline]
207    fn fill_buf(&mut self) -> Result<&[u8]> { (**self).fill_buf() }
208
209    #[inline]
210    fn consume(&mut self, amount: usize) { (**self).consume(amount) }
211}
212
213impl Read for &[u8] {
214    #[inline]
215    fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
216        let cnt = cmp::min(self.len(), buf.len());
217        buf[..cnt].copy_from_slice(&self[..cnt]);
218        *self = &self[cnt..];
219        Ok(cnt)
220    }
221}
222
223impl BufRead for &[u8] {
224    #[inline]
225    fn fill_buf(&mut self) -> Result<&[u8]> { Ok(self) }
226
227    // This panics if amount is out of bounds, same as the std version.
228    #[inline]
229    fn consume(&mut self, amount: usize) { *self = &self[amount..] }
230}
231
232/// Wraps an in memory buffer providing `position` functionality for read and write.
233#[derive(Clone, Debug, Default, Eq, PartialEq)]
234pub struct Cursor<T> {
235    inner: T,
236    pos: u64,
237}
238
239impl<T: AsRef<[u8]>> Cursor<T> {
240    /// Constructs a new `Cursor` by wrapping `inner`.
241    #[inline]
242    pub const fn new(inner: T) -> Self { Self { inner, pos: 0 } }
243
244    /// Returns the position read or written up to thus far.
245    #[inline]
246    pub const fn position(&self) -> u64 { self.pos }
247
248    /// Sets the internal position.
249    ///
250    /// This method allows seeking within the wrapped memory by setting the position.
251    ///
252    /// Note that setting a position that is larger than the buffer length will cause reads to
253    /// succeed by reading zero bytes. Further, writes will be no-op zero length writes.
254    #[inline]
255    pub fn set_position(&mut self, position: u64) { self.pos = position; }
256
257    /// Returns the inner buffer.
258    ///
259    /// This is the whole wrapped buffer, including the bytes already read.
260    #[inline]
261    pub fn into_inner(self) -> T { self.inner }
262
263    /// Returns a reference to the inner buffer.
264    ///
265    /// This is the whole wrapped buffer, including the bytes already read.
266    #[inline]
267    pub const fn get_ref(&self) -> &T { &self.inner }
268
269    /// Returns a mutable reference to the inner buffer.
270    ///
271    /// This is the whole wrapped buffer, including the bytes already read.
272    #[inline]
273    pub fn get_mut(&mut self) -> &mut T { &mut self.inner }
274
275    /// Returns a reference to the inner buffer.
276    ///
277    /// This is the whole wrapped buffer, including the bytes already read.
278    #[inline]
279    #[deprecated(since = "0.3.0", note = "use `get_ref()` instead")]
280    pub fn inner(&self) -> &T { &self.inner }
281}
282
283impl<T: AsRef<[u8]>> Read for Cursor<T> {
284    #[inline]
285    fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
286        let inner: &[u8] = self.inner.as_ref();
287        let start_pos = self.pos.try_into().unwrap_or(inner.len());
288        if start_pos >= self.inner.as_ref().len() {
289            return Ok(0);
290        }
291
292        let read = core::cmp::min(inner.len().saturating_sub(start_pos), buf.len());
293        buf[..read].copy_from_slice(&inner[start_pos..start_pos + read]);
294        self.pos = self.pos.saturating_add(read.try_into().unwrap_or(u64::MAX /* unreachable */));
295        Ok(read)
296    }
297}
298
299impl<T: AsRef<[u8]>> BufRead for Cursor<T> {
300    #[inline]
301    fn fill_buf(&mut self) -> Result<&[u8]> {
302        let inner: &[u8] = self.inner.as_ref();
303        let pos = self.pos.min(inner.len() as u64) as usize;
304        Ok(&inner[pos..])
305    }
306
307    #[inline]
308    fn consume(&mut self, amount: usize) { self.pos = self.pos.saturating_add(amount as u64); }
309}
310
311impl<T: AsMut<[u8]>> Write for Cursor<T> {
312    #[inline]
313    fn write(&mut self, buf: &[u8]) -> Result<usize> {
314        let write_slice = self.inner.as_mut();
315        let pos = cmp::min(self.pos, write_slice.len() as u64);
316        let amt = (&mut write_slice[(pos as usize)..]).write(buf)?;
317        self.pos += amt as u64;
318        Ok(amt)
319    }
320
321    #[inline]
322    fn flush(&mut self) -> Result<()> { Ok(()) }
323}
324
325/// A generic trait describing an output stream.
326///
327/// See [`std::io::Write`] for more information.
328pub trait Write {
329    /// Writes `buf` into this writer, returning how many bytes were written.
330    fn write(&mut self, buf: &[u8]) -> Result<usize>;
331
332    /// Flushes this output stream, ensuring that all intermediately buffered contents
333    /// reach their destination.
334    fn flush(&mut self) -> Result<()>;
335
336    /// Attempts to write an entire buffer into this writer.
337    #[inline]
338    fn write_all(&mut self, mut buf: &[u8]) -> Result<()> {
339        while !buf.is_empty() {
340            match self.write(buf) {
341                Ok(0) => return Err(ErrorKind::UnexpectedEof.into()),
342                Ok(len) => buf = &buf[len..],
343                Err(e) if e.kind() == ErrorKind::Interrupted => {}
344                Err(e) => return Err(e),
345            }
346        }
347        Ok(())
348    }
349}
350
351impl<T: Write> Write for &'_ mut T {
352    #[inline]
353    fn write(&mut self, buf: &[u8]) -> Result<usize> { (**self).write(buf) }
354
355    #[inline]
356    fn write_all(&mut self, buf: &[u8]) -> Result<()> { (**self).write_all(buf) }
357
358    #[inline]
359    fn flush(&mut self) -> Result<()> { (**self).flush() }
360}
361
362#[cfg(feature = "alloc")]
363impl Write for alloc::vec::Vec<u8> {
364    #[inline]
365    fn write(&mut self, buf: &[u8]) -> Result<usize> {
366        self.extend_from_slice(buf);
367        Ok(buf.len())
368    }
369
370    #[inline]
371    fn flush(&mut self) -> Result<()> { Ok(()) }
372}
373
374impl Write for &mut [u8] {
375    #[inline]
376    fn write(&mut self, buf: &[u8]) -> Result<usize> {
377        let cnt = core::cmp::min(self.len(), buf.len());
378        self[..cnt].copy_from_slice(&buf[..cnt]);
379        *self = &mut core::mem::take(self)[cnt..];
380        Ok(cnt)
381    }
382
383    #[inline]
384    fn flush(&mut self) -> Result<()> { Ok(()) }
385}
386
387/// A sink to which all writes succeed.
388///
389/// Created using [`sink()`]. See [`std::io::Sink`] for more information.
390#[derive(Clone, Copy, Debug, Default)]
391pub struct Sink;
392
393impl Write for Sink {
394    #[inline]
395    fn write(&mut self, buf: &[u8]) -> Result<usize> { Ok(buf.len()) }
396
397    #[inline]
398    fn write_all(&mut self, _: &[u8]) -> Result<()> { Ok(()) }
399
400    #[inline]
401    fn flush(&mut self) -> Result<()> { Ok(()) }
402}
403
404/// Returns a sink to which all writes succeed.
405///
406/// See [`std::io::sink`] for more information.
407#[inline]
408pub fn sink() -> Sink { Sink }
409
410/// Wraps a `std` I/O type to implement the traits from this crate.
411///
412/// All methods are passed through converting the errors.
413#[cfg(feature = "std")]
414#[inline]
415pub const fn from_std<T>(std_io: T) -> FromStd<T> { FromStd::new(std_io) }
416
417/// Wraps a mutable reference to `std` I/O type to implement the traits from this crate.
418///
419/// All methods are passed through converting the errors.
420#[cfg(feature = "std")]
421#[inline]
422pub fn from_std_mut<T>(std_io: &mut T) -> &mut FromStd<T> { FromStd::new_mut(std_io) }
423
424/// Encodes a consensus_encoding object to an I/O writer.
425pub fn encode_to_writer<T, W>(object: &T, mut writer: W) -> Result<()>
426where
427    T: encoding::Encodable + ?Sized,
428    W: Write,
429{
430    let mut encoder = object.encoder();
431    loop {
432        writer.write_all(encoder.current_chunk())?;
433        if !encoder.advance() {
434            break;
435        }
436    }
437    Ok(())
438}
439
440/// Decodes an object from a buffered reader.
441///
442/// # Performance
443///
444/// For unbuffered readers (like [`std::fs::File`] or [`std::net::TcpStream`]), consider wrapping
445/// your reader with [`std::io::BufReader`] in order to use this function. This avoids frequent
446/// small reads, which can significantly impact performance.
447///
448/// # Errors
449///
450/// Returns [`ReadError::Decode`] if the decoder encounters an error while parsing
451/// the data, or [`ReadError::Io`] if an I/O error occurs while reading.
452pub fn decode_from_read<T, R>(mut reader: R) -> core::result::Result<T, ReadError<<T::Decoder as Decoder>::Error>>
453where
454    T: Decodable,
455    R: BufRead,
456{
457    let mut decoder = T::decoder();
458
459    loop {
460        let mut buffer = match reader.fill_buf() {
461            Ok(buffer) => buffer,
462            // Auto retry read for non-fatal error.
463            Err(error) if error.kind() == ErrorKind::Interrupted => continue,
464            Err(error) => return Err(ReadError::Io(error)),
465        };
466
467        if buffer.is_empty() {
468            // EOF, but still try to finalize the decoder.
469            return decoder.end().map_err(ReadError::Decode);
470        }
471
472        let original_len = buffer.len();
473        let need_more = decoder.push_bytes(&mut buffer).map_err(ReadError::Decode)?;
474        let consumed = original_len - buffer.len();
475        reader.consume(consumed);
476
477        if !need_more {
478            return decoder.end().map_err(ReadError::Decode);
479        }
480    }
481}
482
483/// Decodes an object from an unbuffered reader using a fixed-size buffer.
484///
485/// For most use cases, prefer [`decode_from_read`] with a [`std::io::BufReader`].
486/// This function is only needed when you have an unbuffered reader which you
487/// cannot wrap. It will probably have worse performance.
488///
489/// # Buffer
490///
491/// Uses a fixed 4KB (4096 bytes) stack-allocated buffer that is reused across
492/// read operations. This size is a good balance between memory usage and
493/// system call efficiency for most use cases.
494///
495/// For different buffer sizes, use [`decode_from_read_unbuffered_with`].
496///
497/// # Errors
498///
499/// Returns [`ReadError::Decode`] if the decoder encounters an error while parsing
500/// the data, or [`ReadError::Io`] if an I/O error occurs while reading.
501pub fn decode_from_read_unbuffered<T, R>(
502    reader: R,
503) -> core::result::Result<T, ReadError<<T::Decoder as Decoder>::Error>>
504where
505    T: Decodable,
506    R: Read,
507{
508    decode_from_read_unbuffered_with::<T, R, 4096>(reader)
509}
510
511/// Decodes an object from an unbuffered reader using a custom-sized buffer.
512///
513/// For most use cases, prefer [`decode_from_read`] with a [`std::io::BufReader`].
514/// This function is only needed when you have an unbuffered reader which you
515/// cannot wrap. It will probably have worse performance.
516///
517/// # Buffer
518///
519/// The `BUFFER_SIZE` parameter controls the intermediate buffer size used for
520/// reading. The buffer is allocated on the stack (not heap) and reused across
521/// read operations. Larger buffers reduce the number of system calls, but use
522/// more memory.
523///
524/// # Errors
525///
526/// Returns [`ReadError::Decode`] if the decoder encounters an error while parsing
527/// the data, or [`ReadError::Io`] if an I/O error occurs while reading.
528pub fn decode_from_read_unbuffered_with<T, R, const BUFFER_SIZE: usize>(
529    mut reader: R,
530) -> core::result::Result<T, ReadError<<T::Decoder as Decoder>::Error>>
531where
532    T: Decodable,
533    R: Read,
534{
535    let mut decoder = T::decoder();
536    let mut buffer = [0u8; BUFFER_SIZE];
537
538    while decoder.read_limit() > 0 {
539        // Only read what we need, up to buffer size.
540        let clamped_buffer = &mut buffer[..decoder.read_limit().min(BUFFER_SIZE)];
541        match reader.read(clamped_buffer) {
542            Ok(0) => {
543                // EOF, but still try to finalize the decoder.
544                return decoder.end().map_err(ReadError::Decode);
545            }
546            Ok(bytes_read) => {
547                if !decoder
548                    .push_bytes(&mut &clamped_buffer[..bytes_read])
549                    .map_err(ReadError::Decode)?
550                {
551                    return decoder.end().map_err(ReadError::Decode);
552                }
553            }
554            Err(ref e) if e.kind() == ErrorKind::Interrupted => {
555                // Auto retry read for non-fatal error.
556            }
557            Err(e) => return Err(ReadError::Io(e)),
558        }
559    }
560
561    decoder.end().map_err(ReadError::Decode)
562}
563
564/// An error that can occur when reading and decoding from a buffered reader.
565#[derive(Debug)]
566pub enum ReadError<D> {
567    /// An I/O error occurred while reading from the reader.
568    Io(Error),
569    /// The decoder encountered an error while parsing the data.
570    Decode(D),
571}
572
573impl<D: core::fmt::Display> core::fmt::Display for ReadError<D> {
574    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
575        match self {
576            Self::Io(e) => write!(f, "I/O error: {}", e),
577            Self::Decode(e) => write!(f, "decode error: {}", e),
578        }
579    }
580}
581
582#[cfg(feature = "std")]
583impl<D> std::error::Error for ReadError<D>
584where
585    D: core::fmt::Debug + core::fmt::Display + std::error::Error + 'static,
586{
587    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
588        match self {
589            Self::Io(e) => Some(e),
590            Self::Decode(e) => Some(e),
591        }
592    }
593}
594
595#[cfg(feature = "std")]
596impl<D> From<Error> for ReadError<D> {
597    fn from(e: Error) -> Self { Self::Io(e) }
598}
599
600#[cfg(test)]
601mod tests {
602    #[cfg(all(not(feature = "std"), feature = "alloc"))]
603    use alloc::{string::ToString, vec};
604
605    use encoding::{ArrayDecoder, ArrayEncoder, UnexpectedEofError};
606
607    use super::*;
608
609    #[test]
610    fn buf_read_fill_and_consume_slice() {
611        let data = [0_u8, 1, 2];
612
613        let mut slice = &data[..];
614
615        let fill = BufRead::fill_buf(&mut slice).unwrap();
616        assert_eq!(fill.len(), 3);
617        assert_eq!(fill, &[0_u8, 1, 2]);
618        slice.consume(2);
619
620        let fill = BufRead::fill_buf(&mut slice).unwrap();
621        assert_eq!(fill.len(), 1);
622        assert_eq!(fill, &[2_u8]);
623        slice.consume(1);
624
625        // checks we can attempt to read from a now-empty reader.
626        let fill = BufRead::fill_buf(&mut slice).unwrap();
627        assert!(fill.is_empty());
628    }
629
630    #[test]
631    #[cfg(feature = "alloc")]
632    fn read_to_limit_greater_than_total_length() {
633        let s = "16-byte-string!!".to_string();
634        let mut reader = Cursor::new(&s);
635        let mut buf = vec![];
636
637        // 32 is greater than the reader length.
638        let read = reader.read_to_limit(&mut buf, 32).expect("failed to read to limit");
639        assert_eq!(read, s.len());
640        assert_eq!(&buf, s.as_bytes())
641    }
642
643    #[test]
644    #[cfg(feature = "alloc")]
645    fn read_to_limit_less_than_total_length() {
646        let s = "16-byte-string!!".to_string();
647        let mut reader = Cursor::new(&s);
648        let mut buf = vec![];
649
650        let read = reader.read_to_limit(&mut buf, 2).expect("failed to read to limit");
651        assert_eq!(read, 2);
652        assert_eq!(&buf, "16".as_bytes())
653    }
654
655    #[test]
656    #[cfg(feature = "std")]
657    fn set_position_past_end_read_returns_eof() {
658        const BUF_LEN: usize = 64; // Just a small buffer.
659        let mut buf = [0_u8; BUF_LEN]; // We never actually write to this buffer.
660
661        let v = [1_u8; BUF_LEN];
662
663        // Sanity check the stdlib Cursor's behaviour.
664        let mut c = std::io::Cursor::new(v);
665        for pos in [BUF_LEN, BUF_LEN + 1, BUF_LEN * 2] {
666            c.set_position(pos as u64);
667            let read = c.read(&mut buf).unwrap();
668            assert_eq!(read, 0);
669            assert_eq!(buf[0], 0x00); // Double check that buffer state is sane.
670        }
671
672        let mut c = Cursor::new(v);
673        for pos in [BUF_LEN, BUF_LEN + 1, BUF_LEN * 2] {
674            c.set_position(pos as u64);
675            let read = c.read(&mut buf).unwrap();
676            assert_eq!(read, 0);
677            assert_eq!(buf[0], 0x00); // Double check that buffer state is sane.
678        }
679    }
680
681    #[test]
682    fn read_into_zero_length_buffer() {
683        use crate::Read as _;
684
685        const BUF_LEN: usize = 64;
686        let data = [1_u8; BUF_LEN];
687        let mut buf = [0_u8; BUF_LEN];
688
689        let mut slice = data.as_ref();
690        let mut take = Read::take(&mut slice, 32);
691
692        let read = take.read(&mut buf[0..0]).unwrap();
693        assert_eq!(read, 0);
694        assert_eq!(buf[0], 0x00); // Check the buffer didn't get touched.
695    }
696
697    #[test]
698    #[cfg(feature = "alloc")]
699    fn take_and_read_to_end() {
700        const BUF_LEN: usize = 64;
701        let data = [1_u8; BUF_LEN];
702
703        let mut slice = data.as_ref();
704        let mut take = Read::take(&mut slice, 32);
705
706        let mut v = Vec::new();
707        let read = take.read_to_end(&mut v).unwrap();
708        assert_eq!(read, 32);
709        assert_eq!(data[0..32], v[0..32]);
710    }
711
712    #[test]
713    fn cursor_fill_buf_past_end() {
714        let data = [1, 2, 3];
715        let mut cursor = Cursor::new(&data);
716        cursor.set_position(10);
717
718        let buf = cursor.fill_buf().unwrap();
719        assert!(buf.is_empty());
720    }
721
722    #[test]
723    fn cursor_write() {
724        let data = [0x78, 0x56, 0x34, 0x12];
725
726        let mut buf = [0_u8; 4];
727        let mut cursor = Cursor::new(&mut buf);
728        let amt = cursor.write(&data).unwrap();
729
730        assert_eq!(buf, data);
731        assert_eq!(amt, 4);
732    }
733
734    #[test]
735    fn cursor_offset_write() {
736        let data = [0x78, 0x56, 0x34, 0x12];
737
738        let mut buf = [0_u8; 4];
739        let mut cursor = Cursor::new(&mut buf);
740        cursor.set_position(2);
741        let amt = cursor.write(&data).unwrap();
742
743        assert_eq!(buf, [0, 0, 0x78, 0x56]);
744        assert_eq!(amt, 2);
745    }
746
747    #[test]
748    fn cursor_consume_past_end() {
749        let data = [1, 2, 3];
750        let mut cursor = Cursor::new(&data);
751        cursor.set_position(10);
752
753        cursor.consume(5);
754        assert_eq!(cursor.position(), 15);
755    }
756
757    // Simple test type that implements Encodable.
758    struct TestData(u32);
759
760    impl encoding::Encodable for TestData {
761        type Encoder<'s>
762            = ArrayEncoder<4>
763        where
764            Self: 's;
765
766        fn encoder(&self) -> Self::Encoder<'_> {
767            ArrayEncoder::without_length_prefix(self.0.to_le_bytes())
768        }
769    }
770
771    #[test]
772    fn encode_io_writer() {
773        let data = TestData(0x1234_5678);
774
775        let mut buf = [0_u8; 4];
776        encode_to_writer(&data, buf.as_mut_slice()).unwrap();
777
778        assert_eq!(buf, [0x78, 0x56, 0x34, 0x12]);
779    }
780
781    #[derive(Debug, PartialEq)]
782    struct TestArray([u8; 4]);
783
784    impl Decodable for TestArray {
785        type Decoder = TestArrayDecoder;
786        fn decoder() -> Self::Decoder { TestArrayDecoder { inner: ArrayDecoder::new() } }
787    }
788
789    struct TestArrayDecoder {
790        inner: ArrayDecoder<4>,
791    }
792
793    impl Decoder for TestArrayDecoder {
794        type Output = TestArray;
795        type Error = UnexpectedEofError;
796
797        fn push_bytes(&mut self, bytes: &mut &[u8]) -> core::result::Result<bool, Self::Error> {
798            self.inner.push_bytes(bytes)
799        }
800
801        fn end(self) -> core::result::Result<Self::Output, Self::Error> { self.inner.end().map(TestArray) }
802
803        fn read_limit(&self) -> usize { self.inner.read_limit() }
804    }
805
806    #[test]
807    fn decode_from_read_success() {
808        let data = [1, 2, 3, 4];
809        let cursor = Cursor::new(&data);
810        let result: core::result::Result<TestArray, _> = decode_from_read(cursor);
811        assert!(result.is_ok());
812        let decoded = result.unwrap();
813        assert_eq!(decoded.0, [1, 2, 3, 4]);
814    }
815
816    #[test]
817    fn decode_from_read_unexpected_eof() {
818        let data = [1, 2, 3];
819        let cursor = Cursor::new(&data);
820        let result: core::result::Result<TestArray, _> = decode_from_read(cursor);
821        assert!(matches!(result, Err(ReadError::Decode(_))));
822    }
823
824    #[test]
825    fn decode_from_read_trait_object() {
826        let data = [1, 2, 3, 4];
827        let mut cursor = Cursor::new(&data);
828        // Test that we can pass a trait object (&mut dyn BufRead implements BufRead).
829        let reader: &mut dyn BufRead = &mut cursor;
830        let result: core::result::Result<TestArray, _> = decode_from_read(reader);
831        assert!(result.is_ok());
832        let decoded = result.unwrap();
833        assert_eq!(decoded.0, [1, 2, 3, 4]);
834    }
835
836    #[test]
837    #[cfg(feature = "alloc")]
838    fn decode_from_read_by_reference() {
839        use crate::alloc::vec::Vec;
840
841        let data = [1, 2, 3, 4];
842        let mut cursor = Cursor::new(&data);
843        // Test that we can pass by reference (&mut T implements BufRead when T: BufRead).
844        let result: core::result::Result<TestArray, _> = decode_from_read(&mut cursor);
845        assert!(result.is_ok());
846        let decoded = result.unwrap();
847        assert_eq!(decoded.0, [1, 2, 3, 4]);
848
849        let mut buf = Vec::new();
850        let _ = cursor.read_to_limit(&mut buf, 100);
851    }
852
853    #[test]
854    fn decode_from_read_unbuffered_success() {
855        let data = [1, 2, 3, 4];
856        let cursor = Cursor::new(&data);
857        let result: core::result::Result<TestArray, _> = decode_from_read_unbuffered(cursor);
858        assert!(result.is_ok());
859        let decoded = result.unwrap();
860        assert_eq!(decoded.0, [1, 2, 3, 4]);
861    }
862
863    #[test]
864    fn decode_from_read_unbuffered_unexpected_eof() {
865        let data = [1, 2, 3];
866        let cursor = Cursor::new(&data);
867        let result: core::result::Result<TestArray, _> = decode_from_read_unbuffered(cursor);
868        assert!(matches!(result, Err(ReadError::Decode(_))));
869    }
870
871    #[test]
872    fn decode_from_read_unbuffered_empty() {
873        let data = [];
874        let cursor = Cursor::new(&data);
875        let result: core::result::Result<TestArray, _> = decode_from_read_unbuffered(cursor);
876        assert!(matches!(result, Err(ReadError::Decode(_))));
877    }
878
879    #[test]
880    fn decode_from_read_unbuffered_extra_data() {
881        let data = [1, 2, 3, 4, 5, 6];
882        let cursor = Cursor::new(&data);
883        let result: core::result::Result<TestArray, _> = decode_from_read_unbuffered(cursor);
884        assert!(result.is_ok());
885        let decoded = result.unwrap();
886        assert_eq!(decoded.0, [1, 2, 3, 4]);
887    }
888}