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