Skip to main content

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