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 in a consensus-consistent way,
6//! using a *sans-I/O* 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//!
13//! *Consensus* encoding is the canonical byte representation of Bitcoin data types used across the
14//! peer-to-peer network and transaction serialization. This crate only supports deterministic
15//! encoding and will never support types like floats whose encoding is non-deterministic or
16//! platform-dependent.
17//!
18//! # Encoding
19//!
20//! Types implement [`Encode`] to produce an [`Encoder`], which yields encoded bytes in chunks
21//! via [`Encoder::current_chunk`] and [`Encoder::advance`]. The caller drives the process by
22//! pulling chunks until `advance` returns [`EncoderStatus::Finished`].
23//!
24//! # Decoding
25//!
26//! Types implement [`Decode`] to produce a [`Decoder`], which consumes bytes via
27//! [`Decoder::push_bytes`] until it signals completion by returning `Ok(DecoderStatus::Ready)`. The
28//! caller then calls [`Decoder::end`] to obtain the decoded value.
29//!
30//! Unlike encoding, decoding is fallible. Both `push_bytes` and `end` return `Result`. I/O errors
31//! are handled by the caller, keeping the codec logic I/O-agnostic.
32//!
33//! # Drivers
34//!
35//! This crate provides free functions which drive codecs for common I/O interfaces. On the decoding
36//! side we provide:
37//!
38//! * [`decode_from_read`]: Decode from a stdlib buffered reader.
39//! * [`decode_from_read_unbuffered`]: Decode from a stdlib unbuffered reader (4k buffer on stack).
40//! * [`decode_from_read_unbuffered_with`]: As above with custom sized stack-allocated buffer.
41//! * [`decode_from_slice`]: Decode from a byte slice (errors if slice is not completely consumed).
42//! * [`decode_from_slice_unbounded`]: Slice can contain additional data after decoding completes.
43//! * [`decode_from_hex`]: Decode from a hex string without heap allocations.
44//!
45//! Each function above takes a type parameter `T: Decode` to select the output type and its
46//! associated decoder. The following variants instead accept a [`Decoder`] type directly,
47//! instantiated with [`Default`], and can be used when the output type does not implement [`Decode`]:
48//!
49//! * [`decode_from_read_with_decoder`]: Counterpart to [`decode_from_read`].
50//! * [`decode_from_slice_with_decoder`]: Counterpart to [`decode_from_slice`].
51//! * [`decode_from_slice_unbounded_with_decoder`]: Counterpart to [`decode_from_slice_unbounded`].
52//! * [`decode_from_hex_with_decoder`]: Counterpart to [`decode_from_hex`].
53//!
54//! And on the encoding side we provide:
55//!
56//! * [`encode_to_writer`]: Encode to a stdlib writer.
57//! * [`drain_to_writer`]: Drain an encoder to a stdlib writer.
58//! * [`encode_to_vec`]: Encode to the heap.
59//! * [`drain_to_vec`]: Drain an encoder to the heap.
60//! * [`encode_to_hex`]: Encode to a hex string.
61//! * [`drain_to_hex`]: Drain an encoder to a hex string.
62//!
63//! # Feature Flags
64//!
65//! * `std` - Enables std lib I/O driver functions and `std::error::Error` impls (implies `alloc`).
66//! * `alloc` - Enables [`encode_to_vec`], `Vec`-based decoders, and allocation-based helpers.
67//! * `hex` - Enables [`decode_from_hex`], [`decode_from_hex_with_decoder`], [`encode_to_hex`] and
68//! [`drain_to_hex`]. Encoding also requires `alloc`.
69
70#![no_std]
71// Coding conventions.
72#![warn(missing_docs)]
73#![warn(deprecated_in_future)]
74#![doc(test(attr(warn(unused))))]
75
76#[cfg(feature = "alloc")]
77extern crate alloc;
78#[cfg(feature = "std")]
79extern crate std;
80
81#[cfg(feature = "hex")]
82pub extern crate hex;
83#[cfg(feature = "serde")]
84pub extern crate serde;
85
86mod compact_size;
87mod decode;
88mod encode;
89
90pub mod error;
91#[cfg(feature = "serde")]
92pub mod serde_as_consensus;
93
94#[doc(inline)]
95pub use self::compact_size::{CompactSizeDecoder, CompactSizeEncoder, CompactSizeU64Decoder};
96#[doc(inline)]
97pub use self::decode::decoders::{ArrayDecoder, Decoder2, Decoder3, Decoder4, Decoder6};
98#[cfg(feature = "alloc")]
99#[doc(inline)]
100pub use self::decode::decoders::{ByteVecDecoder, VecDecoder};
101#[doc(inline)]
102pub use self::decode::{
103 check_decode, check_decoder, decode_from_slice, decode_from_slice_unbounded,
104 decode_from_slice_unbounded_with_decoder, decode_from_slice_with_decoder, Decode, Decoder,
105 DecoderStatus,
106};
107#[cfg(feature = "hex")]
108#[doc(inline)]
109pub use self::decode::{decode_from_hex, decode_from_hex_with_decoder};
110#[cfg(feature = "std")]
111#[doc(inline)]
112pub use self::decode::{
113 decode_from_read, decode_from_read_unbuffered, decode_from_read_unbuffered_with,
114 decode_from_read_with_decoder,
115};
116#[doc(inline)]
117pub use self::encode::encoders::{
118 ArrayEncoder, ArrayRefEncoder, BytesEncoder, Encoder2, Encoder3, Encoder4, Encoder6,
119 PrefixedBytesEncoder, PrefixedSliceEncoder, SliceEncoder,
120};
121#[doc(inline)]
122pub use self::encode::{
123 check_encode, check_encoder, Encode, Encoder, EncoderByteIter, EncoderStatus, ExactSizeEncoder,
124};
125#[cfg(feature = "alloc")]
126#[cfg(feature = "hex")]
127#[doc(inline)]
128pub use self::encode::{drain_to_hex, encode_to_hex};
129#[cfg(feature = "alloc")]
130#[doc(inline)]
131pub use self::encode::{drain_to_vec, encode_to_vec};
132#[cfg(feature = "std")]
133#[doc(inline)]
134pub use self::encode::{drain_to_writer, encode_to_writer};
135#[cfg(feature = "hex")]
136#[doc(no_inline)]
137pub use self::error::FromHexError;
138#[cfg(feature = "alloc")]
139#[doc(no_inline)]
140pub use self::error::LengthPrefixExceedsMaxError;
141#[cfg(feature = "std")]
142#[doc(no_inline)]
143pub use self::error::ReadError;
144#[cfg(feature = "alloc")]
145#[doc(no_inline)]
146pub use self::error::{ByteVecDecoderError, VecDecoderError};
147#[doc(no_inline)]
148pub use self::error::{
149 CompactSizeDecoderError, DecodeError, Decoder2Error, Decoder3Error, Decoder4Error,
150 Decoder6Error, UnconsumedError, UnexpectedEofError,
151};