dig_peer_protocol/
bytes.rs1use std::{fmt, io::Cursor, ops::Deref};
19
20use chia_sha2::Sha256;
21use chia_traits::{Error, Result, Streamable};
22
23#[derive(Default, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
28pub struct Bytes(Vec<u8>);
29
30impl Bytes {
31 #[must_use]
33 pub fn new(bytes: Vec<u8>) -> Self {
34 Self(bytes)
35 }
36
37 #[must_use]
39 pub fn len(&self) -> usize {
40 self.0.len()
41 }
42
43 #[must_use]
45 pub fn is_empty(&self) -> bool {
46 self.0.is_empty()
47 }
48
49 #[must_use]
51 pub fn into_inner(self) -> Vec<u8> {
52 self.0
53 }
54}
55
56impl fmt::Display for Bytes {
58 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
59 for byte in &self.0 {
60 write!(f, "{byte:02x}")?;
61 }
62 Ok(())
63 }
64}
65
66impl fmt::Debug for Bytes {
69 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
70 write!(f, "Bytes({self})")
71 }
72}
73
74impl Streamable for Bytes {
75 fn update_digest(&self, digest: &mut Sha256) {
76 #[allow(clippy::cast_possible_truncation)]
77 (self.0.len() as u32).update_digest(digest);
78 digest.update(&self.0);
79 }
80
81 fn stream(&self, out: &mut Vec<u8>) -> Result<()> {
82 if self.0.len() > u32::MAX as usize {
85 return Err(Error::SequenceTooLarge);
86 }
87 #[allow(clippy::cast_possible_truncation)]
88 (self.0.len() as u32).stream(out)?;
89 out.extend_from_slice(&self.0);
90 Ok(())
91 }
92
93 fn parse<const TRUSTED: bool>(input: &mut Cursor<&[u8]>) -> Result<Self> {
94 let len = u32::parse::<TRUSTED>(input)? as usize;
95 let start = usize::try_from(input.position()).map_err(|_| Error::EndOfBuffer)?;
96 let end = start.checked_add(len).ok_or(Error::EndOfBuffer)?;
97 let buf = *input.get_ref();
98 if buf.len() < end {
99 return Err(Error::EndOfBuffer);
100 }
101 input.set_position(end as u64);
102 Ok(Self(buf[start..end].to_vec()))
103 }
104}
105
106impl From<Vec<u8>> for Bytes {
107 fn from(value: Vec<u8>) -> Self {
108 Self(value)
109 }
110}
111
112impl From<&[u8]> for Bytes {
113 fn from(value: &[u8]) -> Self {
114 Self(value.to_vec())
115 }
116}
117
118impl From<Bytes> for Vec<u8> {
119 fn from(value: Bytes) -> Self {
120 value.0
121 }
122}
123
124impl AsRef<[u8]> for Bytes {
125 fn as_ref(&self) -> &[u8] {
126 &self.0
127 }
128}
129
130impl Deref for Bytes {
131 type Target = [u8];
132
133 fn deref(&self) -> &Self::Target {
134 &self.0
135 }
136}
137
138#[cfg(test)]
139mod tests {
140 use super::*;
141
142 #[test]
146 fn streams_a_u32_big_endian_length_prefix_then_the_raw_payload() {
147 let bytes = Bytes::new(vec![0xab, 0xcd, 0xef]);
148 assert_eq!(
149 bytes.to_bytes().expect("encode"),
150 vec![0x00, 0x00, 0x00, 0x03, 0xab, 0xcd, 0xef]
151 );
152 }
153
154 #[test]
157 fn a_length_beyond_one_byte_still_occupies_four_prefix_bytes() {
158 let encoded = Bytes::new(vec![7u8; 300]).to_bytes().expect("encode");
159 assert_eq!(&encoded[..4], &[0x00, 0x00, 0x01, 0x2c]);
160 assert_eq!(encoded.len(), 4 + 300);
161 }
162
163 #[test]
164 fn empty_payload_streams_as_a_bare_zero_length() {
165 assert_eq!(
166 Bytes::default().to_bytes().expect("encode"),
167 vec![0x00, 0x00, 0x00, 0x00]
168 );
169 }
170
171 #[test]
172 fn round_trips_through_parse() {
173 let original = Bytes::new((0..300).map(|i| (i % 251) as u8).collect());
174 let decoded = Bytes::from_bytes(&original.to_bytes().expect("encode")).expect("decode");
175 assert_eq!(decoded, original);
176 }
177
178 #[test]
181 fn a_length_prefix_longer_than_the_buffer_is_rejected() {
182 let truncated = [0x00, 0x00, 0x00, 0x08, 0xab, 0xcd];
183 assert!(Bytes::from_bytes(&truncated).is_err());
184 }
185
186 #[test]
188 fn a_maximal_length_prefix_errors_rather_than_overflowing() {
189 let hostile = [0xff, 0xff, 0xff, 0xff, 0x00];
190 assert!(Bytes::from_bytes(&hostile).is_err());
191 }
192
193 #[test]
194 fn renders_as_hex_in_both_display_and_debug() {
195 let bytes = Bytes::new(vec![0x00, 0x0f, 0xff]);
196 assert_eq!(bytes.to_string(), "000fff");
197 assert_eq!(format!("{bytes:?}"), "Bytes(000fff)");
198 }
199
200 #[test]
201 fn converts_to_and_from_the_shapes_callers_actually_hold() {
202 let from_vec: Bytes = vec![1u8, 2, 3].into();
203 let from_slice: Bytes = [1u8, 2, 3].as_slice().into();
204 assert_eq!(from_vec, from_slice);
205 assert_eq!(from_vec.as_ref(), &[1, 2, 3]);
206 assert_eq!(&*from_slice, &[1, 2, 3]);
207 assert_eq!(Vec::<u8>::from(from_vec.clone()), vec![1, 2, 3]);
208 assert_eq!(from_vec.into_inner(), vec![1, 2, 3]);
209 }
210
211 #[test]
212 fn reports_its_own_length_and_emptiness() {
213 assert!(Bytes::default().is_empty());
214 assert_eq!(Bytes::default().len(), 0);
215 assert!(!Bytes::new(vec![1]).is_empty());
216 assert_eq!(Bytes::new(vec![1, 2]).len(), 2);
217 }
218}