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 #[inline]
105 pub fn is_eth_v66(&self) -> bool {
106 self.name == "eth" && self.version == 66
107 }
108
109 #[inline]
111 pub fn is_eth_v67(&self) -> bool {
112 self.name == "eth" && self.version == 67
113 }
114
115 #[inline]
117 pub fn is_eth_v68(&self) -> bool {
118 self.name == "eth" && self.version == 68
119 }
120
121 #[inline]
123 pub fn is_eth(&self) -> bool {
124 self.is_eth_v66() || self.is_eth_v67() || self.is_eth_v68()
125 }
126}
127
128impl fmt::Display for Capability {
129 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
130 write!(f, "{}/{}", self.name, self.version)
131 }
132}
133
134impl From<EthVersion> for Capability {
135 #[inline]
136 fn from(value: EthVersion) -> Self {
137 Self::eth(value)
138 }
139}
140
141#[cfg(any(test, feature = "arbitrary"))]
142impl<'a> arbitrary::Arbitrary<'a> for Capability {
143 fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> {
144 let version = u.int_in_range(66..=69)?; Ok(Self::new_static("eth", version))
147 }
148}
149
150#[derive(Debug, Clone, Eq, PartialEq)]
152pub struct Capabilities {
153 inner: Vec<Capability>,
155 eth_66: bool,
156 eth_67: bool,
157 eth_68: bool,
158}
159
160impl Capabilities {
161 pub fn new(value: Vec<Capability>) -> Self {
163 Self {
164 eth_66: value.iter().any(Capability::is_eth_v66),
165 eth_67: value.iter().any(Capability::is_eth_v67),
166 eth_68: value.iter().any(Capability::is_eth_v68),
167 inner: value,
168 }
169 }
170 #[inline]
172 pub fn capabilities(&self) -> &[Capability] {
173 &self.inner
174 }
175
176 #[inline]
178 pub fn into_inner(self) -> Vec<Capability> {
179 self.inner
180 }
181
182 #[inline]
184 pub const fn supports_eth(&self) -> bool {
185 self.eth_68 || self.eth_67 || self.eth_66
186 }
187
188 #[inline]
190 pub const fn supports_eth_v66(&self) -> bool {
191 self.eth_66
192 }
193
194 #[inline]
196 pub const fn supports_eth_v67(&self) -> bool {
197 self.eth_67
198 }
199
200 #[inline]
202 pub const fn supports_eth_v68(&self) -> bool {
203 self.eth_68
204 }
205}
206
207impl From<Vec<Capability>> for Capabilities {
208 fn from(value: Vec<Capability>) -> Self {
209 Self::new(value)
210 }
211}
212
213impl Encodable for Capabilities {
214 fn encode(&self, out: &mut dyn BufMut) {
215 self.inner.encode(out)
216 }
217}
218
219impl Decodable for Capabilities {
220 fn decode(buf: &mut &[u8]) -> alloy_rlp::Result<Self> {
221 let inner = Vec::<Capability>::decode(buf)?;
222
223 Ok(Self {
224 eth_66: inner.iter().any(Capability::is_eth_v66),
225 eth_67: inner.iter().any(Capability::is_eth_v67),
226 eth_68: inner.iter().any(Capability::is_eth_v68),
227 inner,
228 })
229 }
230}