af_sui_types/move_core/
mod.rs

1// Copyright (c) The Diem Core Contributors
2// Copyright (c) The Move Contributors
3// Copyright (c) Mysten Labs, Inc.
4// SPDX-License-Identifier: Apache-2.0
5//
6// Most of the code here is highly adapted from
7// https://github.com/MystenLabs/sui/tree/main/external-crates/move/crates/move-core-types
8#![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        // From: https://suiscan.xyz/mainnet/object/0x9a84c763d68f07811c90fd989ca306cc7ff67916881de3da37e5fc811bbc5a8d
41        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        // From: https://suiscan.xyz/mainnet/object/0x9a84c763d68f07811c90fd989ca306cc7ff67916881de3da37e5fc811bbc5a8d
48        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}