bitcoin_consensus_encoding/encode/
encoders.rs1use core::fmt;
14
15use super::{Encodable, Encoder, ExactSizeEncoder};
16
17#[derive(Debug, Clone)]
19pub struct BytesEncoder<'sl> {
20 sl: Option<&'sl [u8]>,
21}
22
23impl<'sl> BytesEncoder<'sl> {
24 pub const fn without_length_prefix(sl: &'sl [u8]) -> Self { Self { sl: Some(sl) } }
26}
27
28impl Encoder for BytesEncoder<'_> {
29 fn current_chunk(&self) -> &[u8] { self.sl.unwrap_or_default() }
30
31 fn advance(&mut self) -> bool {
32 self.sl = None;
33 false
34 }
35}
36
37impl<'sl> ExactSizeEncoder for BytesEncoder<'sl> {
38 #[inline]
39 fn len(&self) -> usize { self.sl.map_or(0, <[u8]>::len) }
40}
41
42#[derive(Debug, Clone)]
44pub struct ArrayEncoder<const N: usize> {
45 arr: Option<[u8; N]>,
46}
47
48impl<const N: usize> ArrayEncoder<N> {
49 pub const fn without_length_prefix(arr: [u8; N]) -> Self { Self { arr: Some(arr) } }
51}
52
53impl<const N: usize> Encoder for ArrayEncoder<N> {
54 #[inline]
55 fn current_chunk(&self) -> &[u8] { self.arr.as_ref().map(|x| &x[..]).unwrap_or_default() }
56
57 #[inline]
58 fn advance(&mut self) -> bool {
59 self.arr = None;
60 false
61 }
62}
63
64impl<const N: usize> ExactSizeEncoder for ArrayEncoder<N> {
65 #[inline]
66 fn len(&self) -> usize { self.arr.map_or(0, |a| a.len()) }
67}
68
69#[derive(Debug, Clone)]
74pub struct ArrayRefEncoder<'e, const N: usize> {
75 arr: Option<&'e [u8; N]>,
76}
77
78impl<'e, const N: usize> ArrayRefEncoder<'e, N> {
79 pub const fn without_length_prefix(arr: &'e [u8; N]) -> Self { Self { arr: Some(arr) } }
81}
82
83impl<const N: usize> Encoder for ArrayRefEncoder<'_, N> {
84 #[inline]
85 fn current_chunk(&self) -> &[u8] { self.arr.map(|x| &x[..]).unwrap_or_default() }
86
87 #[inline]
88 fn advance(&mut self) -> bool {
89 self.arr = None;
90 false
91 }
92}
93
94impl<const N: usize> ExactSizeEncoder for ArrayRefEncoder<'_, N> {
95 #[inline]
96 fn len(&self) -> usize { self.arr.map_or(0, |a| a.len()) }
97}
98
99pub struct SliceEncoder<'e, T: Encodable> {
101 sl: &'e [T],
103 cur_enc: Option<T::Encoder<'e>>,
105}
106
107impl<'e, T: Encodable> SliceEncoder<'e, T> {
108 pub fn without_length_prefix(sl: &'e [T]) -> Self {
114 Self { sl, cur_enc: sl.first().map(|x| T::encoder(x)) }
118 }
119}
120
121impl<'e, T: Encodable> fmt::Debug for SliceEncoder<'e, T>
122where
123 T::Encoder<'e>: fmt::Debug,
124{
125 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
126 f.debug_struct("SliceEncoder")
127 .field("sl", &self.sl.len())
128 .field("cur_enc", &self.cur_enc)
129 .finish()
130 }
131}
132
133impl<'e, T: Encodable> Clone for SliceEncoder<'e, T>
136where
137 T::Encoder<'e>: Clone,
138{
139 fn clone(&self) -> Self { Self { sl: self.sl, cur_enc: self.cur_enc.clone() } }
140}
141
142impl<T: Encodable> Encoder for SliceEncoder<'_, T> {
143 fn current_chunk(&self) -> &[u8] {
144 self.cur_enc.as_ref().map(T::Encoder::current_chunk).unwrap_or_default()
146 }
147
148 fn advance(&mut self) -> bool {
149 let Some(cur) = self.cur_enc.as_mut() else {
150 return false;
151 };
152
153 loop {
154 if cur.advance() {
157 return true;
158 }
159 self.sl = &self.sl[1..];
161
162 if let Some(x) = self.sl.first() {
164 *cur = x.encoder();
165 if !cur.current_chunk().is_empty() {
166 return true;
167 }
168 } else {
169 self.cur_enc = None; return false;
171 }
172 }
173 }
174}
175
176macro_rules! define_encoder_n {
178 (
179 $(#[$attr:meta])*
180 $name:ident, $idx_limit:literal;
181 $(($enc_idx:literal, $enc_ty:ident, $enc_field:ident),)*
182 ) => {
183 $(#[$attr])*
184 #[derive(Debug, Clone)]
185 pub struct $name<$($enc_ty,)*> {
186 cur_idx: usize,
187 $($enc_field: $enc_ty,)*
188 }
189
190 impl<$($enc_ty,)*> $name<$($enc_ty,)*> {
191 pub const fn new($($enc_field: $enc_ty,)*) -> Self {
193 Self { cur_idx: 0, $($enc_field,)* }
194 }
195 }
196
197 impl<$($enc_ty: Encoder,)*> Encoder for $name<$($enc_ty,)*> {
198 #[inline]
199 fn current_chunk(&self) -> &[u8] {
200 match self.cur_idx {
201 $($enc_idx => self.$enc_field.current_chunk(),)*
202 _ => &[],
203 }
204 }
205
206 #[inline]
207 fn advance(&mut self) -> bool {
208 match self.cur_idx {
209 $(
210 $enc_idx => {
211 if $enc_idx == $idx_limit - 1 {
213 return self.$enc_field.advance()
214 }
215 if !self.$enc_field.advance() {
217 self.cur_idx += 1;
218 }
219 true
220 }
221 )*
222 _ => false,
223 }
224 }
225 }
226
227 impl<$($enc_ty,)*> ExactSizeEncoder for $name<$($enc_ty,)*>
228 where
229 $($enc_ty: Encoder + ExactSizeEncoder,)*
230 {
231 #[inline]
232 fn len(&self) -> usize {
233 0 $(+ self.$enc_field.len())*
234 }
235 }
236 };
237}
238
239define_encoder_n! {
240 Encoder2, 2;
242 (0, A, enc_1), (1, B, enc_2),
243}
244
245define_encoder_n! {
246 Encoder3, 3;
248 (0, A, enc_1), (1, B, enc_2), (2, C, enc_3),
249}
250
251define_encoder_n! {
252 Encoder4, 4;
254 (0, A, enc_1), (1, B, enc_2),
255 (2, C, enc_3), (3, D, enc_4),
256}
257
258define_encoder_n! {
259 Encoder6, 6;
261 (0, A, enc_1), (1, B, enc_2), (2, C, enc_3),
262 (3, D, enc_4), (4, E, enc_5), (5, F, enc_6),
263}