bitcoin_consensus_encoding/encode/
encoders.rs1use core::fmt;
14
15use super::{Encode, Encoder, EncoderStatus, ExactSizeEncoder};
16use crate::CompactSizeEncoder;
17
18#[derive(Debug, Clone)]
20pub struct BytesEncoder<'sl> {
21 sl: &'sl [u8],
22}
23
24impl<'sl> BytesEncoder<'sl> {
25 pub const fn without_length_prefix(sl: &'sl [u8]) -> Self { Self { sl } }
27}
28
29impl Encoder for BytesEncoder<'_> {
30 fn current_chunk(&self) -> &[u8] { self.sl }
31
32 fn advance(&mut self) -> EncoderStatus { EncoderStatus::Finished }
33}
34
35impl<'sl> ExactSizeEncoder for BytesEncoder<'sl> {
36 #[inline]
37 fn len(&self) -> usize { self.sl.len() }
38}
39
40#[derive(Debug, Clone)]
42pub struct PrefixedBytesEncoder<'sl>(Encoder2<CompactSizeEncoder, BytesEncoder<'sl>>);
43
44impl<'sl> PrefixedBytesEncoder<'sl> {
45 #[inline]
47 pub fn new(sl: &'sl [u8]) -> Self {
48 Self(Encoder2::new(
49 CompactSizeEncoder::new(sl.len()),
50 BytesEncoder::without_length_prefix(sl),
51 ))
52 }
53}
54
55impl Encoder for PrefixedBytesEncoder<'_> {
56 #[inline]
57 fn current_chunk(&self) -> &[u8] { self.0.current_chunk() }
58
59 #[inline]
60 fn advance(&mut self) -> EncoderStatus { self.0.advance() }
61}
62
63impl ExactSizeEncoder for PrefixedBytesEncoder<'_> {
64 #[inline]
65 fn len(&self) -> usize { self.0.len() }
66}
67
68#[derive(Debug, Clone)]
70pub struct ArrayEncoder<const N: usize> {
71 arr: [u8; N],
72}
73
74impl<const N: usize> ArrayEncoder<N> {
75 pub const fn without_length_prefix(arr: [u8; N]) -> Self { Self { arr } }
77}
78
79impl<const N: usize> Encoder for ArrayEncoder<N> {
80 #[inline]
81 fn current_chunk(&self) -> &[u8] { &self.arr }
82
83 #[inline]
84 fn advance(&mut self) -> EncoderStatus { EncoderStatus::Finished }
85}
86
87impl<const N: usize> ExactSizeEncoder for ArrayEncoder<N> {
88 #[inline]
89 fn len(&self) -> usize { self.arr.len() }
90}
91
92#[derive(Debug, Clone)]
97pub struct ArrayRefEncoder<'e, const N: usize> {
98 arr: &'e [u8; N],
99}
100
101impl<'e, const N: usize> ArrayRefEncoder<'e, N> {
102 pub const fn without_length_prefix(arr: &'e [u8; N]) -> Self { Self { arr } }
104}
105
106impl<const N: usize> Encoder for ArrayRefEncoder<'_, N> {
107 #[inline]
108 fn current_chunk(&self) -> &[u8] { self.arr }
109
110 #[inline]
111 fn advance(&mut self) -> EncoderStatus { EncoderStatus::Finished }
112}
113
114impl<const N: usize> ExactSizeEncoder for ArrayRefEncoder<'_, N> {
115 #[inline]
116 fn len(&self) -> usize { self.arr.len() }
117}
118
119pub struct SliceEncoder<'e, T: Encode> {
121 sl: &'e [T],
123 cur_enc: Option<T::Encoder<'e>>,
125}
126
127impl<'e, T: Encode> SliceEncoder<'e, T> {
128 pub fn without_length_prefix(sl: &'e [T]) -> Self {
132 Self { sl, cur_enc: sl.first().map(|x| T::encoder(x)) }
136 }
137}
138
139impl<'e, T: Encode> fmt::Debug for SliceEncoder<'e, T>
140where
141 T::Encoder<'e>: fmt::Debug,
142{
143 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
144 f.debug_struct("SliceEncoder")
145 .field("sl", &self.sl.len())
146 .field("cur_enc", &self.cur_enc)
147 .finish()
148 }
149}
150
151impl<'e, T: Encode> Clone for SliceEncoder<'e, T>
154where
155 T::Encoder<'e>: Clone,
156{
157 fn clone(&self) -> Self { Self { sl: self.sl, cur_enc: self.cur_enc.clone() } }
158}
159
160impl<T: Encode> Encoder for SliceEncoder<'_, T> {
161 fn current_chunk(&self) -> &[u8] {
162 self.cur_enc.as_ref().map(T::Encoder::current_chunk).unwrap_or_default()
164 }
165
166 fn advance(&mut self) -> EncoderStatus {
167 let Some(cur) = self.cur_enc.as_mut() else {
168 return EncoderStatus::Finished;
169 };
170
171 loop {
172 if cur.advance().has_more() {
175 return EncoderStatus::HasMore;
176 }
177 self.sl = &self.sl[1..];
179
180 if let Some(x) = self.sl.first() {
182 *cur = x.encoder();
183 if !cur.current_chunk().is_empty() {
184 return EncoderStatus::HasMore;
185 }
186 } else {
187 self.cur_enc = None; return EncoderStatus::Finished;
189 }
190 }
191 }
192}
193
194pub struct PrefixedSliceEncoder<'e, T: Encode>(Encoder2<CompactSizeEncoder, SliceEncoder<'e, T>>);
196
197impl<'e, T: Encode> PrefixedSliceEncoder<'e, T> {
198 #[inline]
200 pub fn new(sl: &'e [T]) -> Self {
201 Self(Encoder2::new(
202 CompactSizeEncoder::new(sl.len()),
203 SliceEncoder::without_length_prefix(sl),
204 ))
205 }
206}
207
208impl<'e, T: Encode> fmt::Debug for PrefixedSliceEncoder<'e, T>
209where
210 T::Encoder<'e>: fmt::Debug,
211{
212 #[inline]
213 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { self.0.fmt(f) }
214}
215
216impl<'e, T: Encode> Clone for PrefixedSliceEncoder<'e, T>
217where
218 T::Encoder<'e>: Clone,
219{
220 #[inline]
221 fn clone(&self) -> Self { Self(self.0.clone()) }
222}
223
224impl<T: Encode> Encoder for PrefixedSliceEncoder<'_, T> {
225 #[inline]
226 fn current_chunk(&self) -> &[u8] { self.0.current_chunk() }
227
228 #[inline]
229 fn advance(&mut self) -> EncoderStatus { self.0.advance() }
230}
231
232macro_rules! define_encoder_n {
234 (
235 $(#[$attr:meta])*
236 $name:ident, $idx_limit:literal;
237 $(($enc_idx:literal, $enc_ty:ident, $enc_field:ident),)*
238 ) => {
239 $(#[$attr])*
240 #[derive(Debug, Clone)]
241 pub struct $name<$($enc_ty,)*> {
242 cur_idx: usize,
243 $($enc_field: $enc_ty,)*
244 }
245
246 impl<$($enc_ty,)*> $name<$($enc_ty,)*> {
247 pub const fn new($($enc_field: $enc_ty,)*) -> Self {
249 Self { cur_idx: 0, $($enc_field,)* }
250 }
251 }
252
253 impl<$($enc_ty: Encoder,)*> Encoder for $name<$($enc_ty,)*> {
254 #[inline]
255 fn current_chunk(&self) -> &[u8] {
256 match self.cur_idx {
257 $($enc_idx => self.$enc_field.current_chunk(),)*
258 _ => unreachable!("index never reaches this value"),
259 }
260 }
261
262 #[inline]
263 fn advance(&mut self) -> EncoderStatus {
264 match self.cur_idx {
265 $(
266 $enc_idx => {
267 if $enc_idx == $idx_limit - 1 {
269 return self.$enc_field.advance()
270 }
271 if self.$enc_field.advance().has_finished() {
273 self.cur_idx += 1;
274 }
275 EncoderStatus::HasMore
276 }
277 )*
278 _ => EncoderStatus::Finished,
279 }
280 }
281 }
282
283 impl<$($enc_ty,)*> ExactSizeEncoder for $name<$($enc_ty,)*>
284 where
285 $($enc_ty: Encoder + ExactSizeEncoder,)*
286 {
287 #[inline]
288 fn len(&self) -> usize {
289 0 $(+ self.$enc_field.len())*
290 }
291 }
292 };
293}
294
295define_encoder_n! {
296 Encoder2, 2;
298 (0, A, enc_1), (1, B, enc_2),
299}
300
301define_encoder_n! {
302 Encoder3, 3;
304 (0, A, enc_1), (1, B, enc_2), (2, C, enc_3),
305}
306
307define_encoder_n! {
308 Encoder4, 4;
310 (0, A, enc_1), (1, B, enc_2),
311 (2, C, enc_3), (3, D, enc_4),
312}
313
314define_encoder_n! {
315 Encoder6, 6;
317 (0, A, enc_1), (1, B, enc_2), (2, C, enc_3),
318 (3, D, enc_4), (4, E, enc_5), (5, F, enc_6),
319}