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 = "hex")]
8use crate::error::{FromHexError, FromHexErrorInner};
9#[cfg(feature = "std")]
10use crate::ReadError;
11use crate::{DecodeError, UnconsumedError};
12
13/// A Bitcoin object which can be consensus-decoded using a push decoder.
14///
15/// To decode something, create a [`Self::Decoder`] and push byte slices into it with
16/// [`Decoder::push_bytes`], then call [`Decoder::end`] to get the result.
17///
18/// # Examples
19///
20/// ```
21/// use bitcoin_consensus_encoding::{decode_from_slice, Decode, Decoder, DecoderStatus, ArrayDecoder, UnexpectedEofError};
22///
23/// struct Foo([u8; 4]);
24///
25/// #[derive(Default)]
26/// struct FooDecoder(ArrayDecoder<4>);
27///
28/// impl Decoder for FooDecoder {
29/// type Output = Foo;
30/// type Error = UnexpectedEofError;
31///
32/// fn push_bytes(&mut self, bytes: &mut &[u8]) -> Result<DecoderStatus, Self::Error> {
33/// self.0.push_bytes(bytes)
34/// }
35/// fn end(self) -> Result<Self::Output, Self::Error> { self.0.end().map(Foo) }
36/// fn read_limit(&self) -> usize { self.0.read_limit() }
37/// }
38///
39/// impl Decode for Foo {
40/// type Decoder = FooDecoder;
41/// }
42///
43/// let foo: Foo = decode_from_slice(&[0xde, 0xad, 0xbe, 0xef]).unwrap();
44/// assert_eq!(foo.0, [0xde, 0xad, 0xbe, 0xef]);
45/// ```
46pub trait Decode {
47 /// Associated decoder for the type.
48 type Decoder: Decoder<Output = Self> + Default;
49
50 /// Constructs a "default decoder" for the type.
51 fn decoder() -> Self::Decoder { Self::Decoder::default() }
52}
53
54/// A push decoder for a consensus-decodable object.
55pub trait Decoder: Sized {
56 /// The type that this decoder produces when decoding is complete.
57 type Output;
58 /// The error type that this decoder can produce.
59 type Error;
60
61 /// Pushes bytes into the decoder, consuming as much as possible.
62 ///
63 /// The slice reference will be advanced to point to the unconsumed portion. Returns
64 /// `Ok(DecoderStatus::NeedsMore)` if more bytes are needed to complete decoding,
65 /// `Ok(DecoderStatus::Ready)` if the decoder is ready to finalize with [`Self::end`], or
66 /// `Err(error)` if parsing failed.
67 ///
68 /// Once the decoder returns `Ok(DecoderStatus::Ready)`, subsequent calls to this method will
69 /// continue to return `Ok(DecoderStatus::Ready)` without consuming additional bytes.
70 ///
71 /// # Errors
72 ///
73 /// Returns an error if the provided bytes are invalid or malformed according to the decoder's
74 /// validation rules. Insufficient data (needing more bytes) is *not* an error for this method,
75 /// the decoder will simply consume what it can and return `DecoderStatus::NeedsMore` to
76 /// indicate more data is needed.
77 ///
78 /// # Panics
79 ///
80 /// May panic if called after a previous call to [`Self::push_bytes`] errored.
81 #[must_use = "must check result to avoid panics on subsequent calls"]
82 #[track_caller]
83 fn push_bytes(&mut self, bytes: &mut &[u8]) -> Result<DecoderStatus, Self::Error>;
84
85 /// Completes the decoding process and returns the final result.
86 ///
87 /// This consumes the decoder and should be called when no more input data is available.
88 ///
89 /// # Errors
90 ///
91 /// Returns an error if the decoder has not received sufficient data to complete decoding, or if
92 /// the accumulated data is invalid when considered as a complete object.
93 ///
94 /// # Panics
95 ///
96 /// May panic if called after a previous call to [`Self::push_bytes`] errored.
97 #[must_use = "must check result to avoid panics on subsequent calls"]
98 #[track_caller]
99 fn end(self) -> Result<Self::Output, Self::Error>;
100
101 /// Returns the maximum number of bytes this decoder can consume without over-reading.
102 ///
103 /// Returns 0 if the decoder is complete and ready to finalize with [`Self::end`]. This is used
104 /// by [`decode_from_read_unbuffered`] to optimize read sizes, avoiding both inefficient
105 /// under-reads and unnecessary over-reads.
106 fn read_limit(&self) -> usize;
107}
108
109/// Indicates whether a decoder needs more data or is ready to finalize.
110///
111/// This is returned from the [`Decoder::push_bytes`] method to indicate whether the decoder
112/// should continue accumulating data or is ready to produce the decoded value with [`Decoder::end`].
113#[derive(Debug, Copy, Clone, Eq, PartialEq)]
114pub enum DecoderStatus {
115 /// The decoder needs more data to complete decoding.
116 ///
117 /// Continue pushing byte slices with [`Decoder::push_bytes`] until this status changes to
118 /// [`Ready`](DecoderStatus::Ready).
119 NeedsMore,
120
121 /// The decoder has accumulated sufficient data and is ready to finalize.
122 ///
123 /// Call [`Decoder::end`] to complete the decoding process and obtain the final result.
124 Ready,
125}
126
127impl DecoderStatus {
128 /// Returns `true` if the decoder needs more data to continue.
129 pub fn needs_more(&self) -> bool { matches!(self, Self::NeedsMore) }
130
131 /// Returns `true` if ready to produce decoded value with [`Decoder::end`].
132 pub fn is_ready(&self) -> bool { matches!(self, Self::Ready) }
133}
134
135/// Decodes an object from a hex string without heap allocations.
136///
137/// # Errors
138///
139/// [`FromHexError`] if the string has an odd number of characters, any character is not a
140/// valid hex digit, or if decoding the type fails, including if bytes remain unconsumed
141/// after the decoder completes.
142#[cfg(feature = "hex")]
143pub fn decode_from_hex<T: Decode>(
144 hex: &str,
145) -> Result<T, FromHexError<<T::Decoder as Decoder>::Error>> {
146 decode_from_hex_internal(hex, T::decoder())
147}
148
149/// Decodes an object from a hex string without heap allocations using a [`Decoder`] type.
150///
151/// Unlike [`decode_from_hex`], this takes a generic [`Decoder`] parameter, allowing use with
152/// decoders which don't have a dedicated [`Decode`] implementer (e.g. [`CompactSizeDecoder`]).
153///
154/// # Errors
155///
156/// [`FromHexError`] if the string has an odd number of characters, any character is not a
157/// valid hex digit, or if decoding the type fails, including if bytes remain unconsumed
158/// after the decoder completes.
159///
160/// [`CompactSizeDecoder`]: crate::CompactSizeDecoder
161#[cfg(feature = "hex")]
162pub fn decode_from_hex_with_decoder<D: Decoder + Default>(
163 hex: &str,
164) -> Result<D::Output, FromHexError<D::Error>> {
165 decode_from_hex_internal(hex, D::default())
166}
167
168#[cfg(feature = "hex")]
169fn decode_from_hex_internal<D: Decoder>(
170 hex: &str,
171 mut decoder: D,
172) -> Result<D::Output, FromHexError<D::Error>> {
173 let iter = hex::HexSliceToBytesIter::new(hex)
174 .map_err(FromHexErrorInner::OddLength)
175 .map_err(FromHexError)?;
176
177 let mut buffer = [0u8; 4096];
178 let mut index = 0;
179
180 for item in iter {
181 let byte = item.map_err(FromHexErrorInner::InvalidChar).map_err(FromHexError)?;
182
183 if index == buffer.len() {
184 let mut to_flush = buffer.as_slice();
185 // There is at least a single byte left after flushing the buffer. Error if the decoder
186 // is ready after flush.
187 while !to_flush.is_empty() {
188 if decoder
189 .push_bytes(&mut to_flush)
190 .map_err(|e| FromHexError(FromHexErrorInner::Decode(DecodeError::Parse(e))))?
191 .is_ready()
192 {
193 return Err(FromHexError(FromHexErrorInner::Decode(DecodeError::Unconsumed(
194 UnconsumedError(),
195 ))));
196 }
197 }
198 index = 0;
199 }
200 buffer[index] = byte;
201 index += 1;
202 }
203
204 let mut to_flush = &buffer[..index];
205 while !to_flush.is_empty() {
206 if decoder
207 .push_bytes(&mut to_flush)
208 .map_err(|e| FromHexError(FromHexErrorInner::Decode(DecodeError::Parse(e))))?
209 .is_ready()
210 {
211 break;
212 }
213 }
214
215 if to_flush.is_empty() {
216 decoder.end().map_err(|e| FromHexError(FromHexErrorInner::Decode(DecodeError::Parse(e))))
217 } else {
218 Err(FromHexError(FromHexErrorInner::Decode(DecodeError::Unconsumed(UnconsumedError()))))
219 }
220}
221
222/// Decodes an object from a byte slice.
223///
224/// # Errors
225///
226/// Returns an error if the decoder encounters an error while parsing the data, including
227/// insufficient data. This function also errors if the provided slice is not completely consumed
228/// during decode.
229pub fn decode_from_slice<T: Decode>(
230 bytes: &[u8],
231) -> Result<T, DecodeError<<T::Decoder as Decoder>::Error>> {
232 decode_from_slice_internal(bytes, T::decoder())
233}
234
235/// Decodes an object from a byte slice using a [`Decoder`] type.
236///
237/// Unlike [`decode_from_slice`], this takes a generic [`Decoder`] parameter, allowing use with
238/// decoders which don't have a dedicated [`Decode`] implementer (e.g. [`CompactSizeDecoder`]).
239///
240/// # Errors
241///
242/// Returns an error if the decoder encounters an error while parsing the data, including
243/// insufficient data. This function also errors if the provided slice is not completely consumed
244/// during decode.
245///
246/// [`CompactSizeDecoder`]: crate::CompactSizeDecoder
247pub fn decode_from_slice_with_decoder<D: Decoder + Default>(
248 bytes: &[u8],
249) -> Result<D::Output, DecodeError<D::Error>> {
250 decode_from_slice_internal(bytes, D::default())
251}
252
253fn decode_from_slice_internal<D: Decoder>(
254 bytes: &[u8],
255 decoder: D,
256) -> Result<D::Output, DecodeError<D::Error>> {
257 let mut remaining = bytes;
258 let data = decode_from_slice_unbounded_internal(&mut remaining, decoder)
259 .map_err(DecodeError::Parse)?;
260
261 if remaining.is_empty() {
262 Ok(data)
263 } else {
264 Err(DecodeError::Unconsumed(UnconsumedError()))
265 }
266}
267
268/// Decodes an object from an unbounded byte slice.
269///
270/// Unlike [`decode_from_slice`], this function will not error if the slice contains additional
271/// bytes that are not required to decode. Furthermore, the byte slice reference provided to this
272/// function will be updated based on the consumed data, returning the unconsumed bytes.
273///
274/// # Errors
275///
276/// Returns an error if the decoder encounters an error while parsing the data, including
277/// insufficient data.
278pub fn decode_from_slice_unbounded<T>(
279 bytes: &mut &[u8],
280) -> Result<T, <T::Decoder as Decoder>::Error>
281where
282 T: Decode,
283{
284 decode_from_slice_unbounded_internal(bytes, T::decoder())
285}
286
287/// Decodes an object from an unbounded byte slice using a [`Decoder`] type.
288///
289/// Unlike [`decode_from_slice_unbounded`], this takes a generic [`Decoder`] parameter, allowing
290/// use with decoders which don't have a dedicated [`Decode`] implementer
291/// (e.g. [`CompactSizeDecoder`]).
292///
293/// Unlike [`decode_from_slice_with_decoder`], this function will not error if the slice contains
294/// additional bytes that are not required to decode. Furthermore, the byte slice reference provided
295/// to this function will be updated based on the consumed data, returning the unconsumed bytes.
296///
297/// # Errors
298///
299/// Returns an error if the decoder encounters an error while parsing the data, including
300/// insufficient data.
301///
302/// [`CompactSizeDecoder`]: crate::CompactSizeDecoder
303pub fn decode_from_slice_unbounded_with_decoder<D: Decoder + Default>(
304 bytes: &mut &[u8],
305) -> Result<D::Output, D::Error> {
306 decode_from_slice_unbounded_internal(bytes, D::default())
307}
308
309fn decode_from_slice_unbounded_internal<D: Decoder>(
310 bytes: &mut &[u8],
311 mut decoder: D,
312) -> Result<D::Output, D::Error> {
313 while !bytes.is_empty() {
314 if decoder.push_bytes(bytes)?.is_ready() {
315 break;
316 }
317 }
318
319 decoder.end()
320}
321
322/// Decodes an object from a buffered reader.
323///
324/// # Performance
325///
326/// For unbuffered readers (like [`std::fs::File`] or [`std::net::TcpStream`]), consider wrapping
327/// your reader with [`std::io::BufReader`] in order to use this function. This avoids frequent
328/// small reads, which can significantly impact performance.
329///
330/// # Errors
331///
332/// Returns [`ReadError::Decode`] if the decoder encounters an error while parsing the data, or
333/// [`ReadError::Io`] if an I/O error occurs while reading.
334#[cfg(feature = "std")]
335pub fn decode_from_read<T, R>(reader: R) -> Result<T, ReadError<<T::Decoder as Decoder>::Error>>
336where
337 T: Decode,
338 R: std::io::BufRead,
339{
340 decode_from_read_internal::<T::Decoder, R>(reader, T::decoder())
341}
342
343/// Decodes an object from a buffered reader using a [`Decoder`] type.
344///
345/// Unlike [`decode_from_read`], this takes a generic [`Decoder`] parameter, allowing use with
346/// decoders which don't have a dedicated [`Decode`] implementer (e.g. [`CompactSizeDecoder`]).
347///
348/// # Performance
349///
350/// For unbuffered readers (like [`std::fs::File`] or [`std::net::TcpStream`]), consider wrapping
351/// your reader with [`std::io::BufReader`] in order to use this function. This avoids frequent
352/// small reads, which can significantly impact performance.
353///
354/// # Errors
355///
356/// Returns [`ReadError::Decode`] if the decoder encounters an error while parsing the data, or
357/// [`ReadError::Io`] if an I/O error occurs while reading.
358///
359/// [`CompactSizeDecoder`]: crate::CompactSizeDecoder
360#[cfg(feature = "std")]
361pub fn decode_from_read_with_decoder<D, R>(reader: R) -> Result<D::Output, ReadError<D::Error>>
362where
363 D: Decoder + Default,
364 R: std::io::BufRead,
365{
366 decode_from_read_internal(reader, D::default())
367}
368
369#[cfg(feature = "std")]
370fn decode_from_read_internal<D, R>(
371 mut reader: R,
372 mut decoder: D,
373) -> Result<D::Output, ReadError<D::Error>>
374where
375 D: Decoder,
376 R: std::io::BufRead,
377{
378 loop {
379 let mut buffer = match reader.fill_buf() {
380 Ok(buffer) => buffer,
381 // Auto retry read for non-fatal error.
382 Err(error) if error.kind() == std::io::ErrorKind::Interrupted => continue,
383 Err(error) => return Err(ReadError::Io(error)),
384 };
385
386 if buffer.is_empty() {
387 // EOF, but still try to finalize the decoder.
388 return decoder.end().map_err(ReadError::Decode);
389 }
390
391 let original_len = buffer.len();
392 let status = decoder.push_bytes(&mut buffer).map_err(ReadError::Decode)?;
393 let consumed = original_len - buffer.len();
394 reader.consume(consumed);
395
396 if status.is_ready() {
397 return decoder.end().map_err(ReadError::Decode);
398 }
399 }
400}
401
402/// Decodes an object from an unbuffered reader using a fixed-size buffer.
403///
404/// For most use cases, prefer [`decode_from_read`] with a [`std::io::BufReader`]. This function is
405/// only needed when you have an unbuffered reader which you cannot wrap. It will probably have
406/// worse performance.
407///
408/// # Buffer
409///
410/// Uses a fixed 4KB (4096 bytes) stack-allocated buffer that is reused across read operations. This
411/// size is a good balance between memory usage and system call efficiency for most use cases.
412///
413/// For different buffer sizes, use [`decode_from_read_unbuffered_with`].
414///
415/// # Errors
416///
417/// Returns [`ReadError::Decode`] if the decoder encounters an error while parsing the data, or
418/// [`ReadError::Io`] if an I/O error occurs while reading.
419#[cfg(feature = "std")]
420pub fn decode_from_read_unbuffered<T, R>(
421 reader: R,
422) -> Result<T, ReadError<<T::Decoder as Decoder>::Error>>
423where
424 T: Decode,
425 R: std::io::Read,
426{
427 decode_from_read_unbuffered_with::<T, R, 4096>(reader)
428}
429
430/// Decodes an object from an unbuffered reader using a custom-sized buffer.
431///
432/// For most use cases, prefer [`decode_from_read`] with a [`std::io::BufReader`]. This function is
433/// only needed when you have an unbuffered reader which you cannot wrap. It will probably have
434/// worse performance.
435///
436/// # Buffer
437///
438/// The `BUFFER_SIZE` parameter controls the intermediate buffer size used for reading. The buffer
439/// is allocated on the stack (not heap) and reused across read operations. Larger buffers reduce
440/// the number of system calls, but use more memory.
441///
442/// # Errors
443///
444/// Returns [`ReadError::Decode`] if the decoder encounters an error while parsing the data, or
445/// [`ReadError::Io`] if an I/O error occurs while reading.
446#[cfg(feature = "std")]
447pub fn decode_from_read_unbuffered_with<T, R, const BUFFER_SIZE: usize>(
448 mut reader: R,
449) -> Result<T, ReadError<<T::Decoder as Decoder>::Error>>
450where
451 T: Decode,
452 R: std::io::Read,
453{
454 let mut decoder = T::decoder();
455 let mut buffer = [0u8; BUFFER_SIZE];
456
457 while decoder.read_limit() > 0 {
458 // Only read what we need, up to buffer size.
459 let clamped_buffer = &mut buffer[..decoder.read_limit().min(BUFFER_SIZE)];
460 match reader.read(clamped_buffer) {
461 Ok(0) => {
462 // EOF, but still try to finalize the decoder.
463 return decoder.end().map_err(ReadError::Decode);
464 }
465 Ok(bytes_read) => {
466 let mut to_push = &clamped_buffer[..bytes_read];
467 while !to_push.is_empty() {
468 if decoder.push_bytes(&mut to_push).map_err(ReadError::Decode)?.is_ready() {
469 return decoder.end().map_err(ReadError::Decode);
470 }
471 }
472 }
473 Err(ref e) if e.kind() == std::io::ErrorKind::Interrupted => {
474 // Auto retry read for non-fatal error.
475 }
476 Err(e) => return Err(ReadError::Io(e)),
477 }
478 }
479
480 decoder.end().map_err(ReadError::Decode)
481}
482
483/// Checks that the given bytes decode to the expected value, panicking if they don't.
484///
485/// This is intended for tests only.
486///
487/// # Panics
488///
489/// If the decoded value doesn't match the expected value, or if decoding fails.
490#[track_caller]
491pub fn check_decode<T: Decode + Eq + core::fmt::Debug>(bytes: &[u8], expected: &T)
492where
493 <T::Decoder as Decoder>::Error: core::fmt::Debug,
494{
495 let decoder = T::decoder();
496 check_decoder(decoder, bytes, expected);
497}
498
499/// Checks that the given `decoder` produces the expected value, panicking if it doesn't.
500///
501/// This is intended for tests only.
502///
503/// # Panics
504///
505/// If the decoder doesn't produce the expected value or if decoding fails.
506#[track_caller]
507pub fn check_decoder<D: Decoder>(mut decoder: D, mut bytes: &[u8], expected: &D::Output)
508where
509 D::Output: Eq + core::fmt::Debug,
510 D::Error: core::fmt::Debug,
511{
512 loop {
513 match decoder.push_bytes(&mut bytes) {
514 Ok(status) => {
515 if status.is_ready() {
516 break;
517 }
518 assert!(!bytes.is_empty(), "decoder needs more data but no bytes remaining");
519 }
520 Err(e) => panic!("decoder failed with error: {e:?}"),
521 }
522 }
523
524 match decoder.end() {
525 Ok(result) => {
526 assert_eq!(&result, expected, "decoded value doesn't match expected value");
527 }
528 Err(e) => panic!("decoder finalization failed with error: {e:?}"),
529 }
530}