rain_metadata/meta/
normalize.rs1use super::{
2 KnownMeta,
3 super::error::Error,
4 types::{
5 authoring::v1::AuthoringMeta, solidity_abi::v2::SolidityAbiMeta,
6 interpreter_caller::v1::InterpreterCallerMeta,
7 },
8};
9
10fn normalize_json<'de, T>(data: &'de [u8]) -> Result<Vec<u8>, Error>
11where
12 T: serde::Deserialize<'de> + serde::Serialize + validator::Validate,
13{
14 let parsed = serde_json::from_str::<T>(std::str::from_utf8(data)?)?;
15 parsed.validate()?;
16 Ok(serde_json::to_string(&parsed)?.as_bytes().to_vec())
17}
18
19impl KnownMeta {
20 pub fn normalize(&self, data: &[u8]) -> Result<Vec<u8>, Error> {
22 Ok(match self {
23 KnownMeta::SolidityAbiV2 => normalize_json::<SolidityAbiMeta>(data)?,
24 KnownMeta::InterpreterCallerMetaV1 => normalize_json::<InterpreterCallerMeta>(data)?,
25 KnownMeta::AuthoringMetaV1 => {
26 match AuthoringMeta::abi_decode(data) {
30 Ok(am) => am.abi_encode_validate()?,
31 _ => AuthoringMeta::abi_encode_validate(
32 &serde_json::from_str::<AuthoringMeta>(std::str::from_utf8(data)?)?,
33 )?,
34 }
35 }
36 _ => data.to_vec(),
39 })
40 }
41}
42
43#[cfg(all(test, not(target_family = "wasm")))]
44mod tests {
45 use crate::error::Error;
46 use crate::meta::types::authoring::v1::{AuthoringMeta, AuthoringMetaItem};
47 use crate::meta::KnownMeta;
48
49 #[test]
53 fn test_normalize_op_v1_is_a_passthrough() {
54 let bytes = b"{ \"name\" : \"add\" }";
55 assert_eq!(KnownMeta::OpV1.normalize(bytes).unwrap(), bytes.to_vec());
56 }
57
58 #[test]
60 fn test_normalize_solidity_abi_v2_rejects_bad_input() {
61 assert!(matches!(
62 KnownMeta::SolidityAbiV2.normalize(b"not json at all"),
63 Err(Error::SerdeJsonError(_))
64 ));
65 assert!(matches!(
66 KnownMeta::SolidityAbiV2.normalize(&[0xff, 0xfe]),
67 Err(Error::Utf8Error(_))
68 ));
69 }
70
71 #[test]
73 fn test_normalize_solidity_abi_v2_canonicalizes() {
74 assert_eq!(
75 KnownMeta::SolidityAbiV2.normalize(b"[ ]").unwrap(),
76 b"[]".to_vec()
77 );
78 }
79
80 #[test]
83 fn test_normalize_interpreter_caller_rejects_empty_methods() {
84 let invalid = br#"{"name":"Test Caller","abiName":"TestCaller","methods":[]}"#;
85 assert!(matches!(
86 KnownMeta::InterpreterCallerMetaV1.normalize(invalid),
87 Err(Error::ValidationErrors(_))
88 ));
89 }
90
91 #[test]
93 fn test_normalize_passthrough_for_binary_metas() {
94 let data = vec![0x00, 0x01, 0xff];
95 assert_eq!(
96 KnownMeta::ExpressionDeployerV2BytecodeV1
97 .normalize(&data)
98 .unwrap(),
99 data
100 );
101 }
102
103 fn sample_authoring_meta() -> AuthoringMeta {
104 serde_json::from_str(
105 r#"[{"word":"stack","description":"Copies an existing value from the stack.","operandParserOffset":16}]"#,
106 )
107 .unwrap()
108 }
109
110 #[test]
113 fn test_normalize_authoring_meta_v1_abi_path() {
114 let authoring_meta = sample_authoring_meta();
115 let abi = authoring_meta.abi_encode_validate().unwrap();
116 let normalized = KnownMeta::AuthoringMetaV1.normalize(&abi).unwrap();
117 assert_eq!(normalized, abi);
118 }
119
120 #[test]
123 fn test_normalize_authoring_meta_v1_abi_invalid_rejected() {
124 let invalid = AuthoringMeta(vec![AuthoringMetaItem {
125 word: "NOTKEBAB".to_string(),
126 operand_parser_offset: 0,
127 description: "some description".to_string(),
128 }]);
129 let abi = invalid.abi_encode().unwrap();
131 let result = KnownMeta::AuthoringMetaV1.normalize(&abi);
132 assert!(matches!(result, Err(Error::ValidationErrors(_))));
133 }
134
135 #[test]
138 fn test_normalize_authoring_meta_v1_json_fallback() {
139 let json = r#"[{"word":"stack","description":"Copies an existing value from the stack.","operandParserOffset":16}]"#;
140 let expected = sample_authoring_meta().abi_encode_validate().unwrap();
141 let normalized = KnownMeta::AuthoringMetaV1
142 .normalize(json.as_bytes())
143 .unwrap();
144 assert_eq!(normalized, expected);
145 assert_ne!(normalized, json.as_bytes().to_vec());
146 }
147
148 #[test]
151 fn test_normalize_default_arm_passthrough() {
152 let data = b"some dotrain text".to_vec();
153 assert_eq!(KnownMeta::DotrainV1.normalize(&data).unwrap(), data);
154 let binary = vec![0xffu8, 0x00, 0x01];
155 assert_eq!(KnownMeta::RainlangV1.normalize(&binary).unwrap(), binary);
156 }
157}