bitcoin_consensus_encoding/encode/
mod.rs1#[cfg(feature = "alloc")]
6use alloc::vec::Vec;
7
8pub mod encoders;
9
10pub trait Encodable {
16 type Encoder<'e>: Encoder
19 where
20 Self: 'e;
21
22 fn encoder(&self) -> Self::Encoder<'_>;
24}
25
26pub trait Encoder {
28 fn current_chunk(&self) -> &[u8];
33
34 fn advance(&mut self) -> bool;
44}
45
46#[macro_export]
49macro_rules! encoder_newtype{
50 (
51 $(#[$($struct_attr:tt)*])*
52 pub struct $name:ident<$lt:lifetime>($encoder:ty);
53 ) => {
54 $(#[$($struct_attr)*])*
55 pub struct $name<$lt>($encoder, core::marker::PhantomData<&$lt $encoder>);
56
57 impl<$lt> $name<$lt> {
58 pub fn new(encoder: $encoder) -> $name<$lt> {
60 $name(encoder, core::marker::PhantomData)
61 }
62 }
63
64 impl<$lt> $crate::Encoder for $name<$lt> {
65 #[inline]
66 fn current_chunk(&self) -> &[u8] { self.0.current_chunk() }
67
68 #[inline]
69 fn advance(&mut self) -> bool { self.0.advance() }
70 }
71 }
72}
73
74#[macro_export]
78macro_rules! encoder_newtype_exact{
79 (
80 $(#[$($struct_attr:tt)*])*
81 pub struct $name:ident<$lt:lifetime>($encoder:ty);
82 ) => {
83 $crate::encoder_newtype! {
84 $(#[$($struct_attr)*])*
85 pub struct $name<$lt>($encoder);
86 }
87
88 impl<$lt> $crate::ExactSizeEncoder for $name<$lt> {
89 #[inline]
90 fn len(&self) -> usize { self.0.len() }
91 }
92 }
93}
94
95pub struct EncodableByteIter<'e, T: Encodable + 'e> {
97 enc: T::Encoder<'e>,
98 position: usize,
99}
100
101impl<'e, T: Encodable + 'e> EncodableByteIter<'e, T> {
102 pub fn new(encodable: &'e T) -> Self { Self { enc: encodable.encoder(), position: 0 } }
104}
105
106impl<'e, T: Encodable + 'e> Iterator for EncodableByteIter<'e, T> {
107 type Item = u8;
108
109 fn next(&mut self) -> Option<Self::Item> {
110 loop {
111 if let Some(b) = self.enc.current_chunk().get(self.position) {
112 self.position += 1;
113 return Some(*b);
114 } else if !self.enc.advance() {
115 return None;
116 }
117 self.position = 0;
118 }
119 }
120}
121
122impl<'e, T> ExactSizeIterator for EncodableByteIter<'e, T>
123where
124 T: Encodable + 'e,
125 T::Encoder<'e>: ExactSizeEncoder,
126{
127 fn len(&self) -> usize { self.enc.len() - self.position }
128}
129
130pub trait ExactSizeEncoder: Encoder {
132 fn len(&self) -> usize;
134
135 fn is_empty(&self) -> bool { self.len() == 0 }
137}
138
139#[cfg(feature = "alloc")]
141pub fn encode_to_vec<T>(object: &T) -> Vec<u8>
142where
143 T: Encodable + ?Sized,
144{
145 let mut encoder = object.encoder();
146 flush_to_vec(&mut encoder)
147}
148
149#[cfg(feature = "alloc")]
151pub fn flush_to_vec<T>(encoder: &mut T) -> Vec<u8>
152where
153 T: Encoder + ?Sized,
154{
155 let mut vec = Vec::new();
156 loop {
157 vec.extend_from_slice(encoder.current_chunk());
158 if !encoder.advance() {
159 break;
160 }
161 }
162 vec
163}
164
165#[cfg(feature = "std")]
178pub fn encode_to_writer<T, W>(object: &T, writer: W) -> Result<(), std::io::Error>
179where
180 T: Encodable + ?Sized,
181 W: std::io::Write,
182{
183 let mut encoder = object.encoder();
184 flush_to_writer(&mut encoder, writer)
185}
186
187#[cfg(feature = "std")]
195pub fn flush_to_writer<T, W>(encoder: &mut T, mut writer: W) -> Result<(), std::io::Error>
196where
197 T: Encoder + ?Sized,
198 W: std::io::Write,
199{
200 loop {
201 writer.write_all(encoder.current_chunk())?;
202 if !encoder.advance() {
203 break;
204 }
205 }
206 Ok(())
207}
208
209impl<T: Encoder> Encoder for Option<T> {
210 fn current_chunk(&self) -> &[u8] {
211 match self {
212 Some(encoder) => encoder.current_chunk(),
213 None => &[],
214 }
215 }
216
217 fn advance(&mut self) -> bool {
218 match self {
219 Some(encoder) => encoder.advance(),
220 None => false,
221 }
222 }
223}