reth_eth_wire_types/
capability.rs1use crate::{EthMessageID, EthVersion};
4use alloc::{borrow::Cow, string::String, vec::Vec};
5use alloy_primitives::bytes::Bytes;
6use alloy_rlp::{Decodable, Encodable, RlpDecodable, RlpEncodable};
7use bytes::BufMut;
8use core::fmt;
9use reth_codecs_derive::add_arbitrary_tests;
10
11#[derive(Debug, Clone, Eq, PartialEq)]
13#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
14pub struct RawCapabilityMessage {
15 pub id: usize,
17 pub payload: Bytes,
19}
20
21impl RawCapabilityMessage {
22 pub const fn new(id: usize, payload: Bytes) -> Self {
24 Self { id, payload }
25 }
26
27 pub const fn eth(id: EthMessageID, payload: Bytes) -> Self {
33 Self::new(id.to_u8() as usize, payload)
34 }
35}
36
37impl Encodable for RawCapabilityMessage {
38 fn encode(&self, out: &mut dyn BufMut) {
40 self.id.encode(out);
41 out.put_slice(&self.payload);
42 }
43
44 fn length(&self) -> usize {
46 self.id.length() + self.payload.len()
47 }
48}
49
50impl Decodable for RawCapabilityMessage {
51 fn decode(buf: &mut &[u8]) -> alloy_rlp::Result<Self> {
53 let id = usize::decode(buf)?;
54 let payload = Bytes::copy_from_slice(buf);
55 *buf = &buf[buf.len()..];
56
57 Ok(Self { id, payload })
58 }
59}
60
61#[add_arbitrary_tests(rlp)]
63#[derive(Clone, Debug, PartialEq, Eq, RlpEncodable, RlpDecodable, Default, Hash)]
64#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
65pub struct Capability {
66 pub name: Cow<'static, str>,
68 pub version: usize,
70}
71
72impl Capability {
73 pub const fn new(name: String, version: usize) -> Self {
75 Self { name: Cow::Owned(name), version }
76 }
77
78 pub const fn new_static(name: &'static str, version: usize) -> Self {
80 Self { name: Cow::Borrowed(name), version }
81 }
82
83 pub const fn eth(version: EthVersion) -> Self {
85 Self::new_static("eth", version as usize)
86 }
87
88 pub const fn eth_66() -> Self {
90 Self::eth(EthVersion::Eth66)
91 }
92
93 pub const fn eth_67() -> Self {
95 Self::eth(EthVersion::Eth67)
96 }
97
98 pub const fn eth_68() -> Self {
100 Self::eth(EthVersion::Eth68)
101 }
102
103 pub const fn eth_69() -> Self {
105 Self::eth(EthVersion::Eth69)
106 }
107
108 pub const fn eth_70() -> Self {
110 Self::eth(EthVersion::Eth70)
111 }
112
113 #[inline]
115 pub fn is_eth_v66(&self) -> bool {
116 self.name == "eth" && self.version == 66
117 }
118
119 #[inline]
121 pub fn is_eth_v67(&self) -> bool {
122 self.name == "eth" && self.version == 67
123 }
124
125 #[inline]
127 pub fn is_eth_v68(&self) -> bool {
128 self.name == "eth" && self.version == 68
129 }
130
131 #[inline]
133 pub fn is_eth_v69(&self) -> bool {
134 self.name == "eth" && self.version == 69
135 }
136
137 #[inline]
139 pub fn is_eth_v70(&self) -> bool {
140 self.name == "eth" && self.version == 70
141 }
142
143 #[inline]
145 pub fn is_eth(&self) -> bool {
146 self.is_eth_v66() ||
147 self.is_eth_v67() ||
148 self.is_eth_v68() ||
149 self.is_eth_v69() ||
150 self.is_eth_v70()
151 }
152}
153
154impl fmt::Display for Capability {
155 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
156 write!(f, "{}/{}", self.name, self.version)
157 }
158}
159
160impl From<EthVersion> for Capability {
161 #[inline]
162 fn from(value: EthVersion) -> Self {
163 Self::eth(value)
164 }
165}
166
167#[cfg(any(test, feature = "arbitrary"))]
168impl<'a> arbitrary::Arbitrary<'a> for Capability {
169 fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> {
170 let version = u.int_in_range(66..=70)?; Ok(Self::new_static("eth", version))
173 }
174}
175
176#[derive(Debug, Clone, Eq, PartialEq)]
178pub struct Capabilities {
179 inner: Vec<Capability>,
181 eth_66: bool,
182 eth_67: bool,
183 eth_68: bool,
184 eth_69: bool,
185 eth_70: bool,
186}
187
188impl Capabilities {
189 pub fn new(value: Vec<Capability>) -> Self {
191 Self {
192 eth_66: value.iter().any(Capability::is_eth_v66),
193 eth_67: value.iter().any(Capability::is_eth_v67),
194 eth_68: value.iter().any(Capability::is_eth_v68),
195 eth_69: value.iter().any(Capability::is_eth_v69),
196 eth_70: value.iter().any(Capability::is_eth_v70),
197 inner: value,
198 }
199 }
200 #[inline]
202 pub fn capabilities(&self) -> &[Capability] {
203 &self.inner
204 }
205
206 #[inline]
208 pub fn into_inner(self) -> Vec<Capability> {
209 self.inner
210 }
211
212 #[inline]
214 pub const fn supports_eth(&self) -> bool {
215 self.eth_70 || self.eth_69 || self.eth_68 || self.eth_67 || self.eth_66
216 }
217
218 #[inline]
220 pub const fn supports_eth_v66(&self) -> bool {
221 self.eth_66
222 }
223
224 #[inline]
226 pub const fn supports_eth_v67(&self) -> bool {
227 self.eth_67
228 }
229
230 #[inline]
232 pub const fn supports_eth_v68(&self) -> bool {
233 self.eth_68
234 }
235
236 #[inline]
238 pub const fn supports_eth_v69(&self) -> bool {
239 self.eth_69
240 }
241
242 #[inline]
244 pub const fn supports_eth_v70(&self) -> bool {
245 self.eth_70
246 }
247}
248
249impl From<Vec<Capability>> for Capabilities {
250 fn from(value: Vec<Capability>) -> Self {
251 Self::new(value)
252 }
253}
254
255impl Encodable for Capabilities {
256 fn encode(&self, out: &mut dyn BufMut) {
257 self.inner.encode(out)
258 }
259}
260
261impl Decodable for Capabilities {
262 fn decode(buf: &mut &[u8]) -> alloy_rlp::Result<Self> {
263 let inner = Vec::<Capability>::decode(buf)?;
264
265 Ok(Self {
266 eth_66: inner.iter().any(Capability::is_eth_v66),
267 eth_67: inner.iter().any(Capability::is_eth_v67),
268 eth_68: inner.iter().any(Capability::is_eth_v68),
269 eth_69: inner.iter().any(Capability::is_eth_v69),
270 eth_70: inner.iter().any(Capability::is_eth_v70),
271 inner,
272 })
273 }
274}