Skip to main content

tidecoin_io/
lib.rs

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