multiversx_sc/types/interaction/expr/
test_sc_address.rs1use core::ptr;
2
3use multiversx_sc_codec::{
4 EncodeErrorHandler, NestedEncode, NestedEncodeOutput, TopEncode, TopEncodeOutput,
5};
6
7use crate::{
8 abi::TypeAbiFrom,
9 api::ManagedTypeApi,
10 types::{
11 heap::Address, AnnotatedValue, ManagedAddress, ManagedBuffer, TxEnv, TxFrom,
12 TxFromSpecified, TxTo, TxToSpecified,
13 },
14};
15
16use super::TestAddress;
17
18const SC_PREFIX: &str = "sc:";
19const VM_TYPE_LEN: usize = 2;
20const DEFAULT_VM_TYPE: &[u8] = &[5, 0];
21
22#[derive(Clone, Copy, Debug, PartialEq, Eq)]
27pub struct TestSCAddress<'a> {
28 name: &'a str,
29}
30
31impl<'a> TestSCAddress<'a> {
32 pub const fn new(name: &'a str) -> Self {
33 TestSCAddress { name }
34 }
35}
36
37impl<Env> AnnotatedValue<Env, ManagedAddress<Env::Api>> for TestSCAddress<'_>
38where
39 Env: TxEnv,
40{
41 fn annotation(&self, _env: &Env) -> ManagedBuffer<Env::Api> {
42 let mut result = ManagedBuffer::new_from_bytes(SC_PREFIX.as_bytes());
43 result.append_bytes(self.name.as_bytes());
44 result
45 }
46
47 fn to_value(&self, _env: &Env) -> ManagedAddress<Env::Api> {
48 let expr: [u8; 32] = self.eval_to_array();
49 expr.into()
50 }
51}
52
53impl TestSCAddress<'_> {
54 pub fn to_address(&self) -> Address {
55 self.eval_to_array().into()
56 }
57
58 pub fn to_managed_address<Api: ManagedTypeApi>(&self) -> ManagedAddress<Api> {
59 self.eval_to_array().into()
60 }
61}
62
63impl PartialEq<TestAddress<'_>> for TestSCAddress<'_> {
64 fn eq(&self, other: &TestAddress) -> bool {
65 self.to_address() == other.to_address()
66 }
67}
68
69impl PartialEq<Address> for TestSCAddress<'_> {
70 fn eq(&self, other: &Address) -> bool {
71 &self.to_address() == other
72 }
73}
74
75impl<'a> PartialEq<TestSCAddress<'a>> for Address {
76 fn eq(&self, other: &TestSCAddress<'a>) -> bool {
77 self == &other.to_address()
78 }
79}
80
81#[cfg(feature = "std")]
82impl PartialEq<multiversx_chain_core::std::Bech32Address> for TestSCAddress<'_> {
83 fn eq(&self, other: &multiversx_chain_core::std::Bech32Address) -> bool {
84 self.to_address() == other.address
85 }
86}
87
88#[cfg(feature = "std")]
89impl<'a> PartialEq<TestSCAddress<'a>> for multiversx_chain_core::std::Bech32Address {
90 fn eq(&self, other: &TestSCAddress<'a>) -> bool {
91 self.address == other.to_address()
92 }
93}
94
95impl<Api: ManagedTypeApi> PartialEq<ManagedAddress<Api>> for TestSCAddress<'_> {
96 fn eq(&self, other: &ManagedAddress<Api>) -> bool {
97 self.to_address() == other.to_address()
98 }
99}
100
101impl<'a, Api: ManagedTypeApi> PartialEq<TestSCAddress<'a>> for ManagedAddress<Api> {
102 fn eq(&self, other: &TestSCAddress<'a>) -> bool {
103 self.to_address() == other.to_address()
104 }
105}
106
107impl<Env> TxFrom<Env> for TestSCAddress<'_>
108where
109 Env: TxEnv,
110{
111 fn resolve_address(&self, _env: &Env) -> ManagedAddress<Env::Api> {
112 let expr: [u8; 32] = self.eval_to_array();
113 expr.into()
114 }
115}
116impl<Env> TxFromSpecified<Env> for TestSCAddress<'_> where Env: TxEnv {}
117impl<Env> TxTo<Env> for TestSCAddress<'_> where Env: TxEnv {}
118impl<Env> TxToSpecified<Env> for TestSCAddress<'_> where Env: TxEnv {}
119
120impl TestSCAddress<'_> {
121 pub fn eval_to_array(&self) -> [u8; 32] {
122 let result = *b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00______________________";
123 let expr_bytes = self.name.as_bytes();
124 let mut len = expr_bytes.len();
125 if len > 22 {
126 len = 22;
127 }
128 unsafe {
129 ptr::copy_nonoverlapping(
130 DEFAULT_VM_TYPE.as_ptr(),
131 result.as_ptr().offset(8) as *mut u8,
132 VM_TYPE_LEN,
133 );
134 ptr::copy_nonoverlapping(
135 expr_bytes.as_ptr(),
136 result.as_ptr().offset(10) as *mut u8,
137 len,
138 );
139 }
140 result
141 }
142
143 #[cfg(feature = "alloc")]
144 pub fn eval_to_expr(&self) -> alloc::string::String {
145 alloc::format!("{SC_PREFIX}{}", self.name)
146 }
147}
148
149impl TopEncode for TestSCAddress<'_> {
150 fn top_encode_or_handle_err<O, H>(&self, output: O, h: H) -> Result<(), H::HandledErr>
151 where
152 O: TopEncodeOutput,
153 H: EncodeErrorHandler,
154 {
155 self.eval_to_array().top_encode_or_handle_err(output, h)
156 }
157}
158
159impl NestedEncode for TestSCAddress<'_> {
160 #[inline]
161 fn dep_encode_or_handle_err<O, H>(&self, dest: &mut O, h: H) -> Result<(), H::HandledErr>
162 where
163 O: NestedEncodeOutput,
164 H: EncodeErrorHandler,
165 {
166 self.eval_to_array().dep_encode_or_handle_err(dest, h)
167 }
168}
169
170impl<Api> TypeAbiFrom<TestSCAddress<'_>> for ManagedAddress<Api> where Api: ManagedTypeApi {}
171
172#[cfg(test)]
173pub mod tests {
174 use super::*;
175
176 fn assert_eq_eval(expr: &'static str, expected: &[u8; 32]) {
177 assert_eq!(&TestSCAddress::new(expr).eval_to_array(), expected);
178 }
179
180 #[test]
181 fn test_address_value() {
182 assert_eq_eval(
183 "",
184 b"\x00\x00\x00\x00\x00\x00\x00\x00\x05\x00______________________",
185 );
186 assert_eq_eval(
187 "a",
188 b"\x00\x00\x00\x00\x00\x00\x00\x00\x05\x00a_____________________",
189 );
190 assert_eq_eval(
191 "12345678901234567890120s",
192 b"\x00\x00\x00\x00\x00\x00\x00\x00\x05\x001234567890123456789012",
193 );
194 }
195}