1#![allow(missing_docs)]
3use core::{
4 array::TryFromSliceError,
5 borrow::{
6 Borrow,
7 BorrowMut,
8 },
9 convert::TryFrom,
10 fmt,
11 ops::{
12 Deref,
13 DerefMut,
14 },
15 str,
16};
17
18#[cfg(feature = "random")]
19use rand::{
20 Rng,
21 distributions::{
22 Distribution,
23 Standard,
24 },
25};
26
27#[cfg(all(feature = "alloc", feature = "typescript"))]
28use alloc::format;
29
30macro_rules! key {
31 ($i:ident, $s:expr) => {
32 #[derive(Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
34 #[repr(transparent)]
35 #[cfg_attr(feature = "typescript", wasm_bindgen::prelude::wasm_bindgen)]
36 #[derive(
37 fuel_types::canonical::Serialize, fuel_types::canonical::Deserialize,
38 )]
39 pub struct $i([u8; $s]);
40
41 key_methods!($i, $s);
42
43 #[cfg(feature = "random")]
44 impl Distribution<$i> for Standard {
45 fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> $i {
46 $i(rng.r#gen())
47 }
48 }
49 };
50}
51
52macro_rules! key_with_big_array {
53 ($i:ident, $s:expr) => {
54 #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
56 #[repr(transparent)]
57 #[cfg_attr(feature = "typescript", wasm_bindgen::prelude::wasm_bindgen)]
58 #[derive(
59 fuel_types::canonical::Serialize, fuel_types::canonical::Deserialize,
60 )]
61 pub struct $i([u8; $s]);
62
63 key_methods!($i, $s);
64
65 impl Default for $i {
66 fn default() -> $i {
67 $i([0u8; $s])
68 }
69 }
70
71 #[cfg(feature = "random")]
72 impl Distribution<$i> for Standard {
73 fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> $i {
74 let mut bytes = $i::default();
75
76 rng.fill_bytes(bytes.as_mut());
77
78 bytes
79 }
80 }
81 };
82}
83
84macro_rules! key_methods {
85 ($i:ident, $s:expr) => {
86 impl $i {
87 pub const LEN: usize = $s;
89
90 pub const fn new(bytes: [u8; $s]) -> Self {
92 Self(bytes)
93 }
94
95 pub const fn zeroed() -> $i {
97 $i([0; $s])
98 }
99
100 #[cfg(feature = "unsafe")]
101 #[allow(unsafe_code)]
102 pub unsafe fn from_slice_unchecked(bytes: &[u8]) -> Self {
110 unsafe { $i($crate::bytes::from_slice_unchecked(bytes)) }
111 }
112
113 pub fn from_bytes_ref_checked(bytes: &[u8]) -> Option<&Self> {
117 let bytes: &[u8; $s] = bytes.get(..$s)?.try_into().ok()?;
118 Some(Self::from_bytes_ref(bytes))
119 }
120
121 pub fn from_bytes_ref(bytes: &[u8; $s]) -> &Self {
125 #[allow(unsafe_code)]
131 unsafe {
132 &*(bytes.as_ptr() as *const Self)
133 }
134 }
135
136 pub const fn size(&self) -> usize {
138 Self::LEN
139 }
140 }
141
142 #[cfg(feature = "typescript")]
143 #[wasm_bindgen::prelude::wasm_bindgen]
144 impl $i {
145 #[wasm_bindgen(js_name = from_bytes)]
152 pub fn from_bytes_typescript(bytes: &[u8]) -> Self {
153 Self(bytes.try_into().expect(
154 format!("The size of the arrays it not {} size", $s).as_str(),
155 ))
156 }
157
158 #[wasm_bindgen(js_name = zeroed)]
160 pub fn zeroed_typescript() -> $i {
161 Self::zeroed()
162 }
163
164 #[wasm_bindgen(js_name = size)]
166 pub fn size_typescript(&self) -> usize {
167 self.size()
168 }
169 }
170
171 #[cfg(feature = "random")]
172 impl rand::Fill for $i {
173 fn try_fill<R: rand::Rng + ?Sized>(
174 &mut self,
175 rng: &mut R,
176 ) -> Result<(), rand::Error> {
177 rng.fill_bytes(self.as_mut());
178
179 Ok(())
180 }
181 }
182
183 impl Deref for $i {
184 type Target = [u8; $s];
185
186 fn deref(&self) -> &[u8; $s] {
187 &self.0
188 }
189 }
190
191 impl Borrow<[u8; $s]> for $i {
192 fn borrow(&self) -> &[u8; $s] {
193 &self.0
194 }
195 }
196
197 impl BorrowMut<[u8; $s]> for $i {
198 fn borrow_mut(&mut self) -> &mut [u8; $s] {
199 &mut self.0
200 }
201 }
202
203 impl DerefMut for $i {
204 fn deref_mut(&mut self) -> &mut [u8; $s] {
205 &mut self.0
206 }
207 }
208
209 impl AsRef<[u8]> for $i {
210 fn as_ref(&self) -> &[u8] {
211 &self.0
212 }
213 }
214
215 impl AsMut<[u8]> for $i {
216 fn as_mut(&mut self) -> &mut [u8] {
217 &mut self.0
218 }
219 }
220
221 impl From<[u8; $s]> for $i {
222 fn from(bytes: [u8; $s]) -> Self {
223 Self(bytes)
224 }
225 }
226
227 impl From<$i> for [u8; $s] {
228 fn from(salt: $i) -> [u8; $s] {
229 salt.0
230 }
231 }
232
233 impl TryFrom<&[u8]> for $i {
234 type Error = TryFromSliceError;
235
236 fn try_from(bytes: &[u8]) -> Result<$i, TryFromSliceError> {
237 <[u8; $s]>::try_from(bytes).map(|b| b.into())
238 }
239 }
240
241 impl fmt::LowerHex for $i {
242 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
243 if f.alternate() {
244 write!(f, "0x")?
245 }
246
247 if let Some(w) = f
248 .width()
249 .and_then(|w| Self::LEN.saturating_mul(2).checked_div(w))
250 {
251 self.0.chunks(w).try_for_each(|c| {
252 write!(f, "{:02x}", c.iter().fold(0u8, |acc, x| acc ^ x))
253 })
254 } else {
255 self.0.iter().try_for_each(|b| write!(f, "{:02x}", &b))
256 }
257 }
258 }
259
260 impl fmt::UpperHex for $i {
261 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
262 if f.alternate() {
263 write!(f, "0x")?
264 }
265
266 if let Some(w) = f
267 .width()
268 .and_then(|w| Self::LEN.saturating_mul(2).checked_div(w))
269 {
270 self.0.chunks(w).try_for_each(|c| {
271 write!(f, "{:02X}", c.iter().fold(0u8, |acc, x| acc ^ x))
272 })
273 } else {
274 self.0.iter().try_for_each(|b| write!(f, "{:02X}", &b))
275 }
276 }
277 }
278
279 impl fmt::Debug for $i {
280 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
281 <Self as fmt::LowerHex>::fmt(&self, f)
282 }
283 }
284
285 impl fmt::Display for $i {
286 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
287 <Self as fmt::LowerHex>::fmt(&self, f)
288 }
289 }
290
291 impl str::FromStr for $i {
292 type Err = &'static str;
293
294 fn from_str(s: &str) -> Result<Self, Self::Err> {
295 const ERR: &str = concat!("Invalid encoded byte in ", stringify!($i));
296 let mut ret = $i::zeroed();
297 let s = s.strip_prefix("0x").unwrap_or(s);
298 hex::decode_to_slice(&s, &mut ret.0).map_err(|_| ERR)?;
299 Ok(ret)
300 }
301 }
302
303 #[cfg(feature = "serde")]
304 impl serde::Serialize for $i {
305 #[inline(always)]
306 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
307 where
308 S: serde::Serializer,
309 {
310 use alloc::format;
311 use serde::ser::SerializeTuple;
312 if serializer.is_human_readable() {
313 serializer.serialize_str(&format!("{:x}", &self))
314 } else {
315 let mut arr = serializer.serialize_tuple($s)?;
317 for elem in &self.0 {
318 arr.serialize_element(elem)?;
319 }
320 arr.end()
321 }
322 }
323 }
324
325 #[cfg(feature = "serde")]
326 impl<'de> serde::Deserialize<'de> for $i {
327 #[inline(always)]
328 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
329 where
330 D: serde::Deserializer<'de>,
331 {
332 use serde::de::Error;
333 if deserializer.is_human_readable() {
334 let s: alloc::string::String =
335 serde::Deserialize::deserialize(deserializer)?;
336 s.parse().map_err(D::Error::custom)
337 } else {
338 deserializer.deserialize_tuple($s, ArrayVisitor).map(Self)
339 }
340 }
341 }
342 };
343}
344
345key!(Address, 32);
346key!(AssetId, 32);
347key!(SubAssetId, 32);
348key!(BlobId, 32);
349key!(ContractId, 32);
350key!(TxId, 32);
351key!(Bytes4, 4);
352key!(Bytes8, 8);
353key!(Bytes20, 20);
354key!(Bytes32, 32);
355key!(Nonce, 32);
356key!(MessageId, 32);
357key!(Salt, 32);
358
359key_with_big_array!(Bytes64, 64);
360
361impl ContractId {
362 pub const SEED: [u8; 4] = 0x4655454C_u32.to_be_bytes();
366}
367
368impl AssetId {
369 pub const BASE: AssetId = AssetId::zeroed();
370}
371
372impl From<u64> for Nonce {
373 fn from(value: u64) -> Self {
374 let mut default = [0u8; 32];
375 default[..8].copy_from_slice(&value.to_be_bytes());
376 default.into()
377 }
378}
379
380#[cfg(feature = "serde")]
382struct ArrayVisitor<const S: usize>;
383
384#[cfg(feature = "serde")]
385impl<'de, const S: usize> serde::de::Visitor<'de> for ArrayVisitor<S> {
386 type Value = [u8; S];
387
388 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
389 write!(formatter, "an array of {S} bytes")
390 }
391
392 #[inline(always)]
393 fn visit_borrowed_bytes<E>(self, items: &'de [u8]) -> Result<Self::Value, E> {
394 let mut result = [0u8; S];
395 result.copy_from_slice(items);
396 Ok(result)
397 }
398
399 #[cfg(feature = "alloc")]
400 #[inline(always)]
401 fn visit_byte_buf<E>(self, v: alloc::vec::Vec<u8>) -> Result<Self::Value, E>
402 where
403 E: serde::de::Error,
404 {
405 self.visit_borrowed_bytes(v.as_slice())
406 }
407
408 #[inline(always)]
409 fn visit_seq<A>(self, mut value: A) -> Result<Self::Value, A::Error>
410 where
411 A: serde::de::SeqAccess<'de>,
412 {
413 let mut arr = [0u8; S];
414 for (i, elem) in arr.iter_mut().enumerate() {
415 *elem = value
416 .next_element()?
417 .ok_or_else(|| serde::de::Error::invalid_length(i, &self))?;
418 }
419 Ok(arr)
420 }
421}
422
423#[cfg(all(test, feature = "serde"))]
425mod tests_serde {
426 use rand::{
427 SeedableRng,
428 rngs::StdRng,
429 };
430
431 use super::*;
432
433 #[test]
435 fn test_human_readable() {
436 let rng = &mut StdRng::seed_from_u64(8586);
437 let original: Address = rng.r#gen();
438 let serialized = serde_json::to_string(&original).expect("Serialization failed");
439 assert_eq!(
440 serialized,
441 "\"7bbd8a4ea06e94461b959ab18d35802bbac3cf47e2bf29195f7db2ce41630cd7\""
442 );
443 let recreated: Address =
444 serde_json::from_str(&serialized).expect("Deserialization failed");
445 assert_eq!(original, recreated);
446 }
447
448 #[test]
450 fn test_not_human_readable() {
451 let rng = &mut StdRng::seed_from_u64(8586);
452 let original: Address = rng.r#gen();
453 let serialized = postcard::to_stdvec(&original).expect("Serialization failed");
454 let expected_vec = original.0.to_vec();
455 assert_eq!(&serialized, &expected_vec);
456 let recreated: Address =
457 postcard::from_bytes(&serialized).expect("Deserialization failed");
458 assert_eq!(original, recreated);
459 }
460
461 #[test]
463 fn test_not_human_readable_incorrect_deser() {
464 let rng = &mut StdRng::seed_from_u64(8586);
465 let original: Address = rng.r#gen();
466 let mut serialized =
467 postcard::to_stdvec(&original).expect("Serialization failed");
468 serialized.pop();
469 let res: Result<Address, _> = postcard::from_bytes(&serialized);
470 res.expect_err("Deserialization should have failed");
471 }
472
473 #[test]
475 fn test_bincode() {
476 let rng = &mut StdRng::seed_from_u64(8586);
477 let original: Address = rng.r#gen();
478 let serialized = bincode::serialize(&original).expect("Serialization failed");
479 let recreated: Address =
480 bincode::deserialize(&serialized).expect("Deserialization failed");
481 assert_eq!(original, recreated);
482 }
483}