Skip to main content

bitcoin_consensus_encoding/decode/
mod.rs

1// SPDX-License-Identifier: CC0-1.0
2
3//! Consensus Decoding Traits
4
5pub mod decoders;
6
7#[cfg(feature = "std")]
8use crate::ReadError;
9use crate::{DecodeError, UnconsumedError};
10
11/// A Bitcoin object which can be consensus-decoded using a push decoder.
12///
13/// To decode something, create a [`Self::Decoder`] and push byte slices into it with
14/// [`Decoder::push_bytes`], then call [`Decoder::end`] to get the result.
15///
16/// # Examples
17///
18/// ```
19/// use bitcoin_consensus_encoding::{decode_from_slice, Decodable, Decoder, ArrayDecoder, UnexpectedEofError};
20///
21/// struct Foo([u8; 4]);
22///
23/// struct FooDecoder(ArrayDecoder<4>);
24///
25/// impl Decoder for FooDecoder {
26///     type Output = Foo;
27///     type Error = UnexpectedEofError;
28///
29///     fn push_bytes(&mut self, bytes: &mut &[u8]) -> Result<bool, Self::Error> {
30///         self.0.push_bytes(bytes)
31///     }
32///     fn end(self) -> Result<Self::Output, Self::Error> { self.0.end().map(Foo) }
33///     fn read_limit(&self) -> usize { self.0.read_limit() }
34/// }
35///
36/// impl Decodable for Foo {
37///     type Decoder = FooDecoder;
38///     fn decoder() -> Self::Decoder { FooDecoder(ArrayDecoder::new()) }
39/// }
40///
41/// let foo: Foo = decode_from_slice(&[0xde, 0xad, 0xbe, 0xef]).unwrap();
42/// assert_eq!(foo.0, [0xde, 0xad, 0xbe, 0xef]);
43/// ```
44pub trait Decodable {
45    /// Associated decoder for the type.
46    type Decoder: Decoder<Output = Self>;
47
48    /// Constructs a "default decoder" for the type.
49    fn decoder() -> Self::Decoder;
50}
51
52/// A push decoder for a consensus-decodable object.
53pub trait Decoder: Sized {
54    /// The type that this decoder produces when decoding is complete.
55    type Output;
56    /// The error type that this decoder can produce.
57    type Error;
58
59    /// Pushes bytes into the decoder, consuming as much as possible.
60    ///
61    /// The slice reference will be advanced to point to the unconsumed portion. Returns `Ok(true)`
62    /// if more bytes are needed to complete decoding, `Ok(false)` if the decoder is ready to
63    /// finalize with [`Self::end`], or `Err(error)` if parsing failed.
64    ///
65    /// # Errors
66    ///
67    /// Returns an error if the provided bytes are invalid or malformed according to the decoder's
68    /// validation rules. Insufficient data (needing more bytes) is *not* an error for this method,
69    /// the decoder will simply consume what it can and return `true` to indicate more data is
70    /// needed.
71    ///
72    /// # Panics
73    ///
74    /// May panic if called after a previous call to [`Self::push_bytes`] errored.
75    #[must_use = "must check result to avoid panics on subsequent calls"]
76    #[track_caller]
77    fn push_bytes(&mut self, bytes: &mut &[u8]) -> Result<bool, Self::Error>;
78
79    /// Completes the decoding process and return the final result.
80    ///
81    /// This consumes the decoder and should be called when no more input data is available.
82    ///
83    /// # Errors
84    ///
85    /// Returns an error if the decoder has not received sufficient data to complete decoding, or if
86    /// the accumulated data is invalid when considered as a complete object.
87    ///
88    /// # Panics
89    ///
90    /// May panic if called after a previous call to [`Self::push_bytes`] errored.
91    #[must_use = "must check result to avoid panics on subsequent calls"]
92    #[track_caller]
93    fn end(self) -> Result<Self::Output, Self::Error>;
94
95    /// Returns the maximum number of bytes this decoder can consume without over-reading.
96    ///
97    /// Returns 0 if the decoder is complete and ready to finalize with [`Self::end`]. This is used
98    /// by [`decode_from_read_unbuffered`] to optimize read sizes, avoiding both inefficient
99    /// under-reads and unnecessary over-reads.
100    fn read_limit(&self) -> usize;
101}
102
103/// Decodes an object from a byte slice.
104///
105/// # Errors
106///
107/// Returns an error if the decoder encounters an error while parsing the data, including
108/// insufficient data. This function also errors if the provided slice is not completely consumed
109/// during decode.
110pub fn decode_from_slice<T: Decodable>(
111    bytes: &[u8],
112) -> Result<T, DecodeError<<T::Decoder as Decoder>::Error>> {
113    let mut remaining = bytes;
114    let data = decode_from_slice_unbounded::<T>(&mut remaining).map_err(DecodeError::Parse)?;
115
116    if remaining.is_empty() {
117        Ok(data)
118    } else {
119        Err(DecodeError::Unconsumed(UnconsumedError()))
120    }
121}
122
123/// Decodes an object from an unbounded byte slice.
124///
125/// Unlike [`decode_from_slice`], this function will not error if the slice contains additional
126/// bytes that are not required to decode. Furthermore, the byte slice reference provided to this
127/// function will be updated based on the consumed data, returning the unconsumed bytes.
128///
129/// # Errors
130///
131/// Returns an error if the decoder encounters an error while parsing the data, including
132/// insufficient data.
133pub fn decode_from_slice_unbounded<T>(
134    bytes: &mut &[u8],
135) -> Result<T, <T::Decoder as Decoder>::Error>
136where
137    T: Decodable,
138{
139    let mut decoder = T::decoder();
140
141    while !bytes.is_empty() {
142        if !decoder.push_bytes(bytes)? {
143            break;
144        }
145    }
146
147    decoder.end()
148}
149
150/// Decodes an object from a buffered reader.
151///
152/// # Performance
153///
154/// For unbuffered readers (like [`std::fs::File`] or [`std::net::TcpStream`]), consider wrapping
155/// your reader with [`std::io::BufReader`] in order to use this function. This avoids frequent
156/// small reads, which can significantly impact performance.
157///
158/// # Errors
159///
160/// Returns [`ReadError::Decode`] if the decoder encounters an error while parsing the data, or
161/// [`ReadError::Io`] if an I/O error occurs while reading.
162#[cfg(feature = "std")]
163pub fn decode_from_read<T, R>(mut reader: R) -> Result<T, ReadError<<T::Decoder as Decoder>::Error>>
164where
165    T: Decodable,
166    R: std::io::BufRead,
167{
168    let mut decoder = T::decoder();
169
170    loop {
171        let mut buffer = match reader.fill_buf() {
172            Ok(buffer) => buffer,
173            // Auto retry read for non-fatal error.
174            Err(error) if error.kind() == std::io::ErrorKind::Interrupted => continue,
175            Err(error) => return Err(ReadError::Io(error)),
176        };
177
178        if buffer.is_empty() {
179            // EOF, but still try to finalize the decoder.
180            return decoder.end().map_err(ReadError::Decode);
181        }
182
183        let original_len = buffer.len();
184        let need_more = decoder.push_bytes(&mut buffer).map_err(ReadError::Decode)?;
185        let consumed = original_len - buffer.len();
186        reader.consume(consumed);
187
188        if !need_more {
189            return decoder.end().map_err(ReadError::Decode);
190        }
191    }
192}
193
194/// Decodes an object from an unbuffered reader using a fixed-size buffer.
195///
196/// For most use cases, prefer [`decode_from_read`] with a [`std::io::BufReader`]. This function is
197/// only needed when you have an unbuffered reader which you cannot wrap. It will probably have
198/// worse performance.
199///
200/// # Buffer
201///
202/// Uses a fixed 4KB (4096 bytes) stack-allocated buffer that is reused across read operations. This
203/// size is a good balance between memory usage and system call efficiency for most use cases.
204///
205/// For different buffer sizes, use [`decode_from_read_unbuffered_with`].
206///
207/// # Errors
208///
209/// Returns [`ReadError::Decode`] if the decoder encounters an error while parsing the data, or
210/// [`ReadError::Io`] if an I/O error occurs while reading.
211#[cfg(feature = "std")]
212pub fn decode_from_read_unbuffered<T, R>(
213    reader: R,
214) -> Result<T, ReadError<<T::Decoder as Decoder>::Error>>
215where
216    T: Decodable,
217    R: std::io::Read,
218{
219    decode_from_read_unbuffered_with::<T, R, 4096>(reader)
220}
221
222/// Decodes an object from an unbuffered reader using a custom-sized buffer.
223///
224/// For most use cases, prefer [`decode_from_read`] with a [`std::io::BufReader`]. This function is
225/// only needed when you have an unbuffered reader which you cannot wrap. It will probably have
226/// worse performance.
227///
228/// # Buffer
229///
230/// The `BUFFER_SIZE` parameter controls the intermediate buffer size used for reading. The buffer
231/// is allocated on the stack (not heap) and reused across read operations. Larger buffers reduce
232/// the number of system calls, but use more memory.
233///
234/// # Errors
235///
236/// Returns [`ReadError::Decode`] if the decoder encounters an error while parsing the data, or
237/// [`ReadError::Io`] if an I/O error occurs while reading.
238#[cfg(feature = "std")]
239pub fn decode_from_read_unbuffered_with<T, R, const BUFFER_SIZE: usize>(
240    mut reader: R,
241) -> Result<T, ReadError<<T::Decoder as Decoder>::Error>>
242where
243    T: Decodable,
244    R: std::io::Read,
245{
246    let mut decoder = T::decoder();
247    let mut buffer = [0u8; BUFFER_SIZE];
248
249    while decoder.read_limit() > 0 {
250        // Only read what we need, up to buffer size.
251        let clamped_buffer = &mut buffer[..decoder.read_limit().min(BUFFER_SIZE)];
252        match reader.read(clamped_buffer) {
253            Ok(0) => {
254                // EOF, but still try to finalize the decoder.
255                return decoder.end().map_err(ReadError::Decode);
256            }
257            Ok(bytes_read) => {
258                if !decoder
259                    .push_bytes(&mut &clamped_buffer[..bytes_read])
260                    .map_err(ReadError::Decode)?
261                {
262                    return decoder.end().map_err(ReadError::Decode);
263                }
264            }
265            Err(ref e) if e.kind() == std::io::ErrorKind::Interrupted => {
266                // Auto retry read for non-fatal error.
267            }
268            Err(e) => return Err(ReadError::Io(e)),
269        }
270    }
271
272    decoder.end().map_err(ReadError::Decode)
273}