vrf_wasm/
serde_helpers.rs1use serde::{Deserialize, Serialize};
5use serde_with::serde_as;
6use crate::error::FastCryptoError;
7
8#[serde_as]
11#[derive(Serialize, Deserialize)]
12#[serde(transparent)]
13pub struct SerializationHelper<const N: usize>(#[serde_as(as = "[_; N]")] pub [u8; N]);
14
15pub trait ToFromByteArray<const LENGTH: usize>: Sized {
16 const BYTE_LENGTH: usize = LENGTH;
17 fn from_byte_array(bytes: &[u8; LENGTH]) -> Result<Self, FastCryptoError>;
18 fn to_byte_array(&self) -> [u8; LENGTH];
19}
20
21#[macro_export]
23macro_rules! serialize_deserialize_with_to_from_byte_array {
24 ($type:ty) => {
25 impl ::serde::Serialize for $type {
26 fn serialize<S: ::serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
27 use $crate::encoding::Base64;
28 use $crate::encoding::Encoding;
29 use $crate::serde_helpers::SerializationHelper;
30
31 let bytes = &self.to_byte_array();
32 match serializer.is_human_readable() {
33 true => Base64::encode(bytes).serialize(serializer),
34 false => SerializationHelper::<{ <$type>::BYTE_LENGTH }>(*bytes)
35 .serialize(serializer),
36 }
37 }
38 }
39
40 impl<'de> ::serde::Deserialize<'de> for $type {
41 fn deserialize<D: ::serde::Deserializer<'de>>(
42 deserializer: D,
43 ) -> Result<Self, D::Error> {
44 use $crate::encoding::Base64;
45 use $crate::encoding::Encoding;
46 use $crate::serde_helpers::SerializationHelper;
47
48 let bytes = match deserializer.is_human_readable() {
49 true => {
50 let s = String::deserialize(deserializer)?;
51 let decoded = Base64::decode(&s)
52 .map_err(|_| de::Error::custom("Base64 decoding failed"))?;
53 if decoded.len() != { <$type>::BYTE_LENGTH } {
54 return Err(de::Error::custom(format!(
55 "Invalid buffer length {}, expecting {}",
56 decoded.len(),
57 { <$type>::BYTE_LENGTH }
58 )));
59 }
60 decoded.try_into().unwrap()
61 }
62 false => {
63 let helper: SerializationHelper<{ <$type>::BYTE_LENGTH }> =
64 Deserialize::deserialize(deserializer)?;
65 helper.0
66 }
67 };
68 Self::from_byte_array(&bytes)
69 .map_err(|_| de::Error::custom("Failed in reconstructing the object"))
70 }
71 }
72 };
73}
74
75#[macro_export]
76macro_rules! serialize_deserialize_with_to_from_bytes {
77 ($type:ty, $length:tt) => {
78 impl ::serde::Serialize for $type {
79 fn serialize<S: ::serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
80 use $crate::serde_helpers::SerializationHelper;
81 match serializer.is_human_readable() {
82 true => serializer.serialize_str(&self.encode_base64()),
83 false => SerializationHelper::<{ $length }>(self.as_ref().try_into().unwrap())
84 .serialize(serializer),
85 }
86 }
87 }
88
89 impl<'de> ::serde::Deserialize<'de> for $type {
90 fn deserialize<D: ::serde::Deserializer<'de>>(
91 deserializer: D,
92 ) -> Result<Self, D::Error> {
93 use serde::Deserialize;
94 use $crate::serde_helpers::SerializationHelper;
95 if deserializer.is_human_readable() {
96 let s = <String as ::serde::Deserialize>::deserialize(deserializer)?;
97 Self::decode_base64(&s).map_err(::serde::de::Error::custom)
98 } else {
99 let helper: SerializationHelper<{ $length }> =
100 Deserialize::deserialize(deserializer)?;
101 <Self as ToFromBytes>::from_bytes(&helper.0).map_err(::serde::de::Error::custom)
102 }
103 }
104 }
105 };
106}