Skip to main content

bitcoin_consensus_encoding/
lib.rs

1// SPDX-License-Identifier: CC0-1.0
2
3//! # Rust Bitcoin Consensus Encoding
4//!
5//! Traits and utilities for encoding and decoding Bitcoin data types using a *sans-I/O*
6//! architecture.
7//!
8//! Rather than reading from or writing to [`std::io::Read`]/[`std::io::Write`] traits directly, the
9//! codec types work with byte slices. This keeps codec logic I/O-agnostic, so the same
10//! implementation works in `no_std` environments, sync I/O, async I/O, and hash engines without
11//! duplicating logic or surfacing I/O errors in non-I/O contexts (e.g. when hashing an encoding).
12//! This crate only supports deterministic encoding and will never support types like floats whose
13//! encoding is non-deterministic or platform-dependent.
14//!
15//! *Consensus* encoding is the canonical byte representation of Bitcoin data types used across the
16//! peer-to-peer network and transaction serialization. Bitcoin types which support consensus
17//! encoding implement the [`Encode`] and [`Decode`] traits.
18//!
19//! # Encoding
20//!
21//! Consensus encodable types implement [`Encode`] to produce an [`Encoder`], which yields encoded
22//! bytes in chunks via [`Encoder::current_chunk`] and [`Encoder::advance`]. The caller drives the
23//! process by pulling chunks until `advance` returns [`EncoderStatus::Finished`].
24//!
25//! # Decoding
26//!
27//! Consensus encodable types implement [`Decode`] to produce a [`Decoder`], which consumes bytes
28//! via [`Decoder::push_bytes`] until it signals completion by returning `Ok(DecoderStatus::Ready)`.
29//! The caller then calls [`Decoder::end`] to obtain the decoded value.
30//!
31//! Unlike encoding, decoding is fallible. Both `push_bytes` and `end` return `Result`. I/O errors
32//! are handled by the caller, keeping the codec logic I/O-agnostic.
33//!
34//! # Drivers
35//!
36//! This crate provides free functions which drive codecs for common I/O interfaces. On the decoding
37//! side we provide functions which take a consensus encodable type parameter `T: Decode` to select
38//! the output type's associated decoder.
39//!
40//! * [`decode_from_read`]: Decode from a stdlib buffered reader.
41//! * [`decode_from_read_unbuffered`]: Decode from a stdlib unbuffered reader (4k buffer on stack).
42//! * [`decode_from_read_unbuffered_with`]: As above with custom sized stack-allocated buffer.
43//! * [`decode_from_slice`]: Decode from a byte slice (errors if slice is not completely consumed).
44//! * [`decode_from_slice_unbounded`]: Slice can contain additional data after decoding completes.
45//! * [`decode_from_hex`]: Decode from a hex string without heap allocations.
46//!
47//! The following variants instead accept an agnostic [`Decoder`] type directly, instantiated with
48//! [`Default`], and can be used when the output type does not implement [`Decode`]:
49//!
50//! * [`decode_from_read_with_decoder`]: Counterpart to [`decode_from_read`].
51//! * [`decode_from_slice_with_decoder`]: Counterpart to [`decode_from_slice`].
52//! * [`decode_from_slice_unbounded_with_decoder`]: Counterpart to [`decode_from_slice_unbounded`].
53//! * [`decode_from_hex_with_decoder`]: Counterpart to [`decode_from_hex`].
54//!
55//! And on the encoding side we provide similar functions for consensus encodable types.
56//!
57//! * [`encode_to_writer`]: Encode to a stdlib writer.
58//! * [`encode_to_vec`]: Encode to the heap.
59//! * [`encode_to_hex`]: Encode to a hex string.
60//!
61//! As well as variants for agnostic [`Encoder`] types.
62//!
63//! * [`drain_to_writer`]: Drain an encoder to a stdlib writer.
64//! * [`drain_to_vec`]: Drain an encoder to the heap.
65//! * [`drain_to_hex`]: Drain an encoder to a hex string.
66//!
67//! # Collections
68//!
69//! This crate provides types for encoding and decoding sequences of items. On the decoding side,
70//! [`VecDecoder`] decodes a length-prefixed sequence of consensus encodable types into a `Vec`.
71//! [`VecDecoderWith`] and [`ExactVecDecoderWith`] are the underlying implementations, bound
72//! directly on [`Decoder`] allowing them to be used with decoder types that do not have a
73//! corresponding [`Decode`] implementation.
74//!
75//! On the encoding side, [`SliceEncoder`] and [`PrefixedSliceEncoder`] encode slices of consensus
76//! encodable types without and with a compact-size length prefix respectively.
77//!
78//! The lower-level [`IterEncoder`] drives any iterator whose items implement [`Encoder`].
79//!
80//! # Feature Flags
81//!
82//! * `std` - Enables std lib I/O driver functions and `std::error::Error` impls (implies `alloc`).
83//! * `alloc` - Enables [`encode_to_vec`], `Vec`-based decoders, and allocation-based helpers.
84//! * `hex` - Enables [`decode_from_hex`], [`decode_from_hex_with_decoder`], [`encode_to_hex`] and
85//!   [`drain_to_hex`]. Encoding also requires `alloc`.
86
87#![no_std]
88// Coding conventions.
89#![warn(missing_docs)]
90#![warn(deprecated_in_future)]
91#![doc(test(attr(warn(unused))))]
92
93#[cfg(feature = "alloc")]
94extern crate alloc;
95#[cfg(feature = "std")]
96extern crate std;
97
98#[cfg(feature = "hex")]
99pub extern crate hex;
100#[cfg(feature = "serde")]
101pub extern crate serde;
102
103mod compact_size;
104mod decode;
105mod encode;
106
107pub mod error;
108#[cfg(feature = "serde")]
109pub mod serde_as_consensus;
110
111#[doc(inline)]
112pub use self::compact_size::{CompactSizeDecoder, CompactSizeEncoder, CompactSizeU64Decoder};
113#[doc(inline)]
114pub use self::decode::decoders::{ArrayDecoder, Decoder2, Decoder3, Decoder4, Decoder6};
115#[cfg(feature = "alloc")]
116#[doc(inline)]
117pub use self::decode::decoders::{ByteVecDecoder, ExactVecDecoderWith, VecDecoder, VecDecoderWith};
118#[doc(inline)]
119pub use self::decode::{
120    check_decode, check_decoder, decode_from_slice, decode_from_slice_unbounded,
121    decode_from_slice_unbounded_with_decoder, decode_from_slice_with_decoder, Decode, Decoder,
122    DecoderStatus,
123};
124#[cfg(feature = "hex")]
125#[doc(inline)]
126pub use self::decode::{decode_from_hex, decode_from_hex_with_decoder};
127#[cfg(feature = "std")]
128#[doc(inline)]
129pub use self::decode::{
130    decode_from_read, decode_from_read_unbuffered, decode_from_read_unbuffered_with,
131    decode_from_read_with_decoder,
132};
133#[doc(inline)]
134pub use self::encode::encoders::{
135    ArrayEncoder, ArrayRefEncoder, BytesEncoder, Encoder2, Encoder3, Encoder4, Encoder6,
136    PrefixedBytesEncoder, PrefixedSliceEncoder, SliceEncoder,
137};
138#[doc(inline)]
139pub use self::encode::iter::IterEncoder;
140#[doc(inline)]
141pub use self::encode::{
142    check_encode, check_encoder, Encode, Encoder, EncoderByteIter, EncoderStatus, ExactSizeEncoder,
143};
144#[cfg(feature = "alloc")]
145#[cfg(feature = "hex")]
146#[doc(inline)]
147pub use self::encode::{drain_to_hex, encode_to_hex};
148#[cfg(feature = "alloc")]
149#[doc(inline)]
150pub use self::encode::{drain_to_vec, encode_to_vec};
151#[cfg(feature = "std")]
152#[doc(inline)]
153pub use self::encode::{drain_to_writer, encode_to_writer};
154#[cfg(feature = "hex")]
155#[doc(no_inline)]
156pub use self::error::FromHexError;
157#[cfg(feature = "alloc")]
158#[doc(no_inline)]
159pub use self::error::LengthPrefixExceedsMaxError;
160#[cfg(feature = "std")]
161#[doc(no_inline)]
162pub use self::error::ReadError;
163#[cfg(feature = "alloc")]
164#[doc(no_inline)]
165pub use self::error::{ByteVecDecoderError, VecDecoderError};
166#[doc(no_inline)]
167pub use self::error::{
168    CompactSizeDecoderError, DecodeError, Decoder2Error, Decoder3Error, Decoder4Error,
169    Decoder6Error, UnconsumedError, UnexpectedEofError,
170};