1use crate::Word;
2
3#[cfg(feature = "alloc")]
4use alloc::vec::Vec;
5
6#[cfg(feature = "alloc")]
8#[derive(educe::Educe, Default, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
9#[educe(Debug)]
10#[derive(fuel_types::canonical::Deserialize, fuel_types::canonical::Serialize)]
11pub struct Bytes(#[educe(Debug(method(crate::fmt::fmt_truncated_hex::<16>)))] Vec<u8>);
12
13#[cfg(feature = "serde")]
14impl serde::Serialize for Bytes {
15 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
16 where
17 S: serde::Serializer,
18 {
19 serializer.serialize_bytes(&self.0)
20 }
21}
22
23#[cfg(feature = "serde")]
24impl<'de> serde::Deserialize<'de> for Bytes {
25 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
26 where
27 D: serde::Deserializer<'de>,
28 {
29 struct BytesVisitor;
31
32 impl<'de> serde::de::Visitor<'de> for BytesVisitor {
33 type Value = Vec<u8>;
34
35 fn expecting(
36 &self,
37 formatter: &mut core::fmt::Formatter,
38 ) -> core::fmt::Result {
39 write!(formatter, "an array of bytes")
40 }
41
42 #[inline(always)]
43 fn visit_borrowed_bytes<E>(self, items: &'de [u8]) -> Result<Self::Value, E> {
44 Ok(items.to_vec())
45 }
46
47 #[inline(always)]
48 fn visit_byte_buf<E>(self, v: Vec<u8>) -> Result<Self::Value, E>
49 where
50 E: serde::de::Error,
51 {
52 Ok(v)
53 }
54
55 #[inline(always)]
56 fn visit_seq<A>(self, mut value: A) -> Result<Self::Value, A::Error>
57 where
58 A: serde::de::SeqAccess<'de>,
59 {
60 let size = value.size_hint().unwrap_or(0);
61 let mut arr = Vec::with_capacity(size);
62
63 while let Some(elem) = value.next_element()? {
64 arr.push(elem);
65 }
66 Ok(arr)
67 }
68 }
69
70 let bytes = deserializer.deserialize_bytes(BytesVisitor)?;
71
72 Ok(Self(bytes))
73 }
74}
75
76#[cfg(feature = "alloc")]
77impl Bytes {
78 pub const fn new(bytes: Vec<u8>) -> Self {
80 Self(bytes)
81 }
82
83 pub fn into_inner(self) -> Vec<u8> {
85 self.0
86 }
87}
88
89#[cfg(feature = "alloc")]
90impl core::ops::Deref for Bytes {
91 type Target = Vec<u8>;
92
93 fn deref(&self) -> &Self::Target {
94 &self.0
95 }
96}
97
98#[cfg(feature = "alloc")]
99impl core::ops::DerefMut for Bytes {
100 fn deref_mut(&mut self) -> &mut Self::Target {
101 &mut self.0
102 }
103}
104
105#[cfg(feature = "alloc")]
106impl From<Vec<u8>> for Bytes {
107 fn from(value: Vec<u8>) -> Self {
108 Self(value)
109 }
110}
111
112#[cfg(feature = "alloc")]
113impl From<Bytes> for Vec<u8> {
114 fn from(value: Bytes) -> Self {
115 value.0
116 }
117}
118
119#[cfg(feature = "alloc")]
120impl AsRef<[u8]> for Bytes {
121 fn as_ref(&self) -> &[u8] {
122 &self.0
123 }
124}
125
126#[cfg(feature = "alloc")]
127impl AsMut<[u8]> for Bytes {
128 fn as_mut(&mut self) -> &mut [u8] {
129 &mut self.0
130 }
131}
132
133pub const WORD_SIZE: usize = core::mem::size_of::<Word>();
135
136pub const fn padded_len(bytes: &[u8]) -> Option<usize> {
139 padded_len_usize(bytes.len())
140}
141
142#[allow(clippy::arithmetic_side_effects)] pub const fn padded_len_usize(len: usize) -> Option<usize> {
146 let modulo = len % WORD_SIZE;
147 if modulo == 0 {
148 Some(len)
149 } else {
150 let padding = WORD_SIZE - modulo;
151 len.checked_add(padding)
152 }
153}
154
155#[allow(clippy::arithmetic_side_effects)] pub const fn padded_len_word(len: Word) -> Option<Word> {
159 let modulo = len % WORD_SIZE as Word;
160 if modulo == 0 {
161 Some(len)
162 } else {
163 let padding = WORD_SIZE as Word - modulo;
164 len.checked_add(padding)
165 }
166}
167
168#[cfg(feature = "unsafe")]
169#[allow(unsafe_code)]
170pub unsafe fn from_slice_unchecked<const N: usize>(buf: &[u8]) -> [u8; N] {
177 unsafe {
178 let ptr = buf.as_ptr() as *const [u8; N];
179
180 *ptr
183 }
184}
185
186#[allow(non_snake_case)]
187#[cfg(test)]
188mod tests {
189 use crate::bytes::{
190 Bytes,
191 WORD_SIZE,
192 padded_len,
193 padded_len_usize,
194 };
195
196 #[test]
197 #[allow(clippy::erasing_op)]
198 #[allow(clippy::identity_op)]
199 fn padded_len_returns_multiple_of_word_len() {
200 assert_eq!(Some(WORD_SIZE * 0), padded_len(&[]));
201 assert_eq!(Some(WORD_SIZE * 1), padded_len(&[0]));
202 assert_eq!(Some(WORD_SIZE * 1), padded_len(&[0; WORD_SIZE]));
203 assert_eq!(Some(WORD_SIZE * 2), padded_len(&[0; WORD_SIZE + 1]));
204 assert_eq!(Some(WORD_SIZE * 2), padded_len(&[0; WORD_SIZE * 2]));
205 }
206
207 #[test]
208 fn padded_len_usize_returns_multiple_of_word_len() {
209 assert_eq!(padded_len_usize(0), Some(0));
210 assert_eq!(padded_len_usize(1), Some(8));
211 assert_eq!(padded_len_usize(2), Some(8));
212 assert_eq!(padded_len_usize(7), Some(8));
213 assert_eq!(padded_len_usize(8), Some(8));
214 assert_eq!(padded_len_usize(9), Some(16));
215 }
216
217 #[test]
218 fn padded_len_usize_handles_overflow() {
219 for i in 0..7 {
220 assert_eq!(padded_len_usize(usize::MAX - i), None);
221 }
222 assert_eq!(padded_len_usize(usize::MAX - 7), Some(usize::MAX - 7));
223 }
224
225 #[test]
226 fn bytes__postcard__serialization_correct() {
227 let original_bytes = vec![1u8, 2u8, 3u8, 4u8, 5u8];
229 let bytes = Bytes::new(original_bytes.clone());
230
231 let serialized_bytes = postcard::to_allocvec(&bytes).unwrap();
233 let serialized_original_bytes = postcard::to_allocvec(&original_bytes).unwrap();
234
235 assert_eq!(serialized_bytes, serialized_original_bytes);
237 }
238
239 #[test]
240 fn bytes__postcard__deserialization_correct() {
241 let original_bytes = vec![1u8, 2u8, 3u8, 4u8, 5u8];
243 let serialized_original_bytes = postcard::to_allocvec(&original_bytes).unwrap();
244
245 let deserialized_bytes: Bytes =
247 postcard::from_bytes(&serialized_original_bytes).unwrap();
248 let expected_bytes = Bytes::new(original_bytes);
249
250 assert_eq!(deserialized_bytes, expected_bytes);
252 }
253
254 #[test]
255 fn bytes__bincode__serialization_correct() {
256 let original_bytes = vec![1u8, 2u8, 3u8, 4u8, 5u8];
258 let bytes = Bytes::new(original_bytes.clone());
259
260 let serialized_bytes = bincode::serialize(&bytes).unwrap();
262 let serialized_original_bytes = bincode::serialize(&original_bytes).unwrap();
263
264 assert_eq!(serialized_bytes, serialized_original_bytes);
266 }
267
268 #[test]
269 fn bytes__bincode__deserialization_correct() {
270 let original_bytes = vec![1u8, 2u8, 3u8, 4u8, 5u8];
272 let serialized_original_bytes = bincode::serialize(&original_bytes).unwrap();
273
274 let deserialized_bytes: Bytes =
276 bincode::deserialize(&serialized_original_bytes).unwrap();
277 let expected_bytes = Bytes::new(original_bytes);
278
279 assert_eq!(deserialized_bytes, expected_bytes);
281 }
282
283 #[test]
284 fn bytes__json__serialization_correct() {
285 let original_bytes = vec![1u8, 2u8, 3u8, 4u8, 5u8];
287 let bytes = Bytes::new(original_bytes.clone());
288
289 let serialized_bytes = serde_json::to_string(&bytes).unwrap();
291 let serialized_original_bytes = serde_json::to_string(&original_bytes).unwrap();
292
293 assert_eq!(serialized_bytes, serialized_original_bytes);
295 }
296
297 #[test]
298 fn bytes__json__deserialization_correct() {
299 let original_bytes = vec![1u8, 2u8, 3u8, 4u8, 5u8];
301 let serialized_original_bytes = serde_json::to_string(&original_bytes).unwrap();
302
303 let deserialized_bytes: Bytes =
305 serde_json::from_str(&serialized_original_bytes).unwrap();
306 let expected_bytes = Bytes::new(original_bytes);
307
308 assert_eq!(deserialized_bytes, expected_bytes);
310 }
311}