1use crate::{Header, EMPTY_STRING_CODE};
2use bytes::{BufMut, Bytes, BytesMut};
3use core::{
4 borrow::Borrow,
5 marker::{PhantomData, PhantomPinned},
6 num::{NonZeroU128, NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU8, NonZeroUsize},
7};
8
9#[allow(unused_imports)]
10use alloc::vec::Vec;
11
12#[cfg(feature = "arrayvec")]
13use arrayvec::ArrayVec;
14
15pub trait Encodable {
17 fn encode(&self, out: &mut dyn BufMut);
19
20 #[inline]
26 fn length(&self) -> usize {
27 let mut out = Vec::new();
28 self.encode(&mut out);
29 out.len()
30 }
31}
32
33fn _assert_trait_object(_b: &dyn Encodable) {}
36
37pub unsafe trait MaxEncodedLen<const LEN: usize>: Encodable {}
43
44pub unsafe trait MaxEncodedLenAssoc: Encodable {
50 const LEN: usize;
52}
53
54#[macro_export]
60macro_rules! impl_max_encoded_len {
61 ($t:ty, $len:expr) => {
62 unsafe impl $crate::MaxEncodedLen<{ $len }> for $t {}
63 unsafe impl $crate::MaxEncodedLenAssoc for $t {
64 const LEN: usize = $len;
65 }
66 };
67}
68
69macro_rules! to_be_bytes_trimmed {
70 ($be:ident, $x:expr) => {{
71 $be = $x.to_be_bytes();
72 &$be[($x.leading_zeros() / 8) as usize..]
73 }};
74}
75pub(crate) use to_be_bytes_trimmed;
76
77impl Encodable for [u8] {
78 #[inline]
79 fn length(&self) -> usize {
80 let mut len = self.len();
81 if len != 1 || self[0] >= EMPTY_STRING_CODE {
82 len += length_of_length(len);
83 }
84 len
85 }
86
87 #[inline]
88 fn encode(&self, out: &mut dyn BufMut) {
89 if self.len() != 1 || self[0] >= EMPTY_STRING_CODE {
90 Header { list: false, payload_length: self.len() }.encode(out);
91 }
92 out.put_slice(self);
93 }
94}
95
96impl<T: ?Sized> Encodable for PhantomData<T> {
97 #[inline]
98 fn length(&self) -> usize {
99 0
100 }
101
102 #[inline]
103 fn encode(&self, _out: &mut dyn BufMut) {}
104}
105
106impl Encodable for PhantomPinned {
107 #[inline]
108 fn length(&self) -> usize {
109 0
110 }
111
112 #[inline]
113 fn encode(&self, _out: &mut dyn BufMut) {}
114}
115
116impl<const N: usize> Encodable for [u8; N] {
117 #[inline]
118 fn length(&self) -> usize {
119 self[..].length()
120 }
121
122 #[inline]
123 fn encode(&self, out: &mut dyn BufMut) {
124 self[..].encode(out);
125 }
126}
127
128unsafe impl<const N: usize> MaxEncodedLenAssoc for [u8; N] {
129 const LEN: usize = N + length_of_length(N);
130}
131
132impl Encodable for str {
133 #[inline]
134 fn length(&self) -> usize {
135 self.as_bytes().length()
136 }
137
138 #[inline]
139 fn encode(&self, out: &mut dyn BufMut) {
140 self.as_bytes().encode(out)
141 }
142}
143
144impl Encodable for bool {
145 #[inline]
146 fn length(&self) -> usize {
147 1
149 }
150
151 #[inline]
152 fn encode(&self, out: &mut dyn BufMut) {
153 out.put_u8(if *self { 1 } else { EMPTY_STRING_CODE });
155 }
156}
157
158impl_max_encoded_len!(bool, <u8 as MaxEncodedLenAssoc>::LEN);
159
160macro_rules! uint_impl {
161 ($($t:ty),+ $(,)?) => {$(
162 impl Encodable for $t {
163 #[inline]
164 fn length(&self) -> usize {
165 let x = *self;
166 if x < EMPTY_STRING_CODE as $t {
167 1
168 } else {
169 1 + (<$t>::BITS as usize / 8) - (x.leading_zeros() as usize / 8)
170 }
171 }
172
173 #[inline]
174 fn encode(&self, out: &mut dyn BufMut) {
175 let x = *self;
176 if x == 0 {
177 out.put_u8(EMPTY_STRING_CODE);
178 } else if x < EMPTY_STRING_CODE as $t {
179 out.put_u8(x as u8);
180 } else {
181 let be;
182 let be = to_be_bytes_trimmed!(be, x);
183 out.put_u8(EMPTY_STRING_CODE + be.len() as u8);
184 out.put_slice(be);
185 }
186 }
187 }
188
189 impl_max_encoded_len!($t, {
190 let bytes = <$t>::BITS as usize / 8;
191 bytes + length_of_length(bytes)
192 });
193 )+};
194}
195
196uint_impl!(u8, u16, u32, u64, usize, u128);
197
198macro_rules! nonzero_uint_impl {
199 ($($t:ty => $inner:ty),+ $(,)?) => {$(
200 impl Encodable for $t {
201 #[inline]
202 fn length(&self) -> usize {
203 self.get().length()
204 }
205
206 #[inline]
207 fn encode(&self, out: &mut dyn BufMut) {
208 self.get().encode(out);
209 }
210 }
211
212 impl_max_encoded_len!($t, <$inner as MaxEncodedLenAssoc>::LEN);
213 )+};
214}
215
216nonzero_uint_impl! {
217 NonZeroU8 => u8,
218 NonZeroU16 => u16,
219 NonZeroU32 => u32,
220 NonZeroU64 => u64,
221 NonZeroUsize => usize,
222 NonZeroU128 => u128,
223}
224
225impl<T: Encodable> Encodable for Vec<T> {
226 #[inline]
227 fn length(&self) -> usize {
228 list_length(self)
229 }
230
231 #[inline]
232 fn encode(&self, out: &mut dyn BufMut) {
233 encode_list(self, out)
234 }
235}
236
237macro_rules! deref_impl {
238 ($($(#[$attr:meta])* [$($gen:tt)*] $t:ty),+ $(,)?) => {$(
239 $(#[$attr])*
240 impl<$($gen)*> Encodable for $t {
241 #[inline]
242 fn length(&self) -> usize {
243 (**self).length()
244 }
245
246 #[inline]
247 fn encode(&self, out: &mut dyn BufMut) {
248 (**self).encode(out)
249 }
250 }
251 )+};
252}
253
254deref_impl! {
255 [] alloc::string::String,
256 [] Bytes,
257 [] BytesMut,
258 #[cfg(feature = "arrayvec")]
259 [const N: usize] ArrayVec<u8, N>,
260 [T: ?Sized + Encodable] &T,
261 [T: ?Sized + Encodable] &mut T,
262 [T: ?Sized + Encodable] alloc::boxed::Box<T>,
263 [T: ?Sized + alloc::borrow::ToOwned + Encodable] alloc::borrow::Cow<'_, T>,
264 [T: ?Sized + Encodable] alloc::rc::Rc<T>,
265 #[cfg(target_has_atomic = "ptr")]
266 [T: ?Sized + Encodable] alloc::sync::Arc<T>,
267}
268
269#[cfg(any(feature = "std", feature = "core-net"))]
270mod std_support {
271 use super::*;
272 #[cfg(all(feature = "core-net", not(feature = "std")))]
273 use core::net::{IpAddr, Ipv4Addr, Ipv6Addr};
274 #[cfg(feature = "std")]
275 use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
276
277 impl Encodable for IpAddr {
278 #[inline]
279 fn length(&self) -> usize {
280 match self {
281 Self::V4(ip) => ip.length(),
282 Self::V6(ip) => ip.length(),
283 }
284 }
285
286 #[inline]
287 fn encode(&self, out: &mut dyn BufMut) {
288 match self {
289 Self::V4(ip) => ip.encode(out),
290 Self::V6(ip) => ip.encode(out),
291 }
292 }
293 }
294
295 impl Encodable for Ipv4Addr {
296 #[inline]
297 fn length(&self) -> usize {
298 self.octets().length()
299 }
300
301 #[inline]
302 fn encode(&self, out: &mut dyn BufMut) {
303 self.octets().encode(out)
304 }
305 }
306
307 impl Encodable for Ipv6Addr {
308 #[inline]
309 fn length(&self) -> usize {
310 self.octets().length()
311 }
312
313 #[inline]
314 fn encode(&self, out: &mut dyn BufMut) {
315 self.octets().encode(out)
316 }
317 }
318}
319
320#[inline]
324pub fn encode<T: Encodable>(value: T) -> Vec<u8> {
325 let mut out = Vec::with_capacity(value.length());
326 value.encode(&mut out);
327 out
328}
329
330#[cfg(feature = "arrayvec")]
332#[inline]
333pub fn encode_fixed_size<T: MaxEncodedLen<LEN>, const LEN: usize>(value: &T) -> ArrayVec<u8, LEN> {
334 let mut vec = ArrayVec::<u8, LEN>::new();
335
336 let mut out = unsafe { core::slice::from_raw_parts_mut(vec.as_mut_ptr(), LEN) };
338 value.encode(&mut out);
339 let written = LEN - out.len();
340
341 unsafe { vec.set_len(written) };
343 vec
344}
345
346#[inline]
348pub fn list_length<B, T>(list: &[B]) -> usize
349where
350 B: Borrow<T>,
351 T: ?Sized + Encodable,
352{
353 let payload_length = rlp_list_header(list).payload_length;
354 payload_length + length_of_length(payload_length)
355}
356
357#[inline]
359pub fn encode_list<B, T>(values: &[B], out: &mut dyn BufMut)
360where
361 B: Borrow<T>,
362 T: ?Sized + Encodable,
363{
364 rlp_list_header(values).encode(out);
365 for value in values {
366 value.borrow().encode(out);
367 }
368}
369
370#[inline]
374pub fn encode_iter<I, B, T>(values: I, out: &mut dyn BufMut)
375where
376 I: Iterator<Item = B> + Clone,
377 B: Borrow<T>,
378 T: ?Sized + Encodable,
379{
380 let mut h = Header { list: true, payload_length: 0 };
381 for t in values.clone() {
382 h.payload_length += t.borrow().length();
383 }
384
385 h.encode(out);
386 for value in values {
387 value.borrow().encode(out);
388 }
389}
390
391#[inline]
393pub const fn length_of_length(payload_length: usize) -> usize {
394 if payload_length < 56 {
395 1
396 } else {
397 1 + (usize::BITS as usize / 8) - payload_length.leading_zeros() as usize / 8
398 }
399}
400
401#[inline]
402fn rlp_list_header<B, T>(values: &[B]) -> Header
403where
404 B: Borrow<T>,
405 T: ?Sized + Encodable,
406{
407 let mut h = Header { list: true, payload_length: 0 };
408 for value in values {
409 h.payload_length += value.borrow().length();
410 }
411 h
412}
413
414#[cfg(test)]
415mod tests {
416 use super::*;
417 use core::num::{NonZeroU128, NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU8, NonZeroUsize};
418 use hex_literal::hex;
419
420 fn encoded_list<T: Encodable + Clone>(t: &[T]) -> BytesMut {
421 let mut out1 = BytesMut::new();
422 encode_list(t, &mut out1);
423
424 let v = t.to_vec();
425 assert_eq!(out1.len(), v.length());
426
427 let mut out2 = BytesMut::new();
428 v.encode(&mut out2);
429 assert_eq!(out1, out2);
430
431 out1
432 }
433
434 fn encoded_iter<T: Encodable>(iter: impl Iterator<Item = T> + Clone) -> BytesMut {
435 let mut out = BytesMut::new();
436 encode_iter(iter, &mut out);
437 out
438 }
439
440 #[test]
441 fn rlp_str() {
442 assert_eq!(encode("")[..], hex!("80")[..]);
443 assert_eq!(encode("{")[..], hex!("7b")[..]);
444 assert_eq!(encode("test str")[..], hex!("887465737420737472")[..]);
445 }
446
447 #[test]
448 fn rlp_strings() {
449 assert_eq!(encode(hex!(""))[..], hex!("80")[..]);
450 assert_eq!(encode(hex!("7B"))[..], hex!("7b")[..]);
451 assert_eq!(encode(hex!("80"))[..], hex!("8180")[..]);
452 assert_eq!(encode(hex!("ABBA"))[..], hex!("82abba")[..]);
453 }
454
455 #[test]
456 fn rlp_bool() {
457 assert_eq!(encode(true), hex!("01"));
458 assert_eq!(encode(false), hex!("80"));
459 }
460
461 fn c<T, U: From<T>>(
462 it: impl IntoIterator<Item = (T, &'static [u8])>,
463 ) -> impl Iterator<Item = (U, &'static [u8])> {
464 it.into_iter().map(|(k, v)| (k.into(), v))
465 }
466
467 fn u8_fixtures() -> impl IntoIterator<Item = (u8, &'static [u8])> {
468 vec![
469 (0, &hex!("80")[..]),
470 (1, &hex!("01")[..]),
471 (0x7F, &hex!("7F")[..]),
472 (0x80, &hex!("8180")[..]),
473 ]
474 }
475
476 fn u16_fixtures() -> impl IntoIterator<Item = (u16, &'static [u8])> {
477 c(u8_fixtures()).chain(vec![(0x400, &hex!("820400")[..])])
478 }
479
480 fn u32_fixtures() -> impl IntoIterator<Item = (u32, &'static [u8])> {
481 c(u16_fixtures())
482 .chain(vec![(0xFFCCB5, &hex!("83ffccb5")[..]), (0xFFCCB5DD, &hex!("84ffccb5dd")[..])])
483 }
484
485 fn u64_fixtures() -> impl IntoIterator<Item = (u64, &'static [u8])> {
486 c(u32_fixtures()).chain(vec![
487 (0xFFCCB5DDFF, &hex!("85ffccb5ddff")[..]),
488 (0xFFCCB5DDFFEE, &hex!("86ffccb5ddffee")[..]),
489 (0xFFCCB5DDFFEE14, &hex!("87ffccb5ddffee14")[..]),
490 (0xFFCCB5DDFFEE1483, &hex!("88ffccb5ddffee1483")[..]),
491 ])
492 }
493
494 fn u128_fixtures() -> impl IntoIterator<Item = (u128, &'static [u8])> {
495 c(u64_fixtures()).chain(vec![(
496 0x10203E405060708090A0B0C0D0E0F2,
497 &hex!("8f10203e405060708090a0b0c0d0e0f2")[..],
498 )])
499 }
500
501 macro_rules! uint_rlp_test {
502 ($fixtures:expr) => {
503 for (input, output) in $fixtures {
504 assert_eq!(encode(input), output, "encode({input})");
505 #[cfg(feature = "arrayvec")]
506 assert_eq!(&encode_fixed_size(&input)[..], output, "encode_fixed_size({input})");
507 }
508 };
509 }
510
511 #[test]
512 fn rlp_uints() {
513 uint_rlp_test!(u8_fixtures());
514 uint_rlp_test!(u16_fixtures());
515 uint_rlp_test!(u32_fixtures());
516 uint_rlp_test!(u64_fixtures());
517 uint_rlp_test!(u128_fixtures());
518 }
521
522 #[test]
523 fn rlp_nonzero_uints() {
524 uint_rlp_test!([(NonZeroU8::new(1).unwrap(), &hex!("01")[..])]);
525 uint_rlp_test!([(NonZeroU16::new(0x400).unwrap(), &hex!("820400")[..])]);
526 uint_rlp_test!([(NonZeroU32::new(0xFFCCB5).unwrap(), &hex!("83ffccb5")[..])]);
527 uint_rlp_test!([(
528 NonZeroU64::new(0xFFCCB5DDFFEE1483).unwrap(),
529 &hex!("88ffccb5ddffee1483")[..]
530 )]);
531 uint_rlp_test!([(NonZeroUsize::new(0x80).unwrap(), &hex!("8180")[..])]);
532 uint_rlp_test!([(
533 NonZeroU128::new(0x10203E405060708090A0B0C0D0E0F2).unwrap(),
534 &hex!("8f10203e405060708090a0b0c0d0e0f2")[..],
535 )]);
536 }
537
538 #[test]
614 fn rlp_list() {
615 assert_eq!(encoded_list::<u64>(&[]), &hex!("c0")[..]);
616 assert_eq!(encoded_list::<u8>(&[0x00u8]), &hex!("c180")[..]);
617 assert_eq!(encoded_list(&[0xFFCCB5_u64, 0xFFC0B5_u64]), &hex!("c883ffccb583ffc0b5")[..]);
618 }
619
620 #[test]
621 fn rlp_iter() {
622 assert_eq!(encoded_iter::<u64>([].into_iter()), &hex!("c0")[..]);
623 assert_eq!(
624 encoded_iter([0xFFCCB5_u64, 0xFFC0B5_u64].iter()),
625 &hex!("c883ffccb583ffc0b5")[..]
626 );
627 }
628
629 #[test]
630 fn to_be_bytes_trimmed() {
631 macro_rules! test_to_be_bytes_trimmed {
632 ($($x:expr => $expected:expr),+ $(,)?) => {$(
633 let be;
634 assert_eq!(to_be_bytes_trimmed!(be, $x), $expected);
635 )+};
636 }
637
638 test_to_be_bytes_trimmed! {
639 0u8 => [],
640 0u16 => [],
641 0u32 => [],
642 0u64 => [],
643 0usize => [],
644 0u128 => [],
645
646 1u8 => [1],
647 1u16 => [1],
648 1u32 => [1],
649 1u64 => [1],
650 1usize => [1],
651 1u128 => [1],
652
653 u8::MAX => [0xff],
654 u16::MAX => [0xff, 0xff],
655 u32::MAX => [0xff, 0xff, 0xff, 0xff],
656 u64::MAX => [0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff],
657 u128::MAX => [0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff],
658
659 1u8 => [1],
660 255u8 => [255],
661 256u16 => [1, 0],
662 65535u16 => [255, 255],
663 65536u32 => [1, 0, 0],
664 65536u64 => [1, 0, 0],
665 }
666 }
667}