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 pub const fn eth_71() -> Self {
115 Self::eth(EthVersion::Eth71)
116 }
117
118 #[inline]
120 pub fn is_eth_v66(&self) -> bool {
121 self.name == "eth" && self.version == 66
122 }
123
124 #[inline]
126 pub fn is_eth_v67(&self) -> bool {
127 self.name == "eth" && self.version == 67
128 }
129
130 #[inline]
132 pub fn is_eth_v68(&self) -> bool {
133 self.name == "eth" && self.version == 68
134 }
135
136 #[inline]
138 pub fn is_eth_v69(&self) -> bool {
139 self.name == "eth" && self.version == 69
140 }
141
142 #[inline]
144 pub fn is_eth_v70(&self) -> bool {
145 self.name == "eth" && self.version == 70
146 }
147
148 #[inline]
150 pub fn is_eth_v71(&self) -> bool {
151 self.name == "eth" && self.version == 71
152 }
153
154 #[inline]
156 pub fn is_eth(&self) -> bool {
157 self.is_eth_v66() ||
158 self.is_eth_v67() ||
159 self.is_eth_v68() ||
160 self.is_eth_v69() ||
161 self.is_eth_v70() ||
162 self.is_eth_v71()
163 }
164}
165
166impl fmt::Display for Capability {
167 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
168 write!(f, "{}/{}", self.name, self.version)
169 }
170}
171
172impl From<EthVersion> for Capability {
173 #[inline]
174 fn from(value: EthVersion) -> Self {
175 Self::eth(value)
176 }
177}
178
179#[cfg(any(test, feature = "arbitrary"))]
180impl<'a> arbitrary::Arbitrary<'a> for Capability {
181 fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> {
182 let version = u.int_in_range(66..=71)?; Ok(Self::new_static("eth", version))
185 }
186}
187
188#[derive(Debug, Clone, Eq, PartialEq)]
190pub struct Capabilities {
191 inner: Vec<Capability>,
193 eth_66: bool,
194 eth_67: bool,
195 eth_68: bool,
196 eth_69: bool,
197 eth_70: bool,
198 eth_71: bool,
199}
200
201impl Capabilities {
202 pub fn new(value: Vec<Capability>) -> Self {
204 Self {
205 eth_66: value.iter().any(Capability::is_eth_v66),
206 eth_67: value.iter().any(Capability::is_eth_v67),
207 eth_68: value.iter().any(Capability::is_eth_v68),
208 eth_69: value.iter().any(Capability::is_eth_v69),
209 eth_70: value.iter().any(Capability::is_eth_v70),
210 eth_71: value.iter().any(Capability::is_eth_v71),
211 inner: value,
212 }
213 }
214 #[inline]
216 pub fn capabilities(&self) -> &[Capability] {
217 &self.inner
218 }
219
220 #[inline]
222 pub fn into_inner(self) -> Vec<Capability> {
223 self.inner
224 }
225
226 #[inline]
228 pub const fn supports_eth(&self) -> bool {
229 self.eth_71 || self.eth_70 || self.eth_69 || self.eth_68 || self.eth_67 || self.eth_66
230 }
231
232 #[inline]
234 pub const fn supports_eth_v66(&self) -> bool {
235 self.eth_66
236 }
237
238 #[inline]
240 pub const fn supports_eth_v67(&self) -> bool {
241 self.eth_67
242 }
243
244 #[inline]
246 pub const fn supports_eth_v68(&self) -> bool {
247 self.eth_68
248 }
249
250 #[inline]
252 pub const fn supports_eth_v69(&self) -> bool {
253 self.eth_69
254 }
255
256 #[inline]
258 pub const fn supports_eth_v70(&self) -> bool {
259 self.eth_70
260 }
261
262 #[inline]
264 pub const fn supports_eth_v71(&self) -> bool {
265 self.eth_71
266 }
267}
268
269impl From<Vec<Capability>> for Capabilities {
270 fn from(value: Vec<Capability>) -> Self {
271 Self::new(value)
272 }
273}
274
275impl Encodable for Capabilities {
276 fn encode(&self, out: &mut dyn BufMut) {
277 self.inner.encode(out)
278 }
279}
280
281impl Decodable for Capabilities {
282 fn decode(buf: &mut &[u8]) -> alloy_rlp::Result<Self> {
283 let inner = Vec::<Capability>::decode(buf)?;
284
285 Ok(Self {
286 eth_66: inner.iter().any(Capability::is_eth_v66),
287 eth_67: inner.iter().any(Capability::is_eth_v67),
288 eth_68: inner.iter().any(Capability::is_eth_v68),
289 eth_69: inner.iter().any(Capability::is_eth_v69),
290 eth_70: inner.iter().any(Capability::is_eth_v70),
291 eth_71: inner.iter().any(Capability::is_eth_v71),
292 inner,
293 })
294 }
295}