bitcoin_consensus_encoding/encode/mod.rs
1// SPDX-License-Identifier: CC0-1.0
2
3//! Consensus Encoding Traits
4
5#[cfg(feature = "alloc")]
6use alloc::vec::Vec;
7
8pub mod encoders;
9
10/// A Bitcoin object which can be consensus-encoded.
11///
12/// To encode something, use the [`Self::encoder`] method to obtain a [`Self::Encoder`], which will
13/// behave like an iterator yielding byte slices.
14///
15/// # Examples
16///
17/// ```
18/// # #[cfg(feature = "alloc")] {
19/// use bitcoin_consensus_encoding::{encoder_newtype, encode_to_vec, Encodable, ArrayEncoder};
20///
21/// struct Foo([u8; 4]);
22///
23/// encoder_newtype! {
24/// pub struct FooEncoder<'e>(ArrayEncoder<4>);
25/// }
26///
27/// impl Encodable for Foo {
28/// type Encoder<'e> = FooEncoder<'e> where Self: 'e;
29///
30/// fn encoder(&self) -> Self::Encoder<'_> {
31/// FooEncoder::new(ArrayEncoder::without_length_prefix(self.0))
32/// }
33/// }
34///
35/// let foo = Foo([0xde, 0xad, 0xbe, 0xef]);
36/// assert_eq!(encode_to_vec(&foo), vec![0xde, 0xad, 0xbe, 0xef]);
37/// # }
38/// ```
39pub trait Encodable {
40 /// The encoder associated with this type. Conceptually, the encoder is like
41 /// an iterator which yields byte slices.
42 type Encoder<'e>: Encoder
43 where
44 Self: 'e;
45
46 /// Constructs a "default encoder" for the type.
47 fn encoder(&self) -> Self::Encoder<'_>;
48}
49
50/// An encoder for a consensus-encodable object.
51pub trait Encoder {
52 /// Yields the current encoded byteslice.
53 ///
54 /// Will always return the same value until [`Self::advance`] is called.
55 /// May return an empty list.
56 fn current_chunk(&self) -> &[u8];
57
58 /// Moves the encoder to its next state.
59 ///
60 /// Does not need to be called when the encoder is first created. (In fact, if it
61 /// is called, this will discard the first chunk of encoded data.)
62 ///
63 /// # Returns
64 ///
65 /// - `true` if the encoder has advanced to a new state and [`Self::current_chunk`] will return new data.
66 /// - `false` if the encoder is exhausted and has no more states.
67 fn advance(&mut self) -> bool;
68}
69
70/// Implements a newtype around an encoder.
71///
72/// The new type will implement the [`Encoder`] trait by forwarding to the wrapped encoder. If your
73/// type has a known size consider using [`crate::encoder_newtype_exact`] instead.
74///
75/// # Examples
76/// ```
77/// use bitcoin_consensus_encoding::{encoder_newtype, BytesEncoder};
78///
79/// encoder_newtype! {
80/// /// The encoder for the [`Foo`] type.
81/// pub struct FooEncoder<'e>(BytesEncoder<'e>);
82/// }
83/// ```
84///
85/// For a full example see `./examples/encoder.rs`.
86#[macro_export]
87macro_rules! encoder_newtype {
88 (
89 $(#[$($struct_attr:tt)*])*
90 $vis:vis struct $name:ident<$lt:lifetime>($encoder:ty);
91 ) => {
92 $(#[$($struct_attr)*])*
93 $vis struct $name<$lt>($encoder, core::marker::PhantomData<&$lt $encoder>);
94
95 #[allow(clippy::type_complexity)]
96 impl<$lt> $name<$lt> {
97 /// Constructs a new instance of the newtype encoder.
98 pub(crate) const fn new(encoder: $encoder) -> $name<$lt> {
99 $name(encoder, core::marker::PhantomData)
100 }
101 }
102
103 impl<$lt> $crate::Encoder for $name<$lt> {
104 #[inline]
105 fn current_chunk(&self) -> &[u8] { self.0.current_chunk() }
106
107 #[inline]
108 fn advance(&mut self) -> bool { self.0.advance() }
109 }
110 }
111}
112
113/// Implements a newtype around an exact-size encoder.
114///
115/// The new type will implement both the [`Encoder`] and [`ExactSizeEncoder`] traits
116/// by forwarding to the wrapped encoder.
117///
118/// # Examples
119/// ```
120/// use bitcoin_consensus_encoding::{encoder_newtype_exact, ArrayEncoder};
121///
122/// encoder_newtype_exact! {
123/// /// The encoder for the [`Bar`] type.
124/// pub struct BarEncoder<'e>(ArrayEncoder<32>);
125/// }
126/// ```
127///
128/// For a full example see `./examples/encoder.rs`.
129#[macro_export]
130macro_rules! encoder_newtype_exact {
131 (
132 $(#[$($struct_attr:tt)*])*
133 $vis:vis struct $name:ident<$lt:lifetime>($encoder:ty);
134 ) => {
135 $crate::encoder_newtype! {
136 $(#[$($struct_attr)*])*
137 $vis struct $name<$lt>($encoder);
138 }
139
140 impl<$lt> $crate::ExactSizeEncoder for $name<$lt> {
141 #[inline]
142 fn len(&self) -> usize { self.0.len() }
143 }
144 }
145}
146
147/// Yields bytes from any [`Encodable`] instance.
148#[derive(Debug)]
149pub struct EncodableByteIter<'e, T: Encodable + ?Sized + 'e> {
150 enc: T::Encoder<'e>,
151 position: usize,
152}
153
154impl<'e, T: Encodable + ?Sized + 'e> EncodableByteIter<'e, T> {
155 /// Constructs a new byte iterator around a provided encodable.
156 pub fn new(encodable: &'e T) -> Self { Self { enc: encodable.encoder(), position: 0 } }
157}
158
159// Manual impl rather than #[derive(Clone)] because derive would constrain `where T: Clone`,
160// but `T` itself is never cloned, only the associated type `T::Encoder<'e>`.
161impl<'e, T: Encodable + ?Sized + 'e> Clone for EncodableByteIter<'e, T>
162where
163 T::Encoder<'e>: Clone,
164{
165 fn clone(&self) -> Self { Self { enc: self.enc.clone(), position: self.position } }
166}
167
168impl<'e, T: Encodable + ?Sized + 'e> Iterator for EncodableByteIter<'e, T> {
169 type Item = u8;
170
171 fn next(&mut self) -> Option<Self::Item> {
172 loop {
173 if let Some(b) = self.enc.current_chunk().get(self.position) {
174 self.position += 1;
175 return Some(*b);
176 } else if !self.enc.advance() {
177 return None;
178 }
179 self.position = 0;
180 }
181 }
182}
183
184impl<'e, T> ExactSizeIterator for EncodableByteIter<'e, T>
185where
186 T: Encodable + ?Sized + 'e,
187 T::Encoder<'e>: ExactSizeEncoder,
188{
189 fn len(&self) -> usize { self.enc.len() - self.position }
190}
191
192/// An encoder with a known size.
193pub trait ExactSizeEncoder: Encoder {
194 /// The number of bytes remaining that the encoder will yield.
195 fn len(&self) -> usize;
196
197 /// Returns whether the encoder would yield an empty response.
198 fn is_empty(&self) -> bool { self.len() == 0 }
199}
200
201/// Encodes an object into a vector.
202#[cfg(feature = "alloc")]
203pub fn encode_to_vec<T>(object: &T) -> Vec<u8>
204where
205 T: Encodable + ?Sized,
206{
207 let mut encoder = object.encoder();
208 flush_to_vec(&mut encoder)
209}
210
211/// Flushes the output of an [`Encoder`] into a vector.
212#[cfg(feature = "alloc")]
213pub fn flush_to_vec<T>(encoder: &mut T) -> Vec<u8>
214where
215 T: Encoder + ?Sized,
216{
217 let mut vec = Vec::new();
218 loop {
219 vec.extend_from_slice(encoder.current_chunk());
220 if !encoder.advance() {
221 break;
222 }
223 }
224 vec
225}
226
227/// Encodes an object to a standard I/O writer.
228///
229/// # Performance
230///
231/// This method writes data in potentially small chunks based on the encoder's internal chunking
232/// strategy. For optimal performance with unbuffered writers (like [`std::fs::File`] or
233/// [`std::net::TcpStream`]), consider wrapping your writer with [`std::io::BufWriter`].
234///
235/// # Errors
236///
237/// Returns any I/O error encountered while writing to the writer.
238#[cfg(feature = "std")]
239pub fn encode_to_writer<T, W>(object: &T, writer: W) -> Result<(), std::io::Error>
240where
241 T: Encodable + ?Sized,
242 W: std::io::Write,
243{
244 let mut encoder = object.encoder();
245 flush_to_writer(&mut encoder, writer)
246}
247
248/// Flushes the output of an [`Encoder`] to a standard I/O writer.
249///
250/// See [`encode_to_writer`] for more information.
251///
252/// # Errors
253///
254/// Returns any I/O error encountered while writing to the writer.
255#[cfg(feature = "std")]
256pub fn flush_to_writer<T, W>(encoder: &mut T, mut writer: W) -> Result<(), std::io::Error>
257where
258 T: Encoder + ?Sized,
259 W: std::io::Write,
260{
261 loop {
262 writer.write_all(encoder.current_chunk())?;
263 if !encoder.advance() {
264 break;
265 }
266 }
267 Ok(())
268}
269
270impl<T: Encoder> Encoder for Option<T> {
271 fn current_chunk(&self) -> &[u8] {
272 match self {
273 Some(encoder) => encoder.current_chunk(),
274 None => &[],
275 }
276 }
277
278 fn advance(&mut self) -> bool {
279 match self {
280 Some(encoder) => encoder.advance(),
281 None => false,
282 }
283 }
284}