1#![allow(clippy::use_self)]
9#![allow(clippy::option_if_let_else)]
10
11#[expect(clippy::redundant_pub_crate, reason = "Want to keep it explicit")]
12pub(crate) mod identifier;
13#[cfg(feature = "u256")]
14pub mod u256;
15
16#[cfg(test)]
17#[allow(clippy::unwrap_used)]
18mod tests {
19 use std::mem;
20 use std::str::FromStr as _;
21
22 use crate::{IdentStr, StructTag, TypeTag};
23
24 #[test]
25 fn test_type_tag_serde() {
26 let a = TypeTag::Struct(Box::new(StructTag::new(
27 "0x1".parse().expect("Parses short hex reprs"),
28 IdentStr::cast("abc").to_owned(),
29 IdentStr::cast("abc").to_owned(),
30 vec![TypeTag::U8],
31 )));
32 let b = serde_json::to_string(&a).unwrap();
33 let c: TypeTag = serde_json::from_str(&b).unwrap();
34 assert!(a.eq(&c), "Typetag serde error");
35 assert_eq!(mem::size_of::<TypeTag>(), 16);
36 }
37
38 #[test]
39 fn type_tag_with_leading_underscores() {
40 let display = "0xb24b6789e088b876afabca733bed2299fbc9e2d6369be4d1acfa17d8145454d9::swap::Pool<0x2::sui::SUI, 0x1687f9a0321d0e643ba47ba1c8fc9226e4e28b55fe176a5a2675691a458dee9d::_jeet::_JEET>";
42 let _: TypeTag = display.parse().unwrap();
43 }
44
45 #[test]
46 fn struct_tag_with_leading_underscores() {
47 let display = "0xb24b6789e088b876afabca733bed2299fbc9e2d6369be4d1acfa17d8145454d9::swap::Pool<0x2::sui::SUI, 0x1687f9a0321d0e643ba47ba1c8fc9226e4e28b55fe176a5a2675691a458dee9d::_jeet::_JEET>";
49 let _: StructTag = display.parse().unwrap();
50 }
51
52 #[test]
53 fn test_type_tag() {
54 for s in &[
55 "u64",
56 "bool",
57 "vector<u8>",
58 "vector<vector<u64>>",
59 "vector<u16>",
60 "vector<vector<u16>>",
61 "vector<u32>",
62 "vector<vector<u32>>",
63 "vector<u128>",
64 "vector<vector<u128>>",
65 "vector<u256>",
66 "vector<vector<u256>>",
67 "signer",
68 "0x1::M::S",
69 "0x2::M::S_",
70 "0x3::M_::S",
71 "0x4::M_::S_",
72 "0x00000000004::M::S",
73 "0x1::M::S<u64>",
74 "0x1::M::S<u16>",
75 "0x1::M::S<u32>",
76 "0x1::M::S<u256>",
77 "0x1::M::S<0x2::P::Q>",
78 "vector<0x1::M::S>",
79 "vector<0x1::M_::S_>",
80 "vector<vector<0x1::M_::S_>>",
81 "0x1::M::S<vector<u8>>",
82 "0x1::M::S<vector<u16>>",
83 "0x1::M::S<vector<u32>>",
84 "0x1::M::S<vector<u64>>",
85 "0x1::M::S<vector<u128>>",
86 "0x1::M::S<vector<u256>>",
87 ] {
88 assert!(s.parse::<TypeTag>().is_ok(), "Failed to parse tag {}", s);
89 }
90 }
91
92 #[test]
93 fn test_parse_valid_struct_tag() {
94 let valid = vec![
95 "0x1::Diem::Diem",
96 "0x1::Diem_Type::Diem",
97 "0x1::Diem_::Diem",
98 "0x1::X_123::X32_",
99 "0x1::Diem::Diem_Type",
100 "0x1::Diem::Diem<0x1::XDX::XDX>",
101 "0x1::Diem::Diem<0x1::XDX::XDX_Type>",
102 "0x1::Diem::Diem<u8>",
103 "0x1::Diem::Diem<u64>",
104 "0x1::Diem::Diem<u128>",
105 "0x1::Diem::Diem<u16>",
106 "0x1::Diem::Diem<u32>",
107 "0x1::Diem::Diem<u256>",
108 "0x1::Diem::Diem<bool>",
109 "0x1::Diem::Diem<address>",
110 "0x1::Diem::Diem<signer>",
111 "0x1::Diem::Diem<vector<0x1::XDX::XDX>>",
112 "0x1::Diem::Diem<u8,bool>",
113 "0x1::Diem::Diem<u8, bool>",
114 "0x1::Diem::Diem<u16,bool>",
115 "0x1::Diem::Diem<u32, bool>",
116 "0x1::Diem::Diem<u128,bool>",
117 "0x1::Diem::Diem<u256, bool>",
118 "0x1::Diem::Diem<u8 ,bool>",
119 "0x1::Diem::Diem<u8 , bool , vector<u8>,address,signer>",
120 "0x1::Diem::Diem<vector<0x1::Diem::Struct<0x1::XUS::XUS>>>",
121 "0x1::Diem::Diem<0x1::Diem::Struct<vector<0x1::XUS::XUS>, 0x1::Diem::Diem<vector<0x1::Diem::Struct<0x1::XUS::XUS>>>>>",
122 ];
123 for (i, text) in valid.into_iter().enumerate() {
124 let st: StructTag = text.parse().expect("valid StructTag");
125 insta::assert_snapshot!(
126 format!("valid_struct_tag_{i}"),
127 st,
128 &format!("\"{text}\".parse()?")
129 );
130 }
131 }
132
133 #[test]
134 fn test_parse_struct_tag_with_type_names() {
135 let names = vec![
136 "address", "vector", "u128", "u256", "u64", "u32", "u16", "u8", "bool", "signer",
137 ];
138
139 let mut tests = vec![];
140 for name in &names {
141 for name_type in &names {
142 tests.push(format!("0x1::{name}::{name_type}"))
143 }
144 }
145
146 let mut instantiations = vec![];
147 for ty in &tests {
148 for other_ty in &tests {
149 instantiations.push(format!("{ty}<{other_ty}>"))
150 }
151 }
152
153 for text in tests.iter().chain(&instantiations) {
154 text.parse::<StructTag>().expect("valid StructTag");
155 }
156 }
157
158 #[test]
159 fn test_parse_struct_tag_short_account_addr() {
160 let result: StructTag = "0x2::sui::SUI".parse().expect("should not error");
161 insta::assert_snapshot!(
162 result.to_string(),
163 @"0x0000000000000000000000000000000000000000000000000000000000000002::sui::SUI"
164 );
165 }
166
167 #[test]
168 fn test_parse_struct_tag_long_account_addr() {
169 let result: StructTag =
170 "0x0000000000000000000000000000000000000000000000000000000000000002::sui::SUI"
171 .parse()
172 .expect("should not error");
173 insta::assert_snapshot!(
174 result.to_string(),
175 @"0x0000000000000000000000000000000000000000000000000000000000000002::sui::SUI"
176 );
177 }
178
179 #[test]
180 fn test_parse_struct_with_type_param_short_addr() {
181 let result =
182 StructTag::from_str("0x2::coin::COIN<0x2::sui::SUI>").expect("should not error");
183 insta::assert_snapshot!(
184 result.to_string(),
185 @"0x0000000000000000000000000000000000000000000000000000000000000002::coin::COIN<0x0000000000000000000000000000000000000000000000000000000000000002::sui::SUI>"
186 );
187 }
188
189 #[test]
190 fn test_parse_struct_with_type_param_long_addr() {
191 let result = StructTag::from_str("0x0000000000000000000000000000000000000000000000000000000000000002::coin::COIN<0x0000000000000000000000000000000000000000000000000000000000000002::sui::SUI>")
192 .expect("should not error");
193 insta::assert_snapshot!(
194 result.to_string(),
195 @"0x0000000000000000000000000000000000000000000000000000000000000002::coin::COIN<0x0000000000000000000000000000000000000000000000000000000000000002::sui::SUI>"
196 );
197 }
198
199 #[test]
200 fn test_complex_struct_tag_with_short_addr() {
201 let result =
202 StructTag::from_str("0xe7::vec_coin::VecCoin<vector<0x2::coin::Coin<0x2::sui::SUI>>>")
203 .expect("should not error");
204 insta::assert_snapshot!(
205 result.to_string(),
206 @"0x00000000000000000000000000000000000000000000000000000000000000e7::vec_coin::VecCoin<vector<0x0000000000000000000000000000000000000000000000000000000000000002::coin::Coin<0x0000000000000000000000000000000000000000000000000000000000000002::sui::SUI>>>"
207 );
208 }
209
210 #[test]
211 fn test_complex_struct_tag_with_long_addr() {
212 let result = StructTag::from_str("0x00000000000000000000000000000000000000000000000000000000000000e7::vec_coin::VecCoin<vector<0x0000000000000000000000000000000000000000000000000000000000000002::coin::Coin<0x0000000000000000000000000000000000000000000000000000000000000002::sui::SUI>>>")
213 .expect("should not error");
214 insta::assert_snapshot!(
215 result.to_string(),
216 @"0x00000000000000000000000000000000000000000000000000000000000000e7::vec_coin::VecCoin<vector<0x0000000000000000000000000000000000000000000000000000000000000002::coin::Coin<0x0000000000000000000000000000000000000000000000000000000000000002::sui::SUI>>>"
217 );
218 }
219
220 #[test]
221 fn test_dynamic_field_short_addr() {
222 let result = StructTag::from_str(
223 "0x2::dynamic_field::Field<address, 0xdee9::custodian_v2::Account<0x234::coin::COIN>>",
224 )
225 .expect("should not error");
226 insta::assert_snapshot!(
227 result.to_string(),
228 @"0x0000000000000000000000000000000000000000000000000000000000000002::dynamic_field::Field<address, 0x000000000000000000000000000000000000000000000000000000000000dee9::custodian_v2::Account<0x0000000000000000000000000000000000000000000000000000000000000234::coin::COIN>>"
229 );
230 }
231
232 #[test]
233 fn test_dynamic_field_long_addr() {
234 let result = StructTag::from_str(
235 "0x2::dynamic_field::Field<address, 0xdee9::custodian_v2::Account<0x234::coin::COIN>>",
236 )
237 .expect("should not error");
238 insta::assert_snapshot!(
239 result.to_string(),
240 @"0x0000000000000000000000000000000000000000000000000000000000000002::dynamic_field::Field<address, 0x000000000000000000000000000000000000000000000000000000000000dee9::custodian_v2::Account<0x0000000000000000000000000000000000000000000000000000000000000234::coin::COIN>>"
241 );
242 }
243}