reth_eth_wire_types/
capability.rs1use crate::EthVersion;
4use alloy_rlp::{Decodable, Encodable, RlpDecodable, RlpEncodable};
5use bytes::BufMut;
6use reth_codecs_derive::add_arbitrary_tests;
7use std::{borrow::Cow, fmt};
8
9#[add_arbitrary_tests(rlp)]
11#[derive(Clone, Debug, PartialEq, Eq, RlpEncodable, RlpDecodable, Default, Hash)]
12#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
13pub struct Capability {
14 pub name: Cow<'static, str>,
16 pub version: usize,
18}
19
20impl Capability {
21 pub const fn new(name: String, version: usize) -> Self {
23 Self { name: Cow::Owned(name), version }
24 }
25
26 pub const fn new_static(name: &'static str, version: usize) -> Self {
28 Self { name: Cow::Borrowed(name), version }
29 }
30
31 pub const fn eth(version: EthVersion) -> Self {
33 Self::new_static("eth", version as usize)
34 }
35
36 pub const fn eth_66() -> Self {
38 Self::eth(EthVersion::Eth66)
39 }
40
41 pub const fn eth_67() -> Self {
43 Self::eth(EthVersion::Eth67)
44 }
45
46 pub const fn eth_68() -> Self {
48 Self::eth(EthVersion::Eth68)
49 }
50
51 #[inline]
53 pub fn is_eth_v66(&self) -> bool {
54 self.name == "eth" && self.version == 66
55 }
56
57 #[inline]
59 pub fn is_eth_v67(&self) -> bool {
60 self.name == "eth" && self.version == 67
61 }
62
63 #[inline]
65 pub fn is_eth_v68(&self) -> bool {
66 self.name == "eth" && self.version == 68
67 }
68
69 #[inline]
71 pub fn is_eth(&self) -> bool {
72 self.is_eth_v66() || self.is_eth_v67() || self.is_eth_v68()
73 }
74}
75
76impl fmt::Display for Capability {
77 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
78 write!(f, "{}/{}", self.name, self.version)
79 }
80}
81
82impl From<EthVersion> for Capability {
83 #[inline]
84 fn from(value: EthVersion) -> Self {
85 Self::eth(value)
86 }
87}
88
89#[cfg(any(test, feature = "arbitrary"))]
90impl<'a> arbitrary::Arbitrary<'a> for Capability {
91 fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> {
92 let version = u.int_in_range(0..=32)?; let name = String::arbitrary(u)?; Ok(Self::new(name, version))
95 }
96}
97
98#[derive(Debug, Clone, Eq, PartialEq)]
100pub struct Capabilities {
101 inner: Vec<Capability>,
103 eth_66: bool,
104 eth_67: bool,
105 eth_68: bool,
106}
107
108impl Capabilities {
109 #[inline]
111 pub fn capabilities(&self) -> &[Capability] {
112 &self.inner
113 }
114
115 #[inline]
117 pub fn into_inner(self) -> Vec<Capability> {
118 self.inner
119 }
120
121 #[inline]
123 pub const fn supports_eth(&self) -> bool {
124 self.eth_68 || self.eth_67 || self.eth_66
125 }
126
127 #[inline]
129 pub const fn supports_eth_v66(&self) -> bool {
130 self.eth_66
131 }
132
133 #[inline]
135 pub const fn supports_eth_v67(&self) -> bool {
136 self.eth_67
137 }
138
139 #[inline]
141 pub const fn supports_eth_v68(&self) -> bool {
142 self.eth_68
143 }
144}
145
146impl From<Vec<Capability>> for Capabilities {
147 fn from(value: Vec<Capability>) -> Self {
148 Self {
149 eth_66: value.iter().any(Capability::is_eth_v66),
150 eth_67: value.iter().any(Capability::is_eth_v67),
151 eth_68: value.iter().any(Capability::is_eth_v68),
152 inner: value,
153 }
154 }
155}
156
157impl Encodable for Capabilities {
158 fn encode(&self, out: &mut dyn BufMut) {
159 self.inner.encode(out)
160 }
161}
162
163impl Decodable for Capabilities {
164 fn decode(buf: &mut &[u8]) -> alloy_rlp::Result<Self> {
165 let inner = Vec::<Capability>::decode(buf)?;
166
167 Ok(Self {
168 eth_66: inner.iter().any(Capability::is_eth_v66),
169 eth_67: inner.iter().any(Capability::is_eth_v67),
170 eth_68: inner.iter().any(Capability::is_eth_v68),
171 inner,
172 })
173 }
174}