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(any(feature = "std", feature = "core-net"))]
241mod std_support {
242 use super::*;
243 #[cfg(all(feature = "core-net", not(feature = "std")))]
244 use core::net::{IpAddr, Ipv4Addr, Ipv6Addr};
245 #[cfg(feature = "std")]
246 use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
247
248 impl Encodable for IpAddr {
249 #[inline]
250 fn length(&self) -> usize {
251 match self {
252 Self::V4(ip) => ip.length(),
253 Self::V6(ip) => ip.length(),
254 }
255 }
256
257 #[inline]
258 fn encode(&self, out: &mut dyn BufMut) {
259 match self {
260 Self::V4(ip) => ip.encode(out),
261 Self::V6(ip) => ip.encode(out),
262 }
263 }
264 }
265
266 impl Encodable for Ipv4Addr {
267 #[inline]
268 fn length(&self) -> usize {
269 self.octets().length()
270 }
271
272 #[inline]
273 fn encode(&self, out: &mut dyn BufMut) {
274 self.octets().encode(out)
275 }
276 }
277
278 impl Encodable for Ipv6Addr {
279 #[inline]
280 fn length(&self) -> usize {
281 self.octets().length()
282 }
283
284 #[inline]
285 fn encode(&self, out: &mut dyn BufMut) {
286 self.octets().encode(out)
287 }
288 }
289}
290
291#[inline]
295pub fn encode<T: Encodable>(value: T) -> Vec<u8> {
296 let mut out = Vec::with_capacity(value.length());
297 value.encode(&mut out);
298 out
299}
300
301#[cfg(feature = "arrayvec")]
303#[inline]
304pub fn encode_fixed_size<T: MaxEncodedLen<LEN>, const LEN: usize>(value: &T) -> ArrayVec<u8, LEN> {
305 let mut vec = ArrayVec::<u8, LEN>::new();
306
307 let mut out = unsafe { core::slice::from_raw_parts_mut(vec.as_mut_ptr(), LEN) };
309 value.encode(&mut out);
310 let written = LEN - out.len();
311
312 unsafe { vec.set_len(written) };
314 vec
315}
316
317#[inline]
319pub fn list_length<B, T>(list: &[B]) -> usize
320where
321 B: Borrow<T>,
322 T: ?Sized + Encodable,
323{
324 let payload_length = rlp_list_header(list).payload_length;
325 payload_length + length_of_length(payload_length)
326}
327
328#[inline]
330pub fn encode_list<B, T>(values: &[B], out: &mut dyn BufMut)
331where
332 B: Borrow<T>,
333 T: ?Sized + Encodable,
334{
335 rlp_list_header(values).encode(out);
336 for value in values {
337 value.borrow().encode(out);
338 }
339}
340
341#[inline]
345pub fn encode_iter<I, B, T>(values: I, out: &mut dyn BufMut)
346where
347 I: Iterator<Item = B> + Clone,
348 B: Borrow<T>,
349 T: ?Sized + Encodable,
350{
351 let mut h = Header { list: true, payload_length: 0 };
352 for t in values.clone() {
353 h.payload_length += t.borrow().length();
354 }
355
356 h.encode(out);
357 for value in values {
358 value.borrow().encode(out);
359 }
360}
361
362#[inline]
364pub const fn length_of_length(payload_length: usize) -> usize {
365 if payload_length < 56 {
366 1
367 } else {
368 1 + (usize::BITS as usize / 8) - payload_length.leading_zeros() as usize / 8
369 }
370}
371
372#[inline]
373fn rlp_list_header<B, T>(values: &[B]) -> Header
374where
375 B: Borrow<T>,
376 T: ?Sized + Encodable,
377{
378 let mut h = Header { list: true, payload_length: 0 };
379 for value in values {
380 h.payload_length += value.borrow().length();
381 }
382 h
383}
384
385#[cfg(test)]
386mod tests {
387 use super::*;
388 use hex_literal::hex;
389
390 fn encoded_list<T: Encodable + Clone>(t: &[T]) -> BytesMut {
391 let mut out1 = BytesMut::new();
392 encode_list(t, &mut out1);
393
394 let v = t.to_vec();
395 assert_eq!(out1.len(), v.length());
396
397 let mut out2 = BytesMut::new();
398 v.encode(&mut out2);
399 assert_eq!(out1, out2);
400
401 out1
402 }
403
404 fn encoded_iter<T: Encodable>(iter: impl Iterator<Item = T> + Clone) -> BytesMut {
405 let mut out = BytesMut::new();
406 encode_iter(iter, &mut out);
407 out
408 }
409
410 #[test]
411 fn rlp_str() {
412 assert_eq!(encode("")[..], hex!("80")[..]);
413 assert_eq!(encode("{")[..], hex!("7b")[..]);
414 assert_eq!(encode("test str")[..], hex!("887465737420737472")[..]);
415 }
416
417 #[test]
418 fn rlp_strings() {
419 assert_eq!(encode(hex!(""))[..], hex!("80")[..]);
420 assert_eq!(encode(hex!("7B"))[..], hex!("7b")[..]);
421 assert_eq!(encode(hex!("80"))[..], hex!("8180")[..]);
422 assert_eq!(encode(hex!("ABBA"))[..], hex!("82abba")[..]);
423 }
424
425 #[test]
426 fn rlp_bool() {
427 assert_eq!(encode(true), hex!("01"));
428 assert_eq!(encode(false), hex!("80"));
429 }
430
431 fn c<T, U: From<T>>(
432 it: impl IntoIterator<Item = (T, &'static [u8])>,
433 ) -> impl Iterator<Item = (U, &'static [u8])> {
434 it.into_iter().map(|(k, v)| (k.into(), v))
435 }
436
437 fn u8_fixtures() -> impl IntoIterator<Item = (u8, &'static [u8])> {
438 vec![
439 (0, &hex!("80")[..]),
440 (1, &hex!("01")[..]),
441 (0x7F, &hex!("7F")[..]),
442 (0x80, &hex!("8180")[..]),
443 ]
444 }
445
446 fn u16_fixtures() -> impl IntoIterator<Item = (u16, &'static [u8])> {
447 c(u8_fixtures()).chain(vec![(0x400, &hex!("820400")[..])])
448 }
449
450 fn u32_fixtures() -> impl IntoIterator<Item = (u32, &'static [u8])> {
451 c(u16_fixtures())
452 .chain(vec![(0xFFCCB5, &hex!("83ffccb5")[..]), (0xFFCCB5DD, &hex!("84ffccb5dd")[..])])
453 }
454
455 fn u64_fixtures() -> impl IntoIterator<Item = (u64, &'static [u8])> {
456 c(u32_fixtures()).chain(vec![
457 (0xFFCCB5DDFF, &hex!("85ffccb5ddff")[..]),
458 (0xFFCCB5DDFFEE, &hex!("86ffccb5ddffee")[..]),
459 (0xFFCCB5DDFFEE14, &hex!("87ffccb5ddffee14")[..]),
460 (0xFFCCB5DDFFEE1483, &hex!("88ffccb5ddffee1483")[..]),
461 ])
462 }
463
464 fn u128_fixtures() -> impl IntoIterator<Item = (u128, &'static [u8])> {
465 c(u64_fixtures()).chain(vec![(
466 0x10203E405060708090A0B0C0D0E0F2,
467 &hex!("8f10203e405060708090a0b0c0d0e0f2")[..],
468 )])
469 }
470
471 macro_rules! uint_rlp_test {
472 ($fixtures:expr) => {
473 for (input, output) in $fixtures {
474 assert_eq!(encode(input), output, "encode({input})");
475 #[cfg(feature = "arrayvec")]
476 assert_eq!(&encode_fixed_size(&input)[..], output, "encode_fixed_size({input})");
477 }
478 };
479 }
480
481 #[test]
482 fn rlp_uints() {
483 uint_rlp_test!(u8_fixtures());
484 uint_rlp_test!(u16_fixtures());
485 uint_rlp_test!(u32_fixtures());
486 uint_rlp_test!(u64_fixtures());
487 uint_rlp_test!(u128_fixtures());
488 }
491
492 #[test]
568 fn rlp_list() {
569 assert_eq!(encoded_list::<u64>(&[]), &hex!("c0")[..]);
570 assert_eq!(encoded_list::<u8>(&[0x00u8]), &hex!("c180")[..]);
571 assert_eq!(encoded_list(&[0xFFCCB5_u64, 0xFFC0B5_u64]), &hex!("c883ffccb583ffc0b5")[..]);
572 }
573
574 #[test]
575 fn rlp_iter() {
576 assert_eq!(encoded_iter::<u64>([].into_iter()), &hex!("c0")[..]);
577 assert_eq!(
578 encoded_iter([0xFFCCB5_u64, 0xFFC0B5_u64].iter()),
579 &hex!("c883ffccb583ffc0b5")[..]
580 );
581 }
582
583 #[test]
584 fn to_be_bytes_trimmed() {
585 macro_rules! test_to_be_bytes_trimmed {
586 ($($x:expr => $expected:expr),+ $(,)?) => {$(
587 let be;
588 assert_eq!(to_be_bytes_trimmed!(be, $x), $expected);
589 )+};
590 }
591
592 test_to_be_bytes_trimmed! {
593 0u8 => [],
594 0u16 => [],
595 0u32 => [],
596 0u64 => [],
597 0usize => [],
598 0u128 => [],
599
600 1u8 => [1],
601 1u16 => [1],
602 1u32 => [1],
603 1u64 => [1],
604 1usize => [1],
605 1u128 => [1],
606
607 u8::MAX => [0xff],
608 u16::MAX => [0xff, 0xff],
609 u32::MAX => [0xff, 0xff, 0xff, 0xff],
610 u64::MAX => [0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff],
611 u128::MAX => [0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff],
612
613 1u8 => [1],
614 255u8 => [255],
615 256u16 => [1, 0],
616 65535u16 => [255, 255],
617 65536u32 => [1, 0, 0],
618 65536u64 => [1, 0, 0],
619 }
620 }
621}