bitcoin_consensus_encoding/encode/
encoders.rs1use core::fmt;
14
15use super::{Encode, Encoder, EncoderStatus, ExactSizeEncoder};
16
17#[derive(Debug, Clone)]
19pub struct BytesEncoder<'sl> {
20 sl: &'sl [u8],
21}
22
23impl<'sl> BytesEncoder<'sl> {
24 pub const fn without_length_prefix(sl: &'sl [u8]) -> Self { Self { sl } }
26}
27
28impl Encoder for BytesEncoder<'_> {
29 fn current_chunk(&self) -> &[u8] { self.sl }
30
31 fn advance(&mut self) -> EncoderStatus { EncoderStatus::Finished }
32}
33
34impl<'sl> ExactSizeEncoder for BytesEncoder<'sl> {
35 #[inline]
36 fn len(&self) -> usize { self.sl.len() }
37}
38
39#[derive(Debug, Clone)]
41pub struct ArrayEncoder<const N: usize> {
42 arr: [u8; N],
43}
44
45impl<const N: usize> ArrayEncoder<N> {
46 pub const fn without_length_prefix(arr: [u8; N]) -> Self { Self { arr } }
48}
49
50impl<const N: usize> Encoder for ArrayEncoder<N> {
51 #[inline]
52 fn current_chunk(&self) -> &[u8] { &self.arr }
53
54 #[inline]
55 fn advance(&mut self) -> EncoderStatus { EncoderStatus::Finished }
56}
57
58impl<const N: usize> ExactSizeEncoder for ArrayEncoder<N> {
59 #[inline]
60 fn len(&self) -> usize { self.arr.len() }
61}
62
63#[derive(Debug, Clone)]
68pub struct ArrayRefEncoder<'e, const N: usize> {
69 arr: &'e [u8; N],
70}
71
72impl<'e, const N: usize> ArrayRefEncoder<'e, N> {
73 pub const fn without_length_prefix(arr: &'e [u8; N]) -> Self { Self { arr } }
75}
76
77impl<const N: usize> Encoder for ArrayRefEncoder<'_, N> {
78 #[inline]
79 fn current_chunk(&self) -> &[u8] { self.arr }
80
81 #[inline]
82 fn advance(&mut self) -> EncoderStatus { EncoderStatus::Finished }
83}
84
85impl<const N: usize> ExactSizeEncoder for ArrayRefEncoder<'_, N> {
86 #[inline]
87 fn len(&self) -> usize { self.arr.len() }
88}
89
90pub struct SliceEncoder<'e, T: Encode> {
92 sl: &'e [T],
94 cur_enc: Option<T::Encoder<'e>>,
96}
97
98impl<'e, T: Encode> SliceEncoder<'e, T> {
99 pub fn without_length_prefix(sl: &'e [T]) -> Self {
105 Self { sl, cur_enc: sl.first().map(|x| T::encoder(x)) }
109 }
110}
111
112impl<'e, T: Encode> fmt::Debug for SliceEncoder<'e, T>
113where
114 T::Encoder<'e>: fmt::Debug,
115{
116 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
117 f.debug_struct("SliceEncoder")
118 .field("sl", &self.sl.len())
119 .field("cur_enc", &self.cur_enc)
120 .finish()
121 }
122}
123
124impl<'e, T: Encode> Clone for SliceEncoder<'e, T>
127where
128 T::Encoder<'e>: Clone,
129{
130 fn clone(&self) -> Self { Self { sl: self.sl, cur_enc: self.cur_enc.clone() } }
131}
132
133impl<T: Encode> Encoder for SliceEncoder<'_, T> {
134 fn current_chunk(&self) -> &[u8] {
135 self.cur_enc.as_ref().map(T::Encoder::current_chunk).unwrap_or_default()
137 }
138
139 fn advance(&mut self) -> EncoderStatus {
140 let Some(cur) = self.cur_enc.as_mut() else {
141 return EncoderStatus::Finished;
142 };
143
144 loop {
145 if cur.advance().has_more() {
148 return EncoderStatus::HasMore;
149 }
150 self.sl = &self.sl[1..];
152
153 if let Some(x) = self.sl.first() {
155 *cur = x.encoder();
156 if !cur.current_chunk().is_empty() {
157 return EncoderStatus::HasMore;
158 }
159 } else {
160 self.cur_enc = None; return EncoderStatus::Finished;
162 }
163 }
164 }
165}
166
167macro_rules! define_encoder_n {
169 (
170 $(#[$attr:meta])*
171 $name:ident, $idx_limit:literal;
172 $(($enc_idx:literal, $enc_ty:ident, $enc_field:ident),)*
173 ) => {
174 $(#[$attr])*
175 #[derive(Debug, Clone)]
176 pub struct $name<$($enc_ty,)*> {
177 cur_idx: usize,
178 $($enc_field: $enc_ty,)*
179 }
180
181 impl<$($enc_ty,)*> $name<$($enc_ty,)*> {
182 pub const fn new($($enc_field: $enc_ty,)*) -> Self {
184 Self { cur_idx: 0, $($enc_field,)* }
185 }
186 }
187
188 impl<$($enc_ty: Encoder,)*> Encoder for $name<$($enc_ty,)*> {
189 #[inline]
190 fn current_chunk(&self) -> &[u8] {
191 match self.cur_idx {
192 $($enc_idx => self.$enc_field.current_chunk(),)*
193 _ => unreachable!("index never reaches this value"),
194 }
195 }
196
197 #[inline]
198 fn advance(&mut self) -> EncoderStatus {
199 match self.cur_idx {
200 $(
201 $enc_idx => {
202 if $enc_idx == $idx_limit - 1 {
204 return self.$enc_field.advance()
205 }
206 if self.$enc_field.advance().has_finished() {
208 self.cur_idx += 1;
209 }
210 EncoderStatus::HasMore
211 }
212 )*
213 _ => EncoderStatus::Finished,
214 }
215 }
216 }
217
218 impl<$($enc_ty,)*> ExactSizeEncoder for $name<$($enc_ty,)*>
219 where
220 $($enc_ty: Encoder + ExactSizeEncoder,)*
221 {
222 #[inline]
223 fn len(&self) -> usize {
224 0 $(+ self.$enc_field.len())*
225 }
226 }
227 };
228}
229
230define_encoder_n! {
231 Encoder2, 2;
233 (0, A, enc_1), (1, B, enc_2),
234}
235
236define_encoder_n! {
237 Encoder3, 3;
239 (0, A, enc_1), (1, B, enc_2), (2, C, enc_3),
240}
241
242define_encoder_n! {
243 Encoder4, 4;
245 (0, A, enc_1), (1, B, enc_2),
246 (2, C, enc_3), (3, D, enc_4),
247}
248
249define_encoder_n! {
250 Encoder6, 6;
252 (0, A, enc_1), (1, B, enc_2), (2, C, enc_3),
253 (3, D, enc_4), (4, E, enc_5), (5, F, enc_6),
254}