/ console / program / src / request / input_id / serialize.rs
serialize.rs
  1  // Copyright (c) 2019-2025 Alpha-Delta Network Inc.
  2  // This file is part of the alphavm library.
  3  
  4  // Licensed under the Apache License, Version 2.0 (the "License");
  5  // you may not use this file except in compliance with the License.
  6  // You may obtain a copy of the License at:
  7  
  8  // http://www.apache.org/licenses/LICENSE-2.0
  9  
 10  // Unless required by applicable law or agreed to in writing, software
 11  // distributed under the License is distributed on an "AS IS" BASIS,
 12  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 13  // See the License for the specific language governing permissions and
 14  // limitations under the License.
 15  
 16  use super::*;
 17  
 18  use alphavm_utilities::DeserializeExt;
 19  
 20  impl<N: Network> Serialize for InputID<N> {
 21      /// Serializes the input ID into string or bytes.
 22      fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
 23          match serializer.is_human_readable() {
 24              true => match self {
 25                  Self::Constant(id) => {
 26                      let mut input = serializer.serialize_struct("InputID", 2)?;
 27                      input.serialize_field("type", "constant")?;
 28                      input.serialize_field("id", &id)?;
 29                      input.end()
 30                  }
 31                  Self::Public(id) => {
 32                      let mut input = serializer.serialize_struct("InputID", 2)?;
 33                      input.serialize_field("type", "public")?;
 34                      input.serialize_field("id", &id)?;
 35                      input.end()
 36                  }
 37                  Self::Private(id) => {
 38                      let mut input = serializer.serialize_struct("InputID", 2)?;
 39                      input.serialize_field("type", "private")?;
 40                      input.serialize_field("id", &id)?;
 41                      input.end()
 42                  }
 43                  Self::Record(commitment, gamma, record_view_key, serial_number, tag) => {
 44                      let mut input = serializer.serialize_struct("InputID", 5)?;
 45                      input.serialize_field("type", "record")?;
 46                      input.serialize_field("commitment", &commitment)?;
 47                      input.serialize_field("gamma", &gamma)?;
 48                      input.serialize_field("record_view_key", &record_view_key)?;
 49                      input.serialize_field("serial_number", &serial_number)?;
 50                      input.serialize_field("tag", &tag)?;
 51                      input.end()
 52                  }
 53                  Self::ExternalRecord(id) => {
 54                      let mut input = serializer.serialize_struct("InputID", 2)?;
 55                      input.serialize_field("type", "external_record")?;
 56                      input.serialize_field("id", &id)?;
 57                      input.end()
 58                  }
 59              },
 60              false => ToBytesSerializer::serialize_with_size_encoding(self, serializer),
 61          }
 62      }
 63  }
 64  
 65  impl<'de, N: Network> Deserialize<'de> for InputID<N> {
 66      /// Deserializes the input ID from a string or bytes.
 67      fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
 68          match deserializer.is_human_readable() {
 69              true => {
 70                  // Parse the input ID from a string into a value.
 71                  let mut input = serde_json::Value::deserialize(deserializer)?;
 72                  // Recover the input.
 73                  let input_id = match input.get("type").and_then(|t| t.as_str()) {
 74                      Some("constant") => InputID::Constant(DeserializeExt::take_from_value::<D>(&mut input, "id")?),
 75                      Some("public") => InputID::Public(DeserializeExt::take_from_value::<D>(&mut input, "id")?),
 76                      Some("private") => InputID::Private(DeserializeExt::take_from_value::<D>(&mut input, "id")?),
 77                      Some("record") => InputID::Record(
 78                          DeserializeExt::take_from_value::<D>(&mut input, "commitment")?,
 79                          DeserializeExt::take_from_value::<D>(&mut input, "gamma")?,
 80                          DeserializeExt::take_from_value::<D>(&mut input, "record_view_key")?,
 81                          DeserializeExt::take_from_value::<D>(&mut input, "serial_number")?,
 82                          DeserializeExt::take_from_value::<D>(&mut input, "tag")?,
 83                      ),
 84                      Some("external_record") => {
 85                          InputID::ExternalRecord(DeserializeExt::take_from_value::<D>(&mut input, "id")?)
 86                      }
 87                      _ => return Err(de::Error::custom("Invalid input type")),
 88                  };
 89                  Ok(input_id)
 90              }
 91              false => FromBytesDeserializer::<Self>::deserialize_with_size_encoding(deserializer, "input ID"),
 92          }
 93      }
 94  }
 95  
 96  #[cfg(test)]
 97  mod tests {
 98      use super::*;
 99      use alphavm_console_network::MainnetV0;
100  
101      type CurrentNetwork = MainnetV0;
102  
103      /// Add test cases here to be checked for serialization.
104      const TEST_CASES: &[&str] = &[
105          "{\"type\":\"constant\",\"id\":\"5field\"}",
106          "{\"type\":\"public\",\"id\":\"0field\"}",
107          "{\"type\":\"private\",\"id\":\"123field\"}",
108          "{\"type\":\"record\",\"commitment\":\"123123field\",\"tag\":\"0field\",\"record_view_key\":\"0field\",\"serial_number\":\"123456789field\",\"gamma\":\"0group\"}",
109          "{\"type\":\"external_record\",\"id\":\"123456789field\"}",
110      ];
111  
112      fn check_serde_json<
113          T: Serialize + for<'a> Deserialize<'a> + Debug + Display + PartialEq + Eq + FromStr + ToBytes + FromBytes,
114      >(
115          expected: T,
116      ) {
117          // Serialize
118          let expected_string = expected.to_string();
119          let candidate_string = serde_json::to_string(&expected).unwrap();
120          let candidate = serde_json::from_str::<T>(&candidate_string).unwrap();
121          assert_eq!(expected, candidate);
122          assert_eq!(expected_string, candidate_string);
123          assert_eq!(expected_string, candidate.to_string());
124  
125          // Deserialize
126          assert_eq!(expected, T::from_str(&expected_string).unwrap_or_else(|_| panic!("FromStr: {expected_string}")));
127          assert_eq!(expected, serde_json::from_str(&candidate_string).unwrap());
128      }
129  
130      fn check_bincode<
131          T: Serialize + for<'a> Deserialize<'a> + Debug + Display + PartialEq + Eq + FromStr + ToBytes + FromBytes,
132      >(
133          expected: T,
134      ) {
135          // Serialize
136          let expected_bytes = expected.to_bytes_le().unwrap();
137          let expected_bytes_with_size_encoding = bincode::serialize(&expected).unwrap();
138          assert_eq!(&expected_bytes[..], &expected_bytes_with_size_encoding[8..]);
139  
140          // Deserialize
141          assert_eq!(expected, T::read_le(&expected_bytes[..]).unwrap());
142          assert_eq!(expected, bincode::deserialize(&expected_bytes_with_size_encoding[..]).unwrap());
143      }
144  
145      #[test]
146      fn test_serde_json() {
147          for case in TEST_CASES.iter() {
148              check_serde_json(InputID::<CurrentNetwork>::from_str(case).unwrap());
149          }
150      }
151  
152      #[test]
153      fn test_bincode() {
154          for case in TEST_CASES.iter() {
155              check_bincode(InputID::<CurrentNetwork>::from_str(case).unwrap());
156          }
157      }
158  }