1use crate::{Header, EMPTY_STRING_CODE};
2use bytes::{BufMut, Bytes, BytesMut};
3use core::{
4 borrow::Borrow,
5 marker::{PhantomData, PhantomPinned},
6};
7
8#[allow(unused_imports)]
9use alloc::vec::Vec;
10
11#[cfg(feature = "arrayvec")]
12use arrayvec::ArrayVec;
13
14pub trait Encodable {
16 fn encode(&self, out: &mut dyn BufMut);
18
19 #[inline]
25 fn length(&self) -> usize {
26 let mut out = Vec::new();
27 self.encode(&mut out);
28 out.len()
29 }
30}
31
32fn _assert_trait_object(_b: &dyn Encodable) {}
35
36pub unsafe trait MaxEncodedLen<const LEN: usize>: Encodable {}
42
43pub unsafe trait MaxEncodedLenAssoc: Encodable {
49 const LEN: usize;
51}
52
53#[macro_export]
59macro_rules! impl_max_encoded_len {
60 ($t:ty, $len:expr) => {
61 unsafe impl $crate::MaxEncodedLen<{ $len }> for $t {}
62 unsafe impl $crate::MaxEncodedLenAssoc for $t {
63 const LEN: usize = $len;
64 }
65 };
66}
67
68macro_rules! to_be_bytes_trimmed {
69 ($be:ident, $x:expr) => {{
70 $be = $x.to_be_bytes();
71 &$be[($x.leading_zeros() / 8) as usize..]
72 }};
73}
74pub(crate) use to_be_bytes_trimmed;
75
76impl Encodable for [u8] {
77 #[inline]
78 fn length(&self) -> usize {
79 let mut len = self.len();
80 if len != 1 || self[0] >= EMPTY_STRING_CODE {
81 len += length_of_length(len);
82 }
83 len
84 }
85
86 #[inline]
87 fn encode(&self, out: &mut dyn BufMut) {
88 if self.len() != 1 || self[0] >= EMPTY_STRING_CODE {
89 Header { list: false, payload_length: self.len() }.encode(out);
90 }
91 out.put_slice(self);
92 }
93}
94
95impl<T: ?Sized> Encodable for PhantomData<T> {
96 #[inline]
97 fn length(&self) -> usize {
98 0
99 }
100
101 #[inline]
102 fn encode(&self, _out: &mut dyn BufMut) {}
103}
104
105impl Encodable for PhantomPinned {
106 #[inline]
107 fn length(&self) -> usize {
108 0
109 }
110
111 #[inline]
112 fn encode(&self, _out: &mut dyn BufMut) {}
113}
114
115impl<const N: usize> Encodable for [u8; N] {
116 #[inline]
117 fn length(&self) -> usize {
118 self[..].length()
119 }
120
121 #[inline]
122 fn encode(&self, out: &mut dyn BufMut) {
123 self[..].encode(out);
124 }
125}
126
127unsafe impl<const N: usize> MaxEncodedLenAssoc for [u8; N] {
128 const LEN: usize = N + length_of_length(N);
129}
130
131impl Encodable for str {
132 #[inline]
133 fn length(&self) -> usize {
134 self.as_bytes().length()
135 }
136
137 #[inline]
138 fn encode(&self, out: &mut dyn BufMut) {
139 self.as_bytes().encode(out)
140 }
141}
142
143impl Encodable for bool {
144 #[inline]
145 fn length(&self) -> usize {
146 1
148 }
149
150 #[inline]
151 fn encode(&self, out: &mut dyn BufMut) {
152 out.put_u8(if *self { 1 } else { EMPTY_STRING_CODE });
154 }
155}
156
157impl_max_encoded_len!(bool, <u8 as MaxEncodedLenAssoc>::LEN);
158
159macro_rules! uint_impl {
160 ($($t:ty),+ $(,)?) => {$(
161 impl Encodable for $t {
162 #[inline]
163 fn length(&self) -> usize {
164 let x = *self;
165 if x < EMPTY_STRING_CODE as $t {
166 1
167 } else {
168 1 + (<$t>::BITS as usize / 8) - (x.leading_zeros() as usize / 8)
169 }
170 }
171
172 #[inline]
173 fn encode(&self, out: &mut dyn BufMut) {
174 let x = *self;
175 if x == 0 {
176 out.put_u8(EMPTY_STRING_CODE);
177 } else if x < EMPTY_STRING_CODE as $t {
178 out.put_u8(x as u8);
179 } else {
180 let be;
181 let be = to_be_bytes_trimmed!(be, x);
182 out.put_u8(EMPTY_STRING_CODE + be.len() as u8);
183 out.put_slice(be);
184 }
185 }
186 }
187
188 impl_max_encoded_len!($t, {
189 let bytes = <$t>::BITS as usize / 8;
190 bytes + length_of_length(bytes)
191 });
192 )+};
193}
194
195uint_impl!(u8, u16, u32, u64, usize, u128);
196
197impl<T: Encodable> Encodable for Vec<T> {
198 #[inline]
199 fn length(&self) -> usize {
200 list_length(self)
201 }
202
203 #[inline]
204 fn encode(&self, out: &mut dyn BufMut) {
205 encode_list(self, out)
206 }
207}
208
209macro_rules! deref_impl {
210 ($($(#[$attr:meta])* [$($gen:tt)*] $t:ty),+ $(,)?) => {$(
211 $(#[$attr])*
212 impl<$($gen)*> Encodable for $t {
213 #[inline]
214 fn length(&self) -> usize {
215 (**self).length()
216 }
217
218 #[inline]
219 fn encode(&self, out: &mut dyn BufMut) {
220 (**self).encode(out)
221 }
222 }
223 )+};
224}
225
226deref_impl! {
227 [] alloc::string::String,
228 [] Bytes,
229 [] BytesMut,
230 #[cfg(feature = "arrayvec")]
231 [const N: usize] ArrayVec<u8, N>,
232 [T: ?Sized + Encodable] &T,
233 [T: ?Sized + Encodable] &mut T,
234 [T: ?Sized + Encodable] alloc::boxed::Box<T>,
235 [T: ?Sized + alloc::borrow::ToOwned + Encodable] alloc::borrow::Cow<'_, T>,
236 [T: ?Sized + Encodable] alloc::rc::Rc<T>,
237 [T: ?Sized + Encodable] alloc::sync::Arc<T>,
238}
239
240#[cfg(feature = "std")]
241mod std_support {
242 use super::*;
243 use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
244
245 impl Encodable for IpAddr {
246 #[inline]
247 fn length(&self) -> usize {
248 match self {
249 Self::V4(ip) => ip.length(),
250 Self::V6(ip) => ip.length(),
251 }
252 }
253
254 #[inline]
255 fn encode(&self, out: &mut dyn BufMut) {
256 match self {
257 Self::V4(ip) => ip.encode(out),
258 Self::V6(ip) => ip.encode(out),
259 }
260 }
261 }
262
263 impl Encodable for Ipv4Addr {
264 #[inline]
265 fn length(&self) -> usize {
266 self.octets().length()
267 }
268
269 #[inline]
270 fn encode(&self, out: &mut dyn BufMut) {
271 self.octets().encode(out)
272 }
273 }
274
275 impl Encodable for Ipv6Addr {
276 #[inline]
277 fn length(&self) -> usize {
278 self.octets().length()
279 }
280
281 #[inline]
282 fn encode(&self, out: &mut dyn BufMut) {
283 self.octets().encode(out)
284 }
285 }
286}
287
288#[inline]
292pub fn encode<T: Encodable>(value: T) -> Vec<u8> {
293 let mut out = Vec::with_capacity(value.length());
294 value.encode(&mut out);
295 out
296}
297
298#[cfg(feature = "arrayvec")]
300#[inline]
301pub fn encode_fixed_size<T: MaxEncodedLen<LEN>, const LEN: usize>(value: &T) -> ArrayVec<u8, LEN> {
302 let mut vec = ArrayVec::<u8, LEN>::new();
303
304 let mut out = unsafe { core::slice::from_raw_parts_mut(vec.as_mut_ptr(), LEN) };
306 value.encode(&mut out);
307 let written = LEN - out.len();
308
309 unsafe { vec.set_len(written) };
311 vec
312}
313
314#[inline]
316pub fn list_length<B, T>(list: &[B]) -> usize
317where
318 B: Borrow<T>,
319 T: ?Sized + Encodable,
320{
321 let payload_length = rlp_list_header(list).payload_length;
322 payload_length + length_of_length(payload_length)
323}
324
325#[inline]
327pub fn encode_list<B, T>(values: &[B], out: &mut dyn BufMut)
328where
329 B: Borrow<T>,
330 T: ?Sized + Encodable,
331{
332 rlp_list_header(values).encode(out);
333 for value in values {
334 value.borrow().encode(out);
335 }
336}
337
338#[inline]
342pub fn encode_iter<I, B, T>(values: I, out: &mut dyn BufMut)
343where
344 I: Iterator<Item = B> + Clone,
345 B: Borrow<T>,
346 T: ?Sized + Encodable,
347{
348 let mut h = Header { list: true, payload_length: 0 };
349 for t in values.clone() {
350 h.payload_length += t.borrow().length();
351 }
352
353 h.encode(out);
354 for value in values {
355 value.borrow().encode(out);
356 }
357}
358
359#[inline]
361pub const fn length_of_length(payload_length: usize) -> usize {
362 if payload_length < 56 {
363 1
364 } else {
365 1 + (usize::BITS as usize / 8) - payload_length.leading_zeros() as usize / 8
366 }
367}
368
369#[inline]
370fn rlp_list_header<B, T>(values: &[B]) -> Header
371where
372 B: Borrow<T>,
373 T: ?Sized + Encodable,
374{
375 let mut h = Header { list: true, payload_length: 0 };
376 for value in values {
377 h.payload_length += value.borrow().length();
378 }
379 h
380}
381
382#[cfg(test)]
383mod tests {
384 use super::*;
385 use hex_literal::hex;
386
387 fn encoded_list<T: Encodable + Clone>(t: &[T]) -> BytesMut {
388 let mut out1 = BytesMut::new();
389 encode_list(t, &mut out1);
390
391 let v = t.to_vec();
392 assert_eq!(out1.len(), v.length());
393
394 let mut out2 = BytesMut::new();
395 v.encode(&mut out2);
396 assert_eq!(out1, out2);
397
398 out1
399 }
400
401 fn encoded_iter<T: Encodable>(iter: impl Iterator<Item = T> + Clone) -> BytesMut {
402 let mut out = BytesMut::new();
403 encode_iter(iter, &mut out);
404 out
405 }
406
407 #[test]
408 fn rlp_str() {
409 assert_eq!(encode("")[..], hex!("80")[..]);
410 assert_eq!(encode("{")[..], hex!("7b")[..]);
411 assert_eq!(encode("test str")[..], hex!("887465737420737472")[..]);
412 }
413
414 #[test]
415 fn rlp_strings() {
416 assert_eq!(encode(hex!(""))[..], hex!("80")[..]);
417 assert_eq!(encode(hex!("7B"))[..], hex!("7b")[..]);
418 assert_eq!(encode(hex!("80"))[..], hex!("8180")[..]);
419 assert_eq!(encode(hex!("ABBA"))[..], hex!("82abba")[..]);
420 }
421
422 #[test]
423 fn rlp_bool() {
424 assert_eq!(encode(true), hex!("01"));
425 assert_eq!(encode(false), hex!("80"));
426 }
427
428 fn c<T, U: From<T>>(
429 it: impl IntoIterator<Item = (T, &'static [u8])>,
430 ) -> impl Iterator<Item = (U, &'static [u8])> {
431 it.into_iter().map(|(k, v)| (k.into(), v))
432 }
433
434 fn u8_fixtures() -> impl IntoIterator<Item = (u8, &'static [u8])> {
435 vec![
436 (0, &hex!("80")[..]),
437 (1, &hex!("01")[..]),
438 (0x7F, &hex!("7F")[..]),
439 (0x80, &hex!("8180")[..]),
440 ]
441 }
442
443 fn u16_fixtures() -> impl IntoIterator<Item = (u16, &'static [u8])> {
444 c(u8_fixtures()).chain(vec![(0x400, &hex!("820400")[..])])
445 }
446
447 fn u32_fixtures() -> impl IntoIterator<Item = (u32, &'static [u8])> {
448 c(u16_fixtures())
449 .chain(vec![(0xFFCCB5, &hex!("83ffccb5")[..]), (0xFFCCB5DD, &hex!("84ffccb5dd")[..])])
450 }
451
452 fn u64_fixtures() -> impl IntoIterator<Item = (u64, &'static [u8])> {
453 c(u32_fixtures()).chain(vec![
454 (0xFFCCB5DDFF, &hex!("85ffccb5ddff")[..]),
455 (0xFFCCB5DDFFEE, &hex!("86ffccb5ddffee")[..]),
456 (0xFFCCB5DDFFEE14, &hex!("87ffccb5ddffee14")[..]),
457 (0xFFCCB5DDFFEE1483, &hex!("88ffccb5ddffee1483")[..]),
458 ])
459 }
460
461 fn u128_fixtures() -> impl IntoIterator<Item = (u128, &'static [u8])> {
462 c(u64_fixtures()).chain(vec![(
463 0x10203E405060708090A0B0C0D0E0F2,
464 &hex!("8f10203e405060708090a0b0c0d0e0f2")[..],
465 )])
466 }
467
468 macro_rules! uint_rlp_test {
469 ($fixtures:expr) => {
470 for (input, output) in $fixtures {
471 assert_eq!(encode(input), output, "encode({input})");
472 #[cfg(feature = "arrayvec")]
473 assert_eq!(&encode_fixed_size(&input)[..], output, "encode_fixed_size({input})");
474 }
475 };
476 }
477
478 #[test]
479 fn rlp_uints() {
480 uint_rlp_test!(u8_fixtures());
481 uint_rlp_test!(u16_fixtures());
482 uint_rlp_test!(u32_fixtures());
483 uint_rlp_test!(u64_fixtures());
484 uint_rlp_test!(u128_fixtures());
485 }
488
489 #[test]
565 fn rlp_list() {
566 assert_eq!(encoded_list::<u64>(&[]), &hex!("c0")[..]);
567 assert_eq!(encoded_list::<u8>(&[0x00u8]), &hex!("c180")[..]);
568 assert_eq!(encoded_list(&[0xFFCCB5_u64, 0xFFC0B5_u64]), &hex!("c883ffccb583ffc0b5")[..]);
569 }
570
571 #[test]
572 fn rlp_iter() {
573 assert_eq!(encoded_iter::<u64>([].into_iter()), &hex!("c0")[..]);
574 assert_eq!(
575 encoded_iter([0xFFCCB5_u64, 0xFFC0B5_u64].iter()),
576 &hex!("c883ffccb583ffc0b5")[..]
577 );
578 }
579
580 #[test]
581 fn to_be_bytes_trimmed() {
582 macro_rules! test_to_be_bytes_trimmed {
583 ($($x:expr => $expected:expr),+ $(,)?) => {$(
584 let be;
585 assert_eq!(to_be_bytes_trimmed!(be, $x), $expected);
586 )+};
587 }
588
589 test_to_be_bytes_trimmed! {
590 0u8 => [],
591 0u16 => [],
592 0u32 => [],
593 0u64 => [],
594 0usize => [],
595 0u128 => [],
596
597 1u8 => [1],
598 1u16 => [1],
599 1u32 => [1],
600 1u64 => [1],
601 1usize => [1],
602 1u128 => [1],
603
604 u8::MAX => [0xff],
605 u16::MAX => [0xff, 0xff],
606 u32::MAX => [0xff, 0xff, 0xff, 0xff],
607 u64::MAX => [0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff],
608 u128::MAX => [0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff],
609
610 1u8 => [1],
611 255u8 => [255],
612 256u16 => [1, 0],
613 65535u16 => [255, 255],
614 65536u32 => [1, 0, 0],
615 65536u64 => [1, 0, 0],
616 }
617 }
618}