bitcoin_consensus_encoding/encode/
encoders.rs1use core::fmt;
13
14use super::iter::{Encoders, IterEncoder};
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>(IterEncoder<Encoders<'e, T>>);
121
122impl<'e, T: Encode> SliceEncoder<'e, T> {
123 pub fn without_length_prefix(sl: &'e [T]) -> Self { Self(IterEncoder::new(Encoders::new(sl))) }
127}
128
129impl<'e, T: Encode + 'e> fmt::Debug for SliceEncoder<'e, T>
130where
131 T::Encoder<'e>: fmt::Debug,
132{
133 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
134 f.debug_tuple("SliceEncoder").field(&self.0).finish()
135 }
136}
137
138impl<'e, T: Encode + 'e> Clone for SliceEncoder<'e, T>
141where
142 T::Encoder<'e>: Clone,
143{
144 fn clone(&self) -> Self { Self(self.0.clone()) }
145}
146
147impl<T: Encode> Encoder for SliceEncoder<'_, T> {
148 fn current_chunk(&self) -> &[u8] { self.0.current_chunk() }
149 fn advance(&mut self) -> EncoderStatus { self.0.advance() }
150}
151
152pub struct PrefixedSliceEncoder<'e, T: Encode>(Encoder2<CompactSizeEncoder, SliceEncoder<'e, T>>);
154
155impl<'e, T: Encode> PrefixedSliceEncoder<'e, T> {
156 #[inline]
158 pub fn new(sl: &'e [T]) -> Self {
159 Self(Encoder2::new(
160 CompactSizeEncoder::new(sl.len()),
161 SliceEncoder::without_length_prefix(sl),
162 ))
163 }
164}
165
166impl<'e, T: Encode + 'e> fmt::Debug for PrefixedSliceEncoder<'e, T>
167where
168 T::Encoder<'e>: fmt::Debug,
169{
170 #[inline]
171 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { self.0.fmt(f) }
172}
173
174impl<'e, T: Encode + 'e> Clone for PrefixedSliceEncoder<'e, T>
175where
176 T::Encoder<'e>: Clone,
177{
178 #[inline]
179 fn clone(&self) -> Self { Self(self.0.clone()) }
180}
181
182impl<T: Encode> Encoder for PrefixedSliceEncoder<'_, T> {
183 #[inline]
184 fn current_chunk(&self) -> &[u8] { self.0.current_chunk() }
185
186 #[inline]
187 fn advance(&mut self) -> EncoderStatus { self.0.advance() }
188}
189
190macro_rules! define_encoder_n {
192 (
193 $(#[$attr:meta])*
194 $name:ident, $idx_limit:literal;
195 $(($enc_idx:literal, $enc_ty:ident, $enc_field:ident),)*
196 ) => {
197 $(#[$attr])*
198 #[derive(Debug, Clone)]
199 pub struct $name<$($enc_ty,)*> {
200 cur_idx: usize,
201 $($enc_field: $enc_ty,)*
202 }
203
204 impl<$($enc_ty,)*> $name<$($enc_ty,)*> {
205 pub const fn new($($enc_field: $enc_ty,)*) -> Self {
207 Self { cur_idx: 0, $($enc_field,)* }
208 }
209 }
210
211 impl<$($enc_ty: Encoder,)*> Encoder for $name<$($enc_ty,)*> {
212 #[inline]
213 fn current_chunk(&self) -> &[u8] {
214 match self.cur_idx {
215 $($enc_idx => self.$enc_field.current_chunk(),)*
216 _ => unreachable!("index never reaches this value"),
217 }
218 }
219
220 #[inline]
221 fn advance(&mut self) -> EncoderStatus {
222 match self.cur_idx {
223 $(
224 $enc_idx => {
225 if $enc_idx == $idx_limit - 1 {
227 return self.$enc_field.advance()
228 }
229 if self.$enc_field.advance().has_finished() {
231 self.cur_idx += 1;
232 }
233 EncoderStatus::HasMore
234 }
235 )*
236 _ => EncoderStatus::Finished,
237 }
238 }
239 }
240
241 impl<$($enc_ty,)*> ExactSizeEncoder for $name<$($enc_ty,)*>
242 where
243 $($enc_ty: Encoder + ExactSizeEncoder,)*
244 {
245 #[inline]
246 fn len(&self) -> usize {
247 0 $(+ self.$enc_field.len())*
248 }
249 }
250 };
251}
252
253define_encoder_n! {
254 Encoder2, 2;
256 (0, A, enc_1), (1, B, enc_2),
257}
258
259define_encoder_n! {
260 Encoder3, 3;
262 (0, A, enc_1), (1, B, enc_2), (2, C, enc_3),
263}
264
265define_encoder_n! {
266 Encoder4, 4;
268 (0, A, enc_1), (1, B, enc_2),
269 (2, C, enc_3), (3, D, enc_4),
270}
271
272define_encoder_n! {
273 Encoder6, 6;
275 (0, A, enc_1), (1, B, enc_2), (2, C, enc_3),
276 (3, D, enc_4), (4, E, enc_5), (5, F, enc_6),
277}