@layerzerolabs/common-utils-stellar-contracts 0.2.122
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Cargo.toml +28 -0
- package/LICENSE +23 -0
- package/clippy.toml +7 -0
- package/package.json +43 -0
- package/rust-toolchain.toml +4 -0
- package/rustfmt.toml +15 -0
- package/src/auth.rs +48 -0
- package/src/buffer_reader.rs +194 -0
- package/src/buffer_writer.rs +138 -0
- package/src/bytes_ext.rs +18 -0
- package/src/errors.rs +82 -0
- package/src/lib.rs +20 -0
- package/src/multisig.rs +247 -0
- package/src/option_ext.rs +38 -0
- package/src/ownable.rs +227 -0
- package/src/rbac.rs +438 -0
- package/src/testing_utils.rs +180 -0
- package/src/tests/auth.rs +179 -0
- package/src/tests/buffer_reader.rs +969 -0
- package/src/tests/buffer_writer.rs +689 -0
- package/src/tests/bytes_ext.rs +160 -0
- package/src/tests/mod.rs +13 -0
- package/src/tests/multisig.rs +760 -0
- package/src/tests/option_ext.rs +18 -0
- package/src/tests/ownable.rs +822 -0
- package/src/tests/rbac.rs +559 -0
- package/src/tests/test_helper.rs +67 -0
- package/src/tests/testing_utils.rs +522 -0
- package/src/tests/ttl_configurable.rs +586 -0
- package/src/tests/ttl_extendable.rs +64 -0
- package/src/tests/upgradeable.rs +529 -0
- package/src/ttl_configurable.rs +169 -0
- package/src/ttl_extendable.rs +25 -0
- package/src/upgradeable.rs +103 -0
|
@@ -0,0 +1,969 @@
|
|
|
1
|
+
use crate::{
|
|
2
|
+
buffer_reader::BufferReader,
|
|
3
|
+
buffer_writer::BufferWriter,
|
|
4
|
+
bytes_ext::BytesExt,
|
|
5
|
+
tests::test_helper::{assert_address_payload_matches, assert_panics_contains},
|
|
6
|
+
};
|
|
7
|
+
use soroban_sdk::{address_payload::AddressPayload, testutils::Address as _, Address, Bytes, BytesN, Env};
|
|
8
|
+
|
|
9
|
+
type ReaderStep = fn(&mut BufferReader);
|
|
10
|
+
|
|
11
|
+
fn assert_reader_panics_contains(case: &str, raw: &[u8], step: ReaderStep, expected_substring: &str) {
|
|
12
|
+
assert_panics_contains(case, expected_substring, || {
|
|
13
|
+
let env = Env::default();
|
|
14
|
+
let bytes = Bytes::from_slice(&env, raw);
|
|
15
|
+
let mut reader = BufferReader::new(&bytes);
|
|
16
|
+
step(&mut reader);
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/// Helper to test U256 read roundtrip
|
|
21
|
+
fn test_u256_read_roundtrip(env: &Env, value: &soroban_sdk::U256) {
|
|
22
|
+
let mut writer = BufferWriter::new(env);
|
|
23
|
+
writer.write_u256(value.clone());
|
|
24
|
+
let bytes = writer.to_bytes();
|
|
25
|
+
let mut reader = BufferReader::new(&bytes);
|
|
26
|
+
assert_eq!(reader.read_u256(), *value);
|
|
27
|
+
assert_eq!(reader.remaining_len(), 0);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/// Helper to test address roundtrip
|
|
31
|
+
fn test_address_roundtrip(env: &Env, address: &Address) {
|
|
32
|
+
let mut writer = BufferWriter::new(env);
|
|
33
|
+
writer.write_address(address);
|
|
34
|
+
let bytes = writer.to_bytes();
|
|
35
|
+
|
|
36
|
+
let mut reader = BufferReader::new(&bytes);
|
|
37
|
+
let read_address = reader.read_address();
|
|
38
|
+
|
|
39
|
+
assert_eq!(read_address, *address);
|
|
40
|
+
assert_eq!(reader.remaining_len(), 0);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// ============================================
|
|
44
|
+
// read_primitives tests (u8, u16, u32, u64, u128, i128, u256, bool)
|
|
45
|
+
// ============================================
|
|
46
|
+
|
|
47
|
+
#[test]
|
|
48
|
+
fn test_read_primitives_big_endian_golden_bytes() {
|
|
49
|
+
let env = Env::default();
|
|
50
|
+
let bytes = Bytes::from_array(
|
|
51
|
+
&env,
|
|
52
|
+
&[
|
|
53
|
+
0x12, // u8
|
|
54
|
+
0x34, 0x56, // u16
|
|
55
|
+
0x78, 0x9A, 0xBC, 0xDE, // u32
|
|
56
|
+
0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, // u64
|
|
57
|
+
0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
|
|
58
|
+
0x10, // u128
|
|
59
|
+
],
|
|
60
|
+
);
|
|
61
|
+
let mut reader = BufferReader::new(&bytes);
|
|
62
|
+
|
|
63
|
+
assert_eq!(reader.read_u8(), 0x12);
|
|
64
|
+
assert_eq!(reader.read_u16(), 0x3456);
|
|
65
|
+
assert_eq!(reader.read_u32(), 0x789ABCDE);
|
|
66
|
+
assert_eq!(reader.read_u64(), 0x0102030405060708);
|
|
67
|
+
assert_eq!(reader.read_u128(), 0x0102030405060708090a0b0c0d0e0f10);
|
|
68
|
+
assert_eq!(reader.remaining_len(), 0);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
#[test]
|
|
72
|
+
fn test_read_primitives_roundtrip() {
|
|
73
|
+
let env = Env::default();
|
|
74
|
+
let mut writer = BufferWriter::new(&env);
|
|
75
|
+
writer
|
|
76
|
+
.write_u8(0x12)
|
|
77
|
+
.write_u16(0x3456)
|
|
78
|
+
.write_u32(0x789ABCDE)
|
|
79
|
+
.write_u64(0x0102030405060708)
|
|
80
|
+
.write_u128(0x0102030405060708090a0b0c0d0e0f10);
|
|
81
|
+
|
|
82
|
+
let bytes = writer.to_bytes();
|
|
83
|
+
let mut reader = BufferReader::new(&bytes);
|
|
84
|
+
|
|
85
|
+
assert_eq!(reader.read_u8(), 0x12);
|
|
86
|
+
assert_eq!(reader.read_u16(), 0x3456);
|
|
87
|
+
assert_eq!(reader.read_u32(), 0x789ABCDE);
|
|
88
|
+
assert_eq!(reader.read_u64(), 0x0102030405060708);
|
|
89
|
+
assert_eq!(reader.read_u128(), 0x0102030405060708090a0b0c0d0e0f10);
|
|
90
|
+
assert_eq!(reader.remaining_len(), 0);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
#[test]
|
|
94
|
+
fn test_read_i128_roundtrip() {
|
|
95
|
+
let env = Env::default();
|
|
96
|
+
let mut writer = BufferWriter::new(&env);
|
|
97
|
+
writer.write_i128(0).write_i128(-42).write_i128(123_456_789).write_i128(i128::MIN).write_i128(i128::MAX);
|
|
98
|
+
|
|
99
|
+
let bytes = writer.to_bytes();
|
|
100
|
+
let mut reader = BufferReader::new(&bytes);
|
|
101
|
+
|
|
102
|
+
assert_eq!(reader.read_i128(), 0);
|
|
103
|
+
assert_eq!(reader.read_i128(), -42);
|
|
104
|
+
assert_eq!(reader.read_i128(), 123_456_789);
|
|
105
|
+
assert_eq!(reader.read_i128(), i128::MIN);
|
|
106
|
+
assert_eq!(reader.read_i128(), i128::MAX);
|
|
107
|
+
assert_eq!(reader.remaining_len(), 0);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
#[test]
|
|
111
|
+
fn test_read_i8_i16_i32_i64_i128_big_endian_golden_bytes() {
|
|
112
|
+
let env = Env::default();
|
|
113
|
+
|
|
114
|
+
// Layout:
|
|
115
|
+
// - i8: -1, MIN, MAX (3 bytes)
|
|
116
|
+
// - i16: -1, MIN, MAX (6 bytes)
|
|
117
|
+
// - i32: -1, MIN, MAX (12 bytes)
|
|
118
|
+
// - i64: -1, MIN, MAX (24 bytes)
|
|
119
|
+
// - i128: -1, MIN, MAX (48 bytes)
|
|
120
|
+
// Total = 93 bytes
|
|
121
|
+
let mut raw = [0u8; 93];
|
|
122
|
+
let mut pos = 0usize;
|
|
123
|
+
|
|
124
|
+
raw[pos] = (-1i8) as u8;
|
|
125
|
+
pos += 1;
|
|
126
|
+
raw[pos] = i8::MIN as u8;
|
|
127
|
+
pos += 1;
|
|
128
|
+
raw[pos] = i8::MAX as u8;
|
|
129
|
+
pos += 1;
|
|
130
|
+
|
|
131
|
+
raw[pos..pos + 2].copy_from_slice(&(-1i16).to_be_bytes());
|
|
132
|
+
pos += 2;
|
|
133
|
+
raw[pos..pos + 2].copy_from_slice(&i16::MIN.to_be_bytes());
|
|
134
|
+
pos += 2;
|
|
135
|
+
raw[pos..pos + 2].copy_from_slice(&i16::MAX.to_be_bytes());
|
|
136
|
+
pos += 2;
|
|
137
|
+
|
|
138
|
+
raw[pos..pos + 4].copy_from_slice(&(-1i32).to_be_bytes());
|
|
139
|
+
pos += 4;
|
|
140
|
+
raw[pos..pos + 4].copy_from_slice(&i32::MIN.to_be_bytes());
|
|
141
|
+
pos += 4;
|
|
142
|
+
raw[pos..pos + 4].copy_from_slice(&i32::MAX.to_be_bytes());
|
|
143
|
+
pos += 4;
|
|
144
|
+
|
|
145
|
+
raw[pos..pos + 8].copy_from_slice(&(-1i64).to_be_bytes());
|
|
146
|
+
pos += 8;
|
|
147
|
+
raw[pos..pos + 8].copy_from_slice(&i64::MIN.to_be_bytes());
|
|
148
|
+
pos += 8;
|
|
149
|
+
raw[pos..pos + 8].copy_from_slice(&i64::MAX.to_be_bytes());
|
|
150
|
+
pos += 8;
|
|
151
|
+
|
|
152
|
+
raw[pos..pos + 16].copy_from_slice(&[0xFF; 16]); // -1
|
|
153
|
+
pos += 16;
|
|
154
|
+
raw[pos] = 0x80; // i128::MIN (0x80 followed by 15x 0x00)
|
|
155
|
+
pos += 16;
|
|
156
|
+
raw[pos..pos + 16].copy_from_slice(&i128::MAX.to_be_bytes());
|
|
157
|
+
pos += 16;
|
|
158
|
+
|
|
159
|
+
assert_eq!(pos, raw.len());
|
|
160
|
+
|
|
161
|
+
let bytes = Bytes::from_array(&env, &raw);
|
|
162
|
+
let mut reader = BufferReader::new(&bytes);
|
|
163
|
+
|
|
164
|
+
assert_eq!(reader.read_i8(), -1);
|
|
165
|
+
assert_eq!(reader.read_i8(), i8::MIN);
|
|
166
|
+
assert_eq!(reader.read_i8(), i8::MAX);
|
|
167
|
+
assert_eq!(reader.position(), 3);
|
|
168
|
+
|
|
169
|
+
assert_eq!(reader.read_i16(), -1);
|
|
170
|
+
assert_eq!(reader.read_i16(), i16::MIN);
|
|
171
|
+
assert_eq!(reader.read_i16(), i16::MAX);
|
|
172
|
+
assert_eq!(reader.position(), 3 + 6);
|
|
173
|
+
|
|
174
|
+
assert_eq!(reader.read_i32(), -1);
|
|
175
|
+
assert_eq!(reader.read_i32(), i32::MIN);
|
|
176
|
+
assert_eq!(reader.read_i32(), i32::MAX);
|
|
177
|
+
assert_eq!(reader.position(), 3 + 6 + 12);
|
|
178
|
+
|
|
179
|
+
assert_eq!(reader.read_i64(), -1);
|
|
180
|
+
assert_eq!(reader.read_i64(), i64::MIN);
|
|
181
|
+
assert_eq!(reader.read_i64(), i64::MAX);
|
|
182
|
+
assert_eq!(reader.position(), 45);
|
|
183
|
+
|
|
184
|
+
assert_eq!(reader.read_i128(), -1);
|
|
185
|
+
assert_eq!(reader.position(), 45 + 16);
|
|
186
|
+
assert_eq!(reader.read_i128(), i128::MIN);
|
|
187
|
+
assert_eq!(reader.position(), 45 + 16 + 16);
|
|
188
|
+
assert_eq!(reader.read_i128(), i128::MAX);
|
|
189
|
+
assert_eq!(reader.position(), 93);
|
|
190
|
+
|
|
191
|
+
assert_eq!(reader.remaining_len(), 0);
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
#[test]
|
|
195
|
+
fn test_read_i256_big_endian_golden_bytes() {
|
|
196
|
+
use soroban_sdk::I256;
|
|
197
|
+
|
|
198
|
+
let env = Env::default();
|
|
199
|
+
|
|
200
|
+
// Layout: -1, MIN, MAX, +1
|
|
201
|
+
let mut raw = [0u8; 32 * 4];
|
|
202
|
+
raw[0..32].copy_from_slice(&[0xFF; 32]); // -1
|
|
203
|
+
raw[32] = 0x80; // MIN (0x80 followed by 31x 0x00)
|
|
204
|
+
raw[64] = 0x7F; // MAX (0x7F followed by 31x 0xFF)
|
|
205
|
+
raw[65..96].copy_from_slice(&[0xFF; 31]);
|
|
206
|
+
raw[127] = 0x01; // +1
|
|
207
|
+
|
|
208
|
+
let bytes = Bytes::from_array(&env, &raw);
|
|
209
|
+
let mut reader = BufferReader::new(&bytes);
|
|
210
|
+
|
|
211
|
+
let expected_neg1 = I256::from_be_bytes(&env, &Bytes::from_slice(&env, &raw[0..32]));
|
|
212
|
+
let expected_min = I256::from_be_bytes(&env, &Bytes::from_slice(&env, &raw[32..64]));
|
|
213
|
+
let expected_max = I256::from_be_bytes(&env, &Bytes::from_slice(&env, &raw[64..96]));
|
|
214
|
+
let expected_one = I256::from_be_bytes(&env, &Bytes::from_slice(&env, &raw[96..128]));
|
|
215
|
+
|
|
216
|
+
assert_eq!(reader.read_i256(), expected_neg1);
|
|
217
|
+
assert_eq!(reader.position(), 32);
|
|
218
|
+
assert_eq!(reader.read_i256(), expected_min);
|
|
219
|
+
assert_eq!(reader.position(), 64);
|
|
220
|
+
assert_eq!(reader.read_i256(), expected_max);
|
|
221
|
+
assert_eq!(reader.position(), 96);
|
|
222
|
+
assert_eq!(reader.read_i256(), expected_one);
|
|
223
|
+
assert_eq!(reader.position(), 128);
|
|
224
|
+
assert_eq!(reader.remaining_len(), 0);
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
#[test]
|
|
228
|
+
fn test_read_boundary_values() {
|
|
229
|
+
let env = Env::default();
|
|
230
|
+
let mut writer = BufferWriter::new(&env);
|
|
231
|
+
|
|
232
|
+
// Write boundary values for each type
|
|
233
|
+
writer
|
|
234
|
+
.write_u8(0)
|
|
235
|
+
.write_u8(u8::MAX)
|
|
236
|
+
.write_u16(0)
|
|
237
|
+
.write_u16(u16::MAX)
|
|
238
|
+
.write_u32(0)
|
|
239
|
+
.write_u32(u32::MAX)
|
|
240
|
+
.write_u64(0)
|
|
241
|
+
.write_u64(u64::MAX)
|
|
242
|
+
.write_u128(0)
|
|
243
|
+
.write_u128(u128::MAX);
|
|
244
|
+
|
|
245
|
+
let bytes = writer.to_bytes();
|
|
246
|
+
let mut reader = BufferReader::new(&bytes);
|
|
247
|
+
|
|
248
|
+
assert_eq!(reader.read_u8(), 0);
|
|
249
|
+
assert_eq!(reader.read_u8(), u8::MAX);
|
|
250
|
+
assert_eq!(reader.read_u16(), 0);
|
|
251
|
+
assert_eq!(reader.read_u16(), u16::MAX);
|
|
252
|
+
assert_eq!(reader.read_u32(), 0);
|
|
253
|
+
assert_eq!(reader.read_u32(), u32::MAX);
|
|
254
|
+
assert_eq!(reader.read_u64(), 0);
|
|
255
|
+
assert_eq!(reader.read_u64(), u64::MAX);
|
|
256
|
+
assert_eq!(reader.read_u128(), 0);
|
|
257
|
+
assert_eq!(reader.read_u128(), u128::MAX);
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
#[test]
|
|
261
|
+
fn test_read_bool() {
|
|
262
|
+
let env = Env::default();
|
|
263
|
+
let bytes = Bytes::from_array(&env, &[0x00, 0x01, 0x02, 0x7F, 0x80, 0xFF]);
|
|
264
|
+
let mut reader = BufferReader::new(&bytes);
|
|
265
|
+
|
|
266
|
+
assert!(!reader.read_bool()); // 0x00 -> false
|
|
267
|
+
assert!(reader.read_bool()); // 0x01 -> true
|
|
268
|
+
assert!(reader.read_bool()); // 0x02 -> true (any non-zero is true)
|
|
269
|
+
assert!(reader.read_bool()); // 0x7F -> true
|
|
270
|
+
assert!(reader.read_bool()); // 0x80 -> true
|
|
271
|
+
assert!(reader.read_bool()); // 0xFF -> true
|
|
272
|
+
assert_eq!(reader.remaining_len(), 0);
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
#[test]
|
|
276
|
+
fn test_read_u256_boundary_values() {
|
|
277
|
+
use soroban_sdk::U256;
|
|
278
|
+
let env = Env::default();
|
|
279
|
+
|
|
280
|
+
// Zero
|
|
281
|
+
let zero = U256::from_u32(&env, 0);
|
|
282
|
+
test_u256_read_roundtrip(&env, &zero);
|
|
283
|
+
|
|
284
|
+
// From u128::MAX
|
|
285
|
+
let from_u128_max = U256::from_u128(&env, u128::MAX);
|
|
286
|
+
test_u256_read_roundtrip(&env, &from_u128_max);
|
|
287
|
+
|
|
288
|
+
// Max (all 0xFF bytes)
|
|
289
|
+
let max_bytes = Bytes::from_array(&env, &[0xFF; 32]);
|
|
290
|
+
let max_u256 = U256::from_be_bytes(&env, &max_bytes);
|
|
291
|
+
test_u256_read_roundtrip(&env, &max_u256);
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
// ============================================
|
|
295
|
+
// read_bytes tests (read_bytes, read_bytes_n)
|
|
296
|
+
// ============================================
|
|
297
|
+
|
|
298
|
+
#[test]
|
|
299
|
+
fn test_read_bytes_operations() {
|
|
300
|
+
let env = Env::default();
|
|
301
|
+
let bytes = Bytes::from_array(&env, &[0x01, 0x02, 0x03, 0x04, 0x05, 0x06]);
|
|
302
|
+
let mut reader = BufferReader::new(&bytes);
|
|
303
|
+
|
|
304
|
+
// Read partial
|
|
305
|
+
let chunk1 = reader.read_bytes(3);
|
|
306
|
+
assert_eq!(chunk1.len(), 3);
|
|
307
|
+
assert_eq!(chunk1.get(0).unwrap(), 0x01);
|
|
308
|
+
assert_eq!(chunk1.get(2).unwrap(), 0x03);
|
|
309
|
+
|
|
310
|
+
// Read remaining
|
|
311
|
+
let chunk2 = reader.read_bytes_until_end();
|
|
312
|
+
assert_eq!(chunk2.len(), 3);
|
|
313
|
+
assert_eq!(chunk2.get(0).unwrap(), 0x04);
|
|
314
|
+
assert_eq!(chunk2.get(2).unwrap(), 0x06);
|
|
315
|
+
assert_eq!(reader.remaining_len(), 0);
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
#[test]
|
|
319
|
+
fn test_read_bytes_n() {
|
|
320
|
+
let env = Env::default();
|
|
321
|
+
let bytes = Bytes::from_array(
|
|
322
|
+
&env,
|
|
323
|
+
&[
|
|
324
|
+
0x01, 0x02, 0x03, 0x04, // 4 bytes
|
|
325
|
+
0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, // 8 bytes
|
|
326
|
+
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21,
|
|
327
|
+
0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, // 32 bytes
|
|
328
|
+
],
|
|
329
|
+
);
|
|
330
|
+
let mut reader = BufferReader::new(&bytes);
|
|
331
|
+
|
|
332
|
+
let val4: BytesN<4> = reader.read_bytes_n();
|
|
333
|
+
assert_eq!(val4, BytesN::<4>::from_array(&env, &[0x01, 0x02, 0x03, 0x04]));
|
|
334
|
+
|
|
335
|
+
let val8: BytesN<8> = reader.read_bytes_n();
|
|
336
|
+
assert_eq!(val8, BytesN::<8>::from_array(&env, &[0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c]));
|
|
337
|
+
|
|
338
|
+
let val32: BytesN<32> = reader.read_bytes_n();
|
|
339
|
+
assert_eq!(
|
|
340
|
+
val32,
|
|
341
|
+
BytesN::<32>::from_array(
|
|
342
|
+
&env,
|
|
343
|
+
&[
|
|
344
|
+
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20,
|
|
345
|
+
0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f
|
|
346
|
+
]
|
|
347
|
+
)
|
|
348
|
+
);
|
|
349
|
+
|
|
350
|
+
assert_eq!(reader.remaining_len(), 0);
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
#[test]
|
|
354
|
+
fn test_read_array_roundtrip_and_position() {
|
|
355
|
+
let env = Env::default();
|
|
356
|
+
let bytes = Bytes::from_array(&env, &[0xAA, 0xBB, 0xCC, 0xDD, 0x10, 0x11]);
|
|
357
|
+
let mut reader = BufferReader::new(&bytes);
|
|
358
|
+
|
|
359
|
+
let a4: [u8; 4] = reader.read_array();
|
|
360
|
+
assert_eq!(a4, [0xAA, 0xBB, 0xCC, 0xDD]);
|
|
361
|
+
assert_eq!(reader.position(), 4);
|
|
362
|
+
assert_eq!(reader.remaining_len(), 2);
|
|
363
|
+
|
|
364
|
+
let a2: [u8; 2] = reader.read_array();
|
|
365
|
+
assert_eq!(a2, [0x10, 0x11]);
|
|
366
|
+
assert_eq!(reader.position(), 6);
|
|
367
|
+
assert_eq!(reader.remaining_len(), 0);
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
#[test]
|
|
371
|
+
fn test_read_array_write_array_roundtrip() {
|
|
372
|
+
let env = Env::default();
|
|
373
|
+
|
|
374
|
+
let a4: [u8; 4] = [0x01, 0x02, 0x03, 0x04];
|
|
375
|
+
let a1: [u8; 1] = [0xAA];
|
|
376
|
+
let a8: [u8; 8] = [0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17];
|
|
377
|
+
|
|
378
|
+
let mut writer = BufferWriter::new(&env);
|
|
379
|
+
writer.write_array(&a4).write_array(&a1).write_array(&a8);
|
|
380
|
+
|
|
381
|
+
let bytes = writer.to_bytes();
|
|
382
|
+
assert_eq!(bytes.len(), (a4.len() + a1.len() + a8.len()) as u32);
|
|
383
|
+
|
|
384
|
+
let mut reader = BufferReader::new(&bytes);
|
|
385
|
+
let got4: [u8; 4] = reader.read_array();
|
|
386
|
+
assert_eq!(got4, a4);
|
|
387
|
+
assert_eq!(reader.position(), 4);
|
|
388
|
+
|
|
389
|
+
let got1: [u8; 1] = reader.read_array();
|
|
390
|
+
assert_eq!(got1, a1);
|
|
391
|
+
assert_eq!(reader.position(), 5);
|
|
392
|
+
|
|
393
|
+
let got8: [u8; 8] = reader.read_array();
|
|
394
|
+
assert_eq!(got8, a8);
|
|
395
|
+
assert_eq!(reader.position(), 13);
|
|
396
|
+
|
|
397
|
+
assert_eq!(reader.remaining_len(), 0);
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
#[test]
|
|
401
|
+
fn test_read_bytes_zero_length() {
|
|
402
|
+
let env = Env::default();
|
|
403
|
+
let bytes = Bytes::from_array(&env, &[0x01, 0x02, 0x03, 0x04]);
|
|
404
|
+
let mut reader = BufferReader::new(&bytes);
|
|
405
|
+
|
|
406
|
+
// Read zero bytes should return empty bytes and not advance position
|
|
407
|
+
let chunk = reader.read_bytes(0);
|
|
408
|
+
assert_eq!(chunk.len(), 0);
|
|
409
|
+
assert_eq!(reader.position(), 0);
|
|
410
|
+
|
|
411
|
+
// Should be able to read normally after zero-length read
|
|
412
|
+
assert_eq!(reader.read_u8(), 0x01);
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
// ============================================
|
|
416
|
+
// read_bytes_until_end tests
|
|
417
|
+
// ============================================
|
|
418
|
+
|
|
419
|
+
#[test]
|
|
420
|
+
fn test_read_bytes_until_end_at_start() {
|
|
421
|
+
let env = Env::default();
|
|
422
|
+
let bytes = Bytes::from_array(&env, &[0x01, 0x02, 0x03, 0x04]);
|
|
423
|
+
let mut reader = BufferReader::new(&bytes);
|
|
424
|
+
|
|
425
|
+
let all_bytes = reader.read_bytes_until_end();
|
|
426
|
+
assert_eq!(all_bytes.len(), 4);
|
|
427
|
+
assert_eq!(all_bytes.get(0).unwrap(), 0x01);
|
|
428
|
+
assert_eq!(all_bytes.get(3).unwrap(), 0x04);
|
|
429
|
+
assert_eq!(reader.remaining_len(), 0);
|
|
430
|
+
assert_eq!(reader.position(), 4);
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
#[test]
|
|
434
|
+
fn test_read_bytes_until_end_after_partial_read() {
|
|
435
|
+
let env = Env::default();
|
|
436
|
+
let bytes = Bytes::from_array(&env, &[0x01, 0x02, 0x03, 0x04, 0x05]);
|
|
437
|
+
let mut reader = BufferReader::new(&bytes);
|
|
438
|
+
|
|
439
|
+
reader.read_u16(); // Position is now 2
|
|
440
|
+
assert_eq!(reader.position(), 2);
|
|
441
|
+
let remaining = reader.read_bytes_until_end();
|
|
442
|
+
assert_eq!(remaining.len(), 3);
|
|
443
|
+
assert_eq!(remaining.get(0).unwrap(), 0x03);
|
|
444
|
+
assert_eq!(remaining.get(2).unwrap(), 0x05);
|
|
445
|
+
assert_eq!(reader.remaining_len(), 0);
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
#[test]
|
|
449
|
+
fn test_read_bytes_until_end_when_exhausted() {
|
|
450
|
+
let env = Env::default();
|
|
451
|
+
let bytes = Bytes::from_array(&env, &[0x01, 0x02, 0x03, 0x04]);
|
|
452
|
+
let mut reader = BufferReader::new(&bytes);
|
|
453
|
+
|
|
454
|
+
// Exhaust buffer by reading all bytes
|
|
455
|
+
reader.read_bytes(4);
|
|
456
|
+
assert_eq!(reader.remaining_len(), 0);
|
|
457
|
+
|
|
458
|
+
// read_bytes_until_end on exhausted buffer should return empty Bytes
|
|
459
|
+
let empty = reader.read_bytes_until_end();
|
|
460
|
+
assert_eq!(empty.len(), 0);
|
|
461
|
+
assert_eq!(reader.remaining_len(), 0);
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
#[test]
|
|
465
|
+
fn test_read_bytes_until_end_on_empty_buffer() {
|
|
466
|
+
let env = Env::default();
|
|
467
|
+
let bytes = Bytes::from_array(&env, &[]);
|
|
468
|
+
let mut reader = BufferReader::new(&bytes);
|
|
469
|
+
|
|
470
|
+
assert_eq!(reader.remaining_len(), 0);
|
|
471
|
+
let empty = reader.read_bytes_until_end();
|
|
472
|
+
assert_eq!(empty.len(), 0);
|
|
473
|
+
assert_eq!(reader.remaining_len(), 0);
|
|
474
|
+
assert_eq!(reader.position(), 0);
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
// ============================================
|
|
478
|
+
// read_address tests
|
|
479
|
+
// ============================================
|
|
480
|
+
|
|
481
|
+
#[test]
|
|
482
|
+
fn test_read_address_contract_roundtrip() {
|
|
483
|
+
let env = Env::default();
|
|
484
|
+
let address = Address::generate(&env);
|
|
485
|
+
let payload = address.to_payload().unwrap();
|
|
486
|
+
assert!(matches!(payload, AddressPayload::ContractIdHash(_)));
|
|
487
|
+
test_address_roundtrip(&env, &address);
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
#[test]
|
|
491
|
+
fn test_read_address_account_roundtrip() {
|
|
492
|
+
let env = Env::default();
|
|
493
|
+
let account_payload = BytesN::<32>::from_array(
|
|
494
|
+
&env,
|
|
495
|
+
&[
|
|
496
|
+
0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12,
|
|
497
|
+
0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20,
|
|
498
|
+
],
|
|
499
|
+
);
|
|
500
|
+
let address = Address::from_payload(&env, AddressPayload::AccountIdPublicKeyEd25519(account_payload));
|
|
501
|
+
let payload = address.to_payload().unwrap();
|
|
502
|
+
assert!(matches!(payload, AddressPayload::AccountIdPublicKeyEd25519(_)));
|
|
503
|
+
test_address_roundtrip(&env, &address);
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
#[test]
|
|
507
|
+
fn test_read_address_all_zero_payload() {
|
|
508
|
+
let env = Env::default();
|
|
509
|
+
let zero_payload = BytesN::<32>::from_array(&env, &[0x00; 32]);
|
|
510
|
+
let addr = Address::from_payload(&env, AddressPayload::AccountIdPublicKeyEd25519(zero_payload));
|
|
511
|
+
test_address_roundtrip(&env, &addr);
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
#[test]
|
|
515
|
+
fn test_read_address_mixed_types_roundtrip() {
|
|
516
|
+
let env = Env::default();
|
|
517
|
+
let contract_addr = Address::generate(&env);
|
|
518
|
+
let account_payload = BytesN::<32>::from_array(&env, &[0x42; 32]);
|
|
519
|
+
let account_addr = Address::from_payload(&env, AddressPayload::AccountIdPublicKeyEd25519(account_payload));
|
|
520
|
+
|
|
521
|
+
let mut writer = BufferWriter::new(&env);
|
|
522
|
+
writer.write_address(&contract_addr).write_address(&account_addr);
|
|
523
|
+
let bytes = writer.to_bytes();
|
|
524
|
+
|
|
525
|
+
assert_eq!(bytes.len(), 66); // 33 bytes per address
|
|
526
|
+
|
|
527
|
+
let mut reader = BufferReader::new(&bytes);
|
|
528
|
+
assert_eq!(reader.read_address(), contract_addr);
|
|
529
|
+
assert_eq!(reader.read_address(), account_addr);
|
|
530
|
+
assert_eq!(reader.remaining_len(), 0);
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
#[test]
|
|
534
|
+
fn test_address_encoding_golden_bytes() {
|
|
535
|
+
let env = Env::default();
|
|
536
|
+
|
|
537
|
+
let account_payload = BytesN::<32>::from_array(&env, &[0x42; 32]);
|
|
538
|
+
let contract_payload = BytesN::<32>::from_array(&env, &[0x99; 32]);
|
|
539
|
+
|
|
540
|
+
let account_addr = Address::from_payload(&env, AddressPayload::AccountIdPublicKeyEd25519(account_payload.clone()));
|
|
541
|
+
let contract_addr = Address::from_payload(&env, AddressPayload::ContractIdHash(contract_payload.clone()));
|
|
542
|
+
|
|
543
|
+
let mut w = BufferWriter::new(&env);
|
|
544
|
+
w.write_address(&account_addr).write_address(&contract_addr);
|
|
545
|
+
let bytes = w.to_bytes();
|
|
546
|
+
|
|
547
|
+
// Validate raw encoding: 0/1 type byte + 32-byte payload.
|
|
548
|
+
let raw: [u8; 66] = bytes.to_array();
|
|
549
|
+
assert_eq!(raw[0], crate::buffer_writer::ACCOUNT_PAYLOAD_TYPE);
|
|
550
|
+
assert_eq!(raw[1..33], account_payload.to_array());
|
|
551
|
+
assert_eq!(raw[33], crate::buffer_writer::CONTRACT_PAYLOAD_TYPE);
|
|
552
|
+
assert_eq!(raw[34..66], contract_payload.to_array());
|
|
553
|
+
|
|
554
|
+
// Validate reader can decode the raw bytes too.
|
|
555
|
+
let mut r = BufferReader::new(&bytes);
|
|
556
|
+
assert_eq!(r.read_address(), account_addr);
|
|
557
|
+
assert_eq!(r.read_address(), contract_addr);
|
|
558
|
+
assert_eq!(r.remaining_len(), 0);
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
#[test]
|
|
562
|
+
fn test_read_address_with_other_data_roundtrip() {
|
|
563
|
+
let env = Env::default();
|
|
564
|
+
let address = Address::generate(&env);
|
|
565
|
+
|
|
566
|
+
let mut writer = BufferWriter::new(&env);
|
|
567
|
+
writer.write_u32(0x12345678).write_address(&address).write_u64(0xAABBCCDDEEFF0011);
|
|
568
|
+
let bytes = writer.to_bytes();
|
|
569
|
+
|
|
570
|
+
assert_eq!(bytes.len(), 4 + 33 + 8);
|
|
571
|
+
|
|
572
|
+
let mut reader = BufferReader::new(&bytes);
|
|
573
|
+
assert_eq!(reader.read_u32(), 0x12345678);
|
|
574
|
+
assert_eq!(reader.read_address(), address);
|
|
575
|
+
assert_eq!(reader.read_u64(), 0xAABBCCDDEEFF0011);
|
|
576
|
+
assert_eq!(reader.remaining_len(), 0);
|
|
577
|
+
}
|
|
578
|
+
|
|
579
|
+
#[test]
|
|
580
|
+
#[should_panic(expected = "Error(Contract, #1001)")]
|
|
581
|
+
fn test_read_address_invalid_payload_type() {
|
|
582
|
+
let env = Env::default();
|
|
583
|
+
// Create bytes with invalid payload type (not 0 or 1)
|
|
584
|
+
let mut writer = BufferWriter::new(&env);
|
|
585
|
+
writer.write_u8(0xFF); // Invalid payload type
|
|
586
|
+
writer.write_bytes_n(&BytesN::<32>::from_array(&env, &[0x42; 32]));
|
|
587
|
+
let bytes = writer.to_bytes();
|
|
588
|
+
|
|
589
|
+
let mut reader = BufferReader::new(&bytes);
|
|
590
|
+
reader.read_address(); // Should panic with BufferReaderError::InvalidAddressPayload (10001)
|
|
591
|
+
}
|
|
592
|
+
|
|
593
|
+
// ============================================
|
|
594
|
+
// read_address_payload tests
|
|
595
|
+
// ============================================
|
|
596
|
+
|
|
597
|
+
#[test]
|
|
598
|
+
fn test_read_address_payload() {
|
|
599
|
+
let env = Env::default();
|
|
600
|
+
let address = Address::generate(&env);
|
|
601
|
+
let expected_payload = address.to_payload().unwrap();
|
|
602
|
+
|
|
603
|
+
let mut writer = BufferWriter::new(&env);
|
|
604
|
+
writer.write_address_payload(&address);
|
|
605
|
+
let bytes = writer.to_bytes();
|
|
606
|
+
|
|
607
|
+
assert_eq!(bytes.len(), 32); // Only payload, no type byte
|
|
608
|
+
|
|
609
|
+
let mut reader = BufferReader::new(&bytes);
|
|
610
|
+
let payload = reader.read_address_payload();
|
|
611
|
+
assert_address_payload_matches(payload, expected_payload);
|
|
612
|
+
assert_eq!(reader.remaining_len(), 0);
|
|
613
|
+
}
|
|
614
|
+
|
|
615
|
+
#[test]
|
|
616
|
+
#[should_panic(expected = "Error(Contract, #1000)")]
|
|
617
|
+
fn test_read_address_payload_insufficient_bytes() {
|
|
618
|
+
let env = Env::default();
|
|
619
|
+
let bytes = Bytes::from_array(&env, &[0x00; 31]); // Need 32 bytes
|
|
620
|
+
let mut reader = BufferReader::new(&bytes);
|
|
621
|
+
let _payload: BytesN<32> = reader.read_address_payload();
|
|
622
|
+
}
|
|
623
|
+
|
|
624
|
+
// ============================================
|
|
625
|
+
// position tests
|
|
626
|
+
// ============================================
|
|
627
|
+
|
|
628
|
+
#[test]
|
|
629
|
+
fn test_position_operations() {
|
|
630
|
+
let env = Env::default();
|
|
631
|
+
let bytes = Bytes::from_array(&env, &[0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a]);
|
|
632
|
+
let mut reader = BufferReader::new(&bytes);
|
|
633
|
+
|
|
634
|
+
// Test 1: Initial state
|
|
635
|
+
assert_eq!(reader.position(), 0);
|
|
636
|
+
assert_eq!(reader.remaining_len(), 10);
|
|
637
|
+
assert_eq!(reader.len(), 10);
|
|
638
|
+
assert!(!reader.is_empty());
|
|
639
|
+
|
|
640
|
+
// Test 2: Read and check position/remaining relationship
|
|
641
|
+
reader.read_u32();
|
|
642
|
+
assert_eq!(reader.position(), 4);
|
|
643
|
+
assert_eq!(reader.remaining_len(), 6);
|
|
644
|
+
|
|
645
|
+
// Test 3: Skip operation
|
|
646
|
+
reader.skip(2);
|
|
647
|
+
assert_eq!(reader.position(), 6);
|
|
648
|
+
assert_eq!(reader.remaining_len(), 4);
|
|
649
|
+
|
|
650
|
+
// Test 4: Rewind operation
|
|
651
|
+
reader.rewind(3);
|
|
652
|
+
assert_eq!(reader.position(), 3);
|
|
653
|
+
assert_eq!(reader.remaining_len(), 7);
|
|
654
|
+
|
|
655
|
+
// Test 5: Set position operation
|
|
656
|
+
reader.seek(5);
|
|
657
|
+
assert_eq!(reader.position(), 5);
|
|
658
|
+
assert_eq!(reader.remaining_len(), 5);
|
|
659
|
+
|
|
660
|
+
// Test 6: Set position and read
|
|
661
|
+
reader.seek(1);
|
|
662
|
+
assert_eq!(reader.position(), 1);
|
|
663
|
+
assert_eq!(reader.read_u8(), 0x02);
|
|
664
|
+
|
|
665
|
+
// Test 7: Method chaining - skip -> skip -> read
|
|
666
|
+
reader.seek(0);
|
|
667
|
+
let value = reader.skip(2).skip(1).read_u8();
|
|
668
|
+
assert_eq!(value, 0x04);
|
|
669
|
+
assert_eq!(reader.position(), 4);
|
|
670
|
+
|
|
671
|
+
// Test 8: Method chaining - rewind -> read
|
|
672
|
+
reader.rewind(2);
|
|
673
|
+
let value = reader.read_u8();
|
|
674
|
+
assert_eq!(value, 0x03);
|
|
675
|
+
assert_eq!(reader.position(), 3);
|
|
676
|
+
|
|
677
|
+
// Test 9: Method chaining - seek -> read
|
|
678
|
+
let value = reader.seek(0).read_u8();
|
|
679
|
+
assert_eq!(value, 0x01);
|
|
680
|
+
assert_eq!(reader.position(), 1);
|
|
681
|
+
}
|
|
682
|
+
|
|
683
|
+
// ============================================
|
|
684
|
+
// seek tests
|
|
685
|
+
// ============================================
|
|
686
|
+
|
|
687
|
+
#[test]
|
|
688
|
+
fn test_seek_boundary_values() {
|
|
689
|
+
let env = Env::default();
|
|
690
|
+
let bytes = Bytes::from_array(&env, &[0x01, 0x02, 0x03, 0x04]);
|
|
691
|
+
let mut reader = BufferReader::new(&bytes);
|
|
692
|
+
|
|
693
|
+
// Set to start
|
|
694
|
+
reader.seek(0);
|
|
695
|
+
assert_eq!(reader.position(), 0);
|
|
696
|
+
assert_eq!(reader.read_u8(), 0x01);
|
|
697
|
+
|
|
698
|
+
// Set to end (exact boundary - should be valid)
|
|
699
|
+
reader.seek(4);
|
|
700
|
+
assert_eq!(reader.position(), 4);
|
|
701
|
+
assert_eq!(reader.remaining_len(), 0);
|
|
702
|
+
|
|
703
|
+
// Set to middle
|
|
704
|
+
reader.seek(2);
|
|
705
|
+
assert_eq!(reader.position(), 2);
|
|
706
|
+
assert_eq!(reader.read_u8(), 0x03);
|
|
707
|
+
}
|
|
708
|
+
|
|
709
|
+
#[test]
|
|
710
|
+
fn test_seek_on_empty_buffer() {
|
|
711
|
+
let env = Env::default();
|
|
712
|
+
let bytes = Bytes::from_array(&env, &[]);
|
|
713
|
+
let mut reader = BufferReader::new(&bytes);
|
|
714
|
+
|
|
715
|
+
// Should be able to set position to 0 on empty buffer
|
|
716
|
+
reader.seek(0);
|
|
717
|
+
assert_eq!(reader.position(), 0);
|
|
718
|
+
assert_eq!(reader.remaining_len(), 0);
|
|
719
|
+
}
|
|
720
|
+
|
|
721
|
+
#[test]
|
|
722
|
+
#[should_panic(expected = "Error(Contract, #1000)")]
|
|
723
|
+
fn test_seek_beyond_buffer() {
|
|
724
|
+
let env = Env::default();
|
|
725
|
+
let bytes = Bytes::from_array(&env, &[0x01, 0x02, 0x03, 0x04]);
|
|
726
|
+
let mut reader = BufferReader::new(&bytes);
|
|
727
|
+
reader.seek(5); // Buffer length is 4, position 5 is invalid
|
|
728
|
+
}
|
|
729
|
+
|
|
730
|
+
// ============================================
|
|
731
|
+
// skip tests
|
|
732
|
+
// ============================================
|
|
733
|
+
|
|
734
|
+
#[test]
|
|
735
|
+
fn test_skip_zero() {
|
|
736
|
+
let env = Env::default();
|
|
737
|
+
let bytes = Bytes::from_array(&env, &[0x01, 0x02, 0x03, 0x04]);
|
|
738
|
+
let mut reader = BufferReader::new(&bytes);
|
|
739
|
+
|
|
740
|
+
reader.read_u8(); // Position is now 1
|
|
741
|
+
assert_eq!(reader.position(), 1);
|
|
742
|
+
|
|
743
|
+
// Skip zero should be no-op
|
|
744
|
+
reader.skip(0);
|
|
745
|
+
assert_eq!(reader.position(), 1);
|
|
746
|
+
}
|
|
747
|
+
|
|
748
|
+
#[test]
|
|
749
|
+
fn test_skip_to_exact_end() {
|
|
750
|
+
let env = Env::default();
|
|
751
|
+
let bytes = Bytes::from_array(&env, &[0x01, 0x02, 0x03, 0x04]);
|
|
752
|
+
let mut reader = BufferReader::new(&bytes);
|
|
753
|
+
|
|
754
|
+
// Skip to exactly the end (boundary case)
|
|
755
|
+
reader.skip(4);
|
|
756
|
+
assert_eq!(reader.position(), 4);
|
|
757
|
+
assert_eq!(reader.remaining_len(), 0);
|
|
758
|
+
|
|
759
|
+
// Should be able to read_bytes_until_end without error (returns empty)
|
|
760
|
+
let empty = reader.read_bytes_until_end();
|
|
761
|
+
assert_eq!(empty.len(), 0);
|
|
762
|
+
}
|
|
763
|
+
|
|
764
|
+
#[test]
|
|
765
|
+
#[should_panic(expected = "Error(Contract, #1000)")]
|
|
766
|
+
fn test_skip_beyond_buffer() {
|
|
767
|
+
let env = Env::default();
|
|
768
|
+
let bytes = Bytes::from_array(&env, &[0x01, 0x02, 0x03, 0x04]);
|
|
769
|
+
let mut reader = BufferReader::new(&bytes);
|
|
770
|
+
reader.skip(5);
|
|
771
|
+
}
|
|
772
|
+
|
|
773
|
+
// ============================================
|
|
774
|
+
// rewind tests
|
|
775
|
+
// ============================================
|
|
776
|
+
|
|
777
|
+
#[test]
|
|
778
|
+
fn test_rewind_zero() {
|
|
779
|
+
let env = Env::default();
|
|
780
|
+
let bytes = Bytes::from_array(&env, &[0x01, 0x02, 0x03, 0x04]);
|
|
781
|
+
let mut reader = BufferReader::new(&bytes);
|
|
782
|
+
|
|
783
|
+
reader.read_u8(); // Position is now 1
|
|
784
|
+
assert_eq!(reader.position(), 1);
|
|
785
|
+
|
|
786
|
+
// Rewind zero should be no-op
|
|
787
|
+
reader.rewind(0);
|
|
788
|
+
assert_eq!(reader.position(), 1);
|
|
789
|
+
}
|
|
790
|
+
|
|
791
|
+
#[test]
|
|
792
|
+
#[should_panic(expected = "Error(Contract, #1000)")]
|
|
793
|
+
fn test_rewind_beyond_start() {
|
|
794
|
+
let env = Env::default();
|
|
795
|
+
let bytes = Bytes::from_array(&env, &[0x01, 0x02, 0x03, 0x04]);
|
|
796
|
+
let mut reader = BufferReader::new(&bytes);
|
|
797
|
+
reader.read_bytes(2);
|
|
798
|
+
reader.rewind(3); // Can only rewind 2
|
|
799
|
+
}
|
|
800
|
+
|
|
801
|
+
#[test]
|
|
802
|
+
#[should_panic(expected = "Error(Contract, #1000)")]
|
|
803
|
+
fn test_rewind_from_start() {
|
|
804
|
+
let env = Env::default();
|
|
805
|
+
let bytes = Bytes::from_array(&env, &[0x01, 0x02, 0x03]);
|
|
806
|
+
let mut reader = BufferReader::new(&bytes);
|
|
807
|
+
assert_eq!(reader.position(), 0);
|
|
808
|
+
reader.rewind(1); // Position is 0, can't rewind
|
|
809
|
+
}
|
|
810
|
+
|
|
811
|
+
// ============================================
|
|
812
|
+
// buffer_access tests (buffer, env, is_empty, len, remaining)
|
|
813
|
+
// ============================================
|
|
814
|
+
|
|
815
|
+
#[test]
|
|
816
|
+
fn test_buffer_access_and_empty_buffer() {
|
|
817
|
+
let env = Env::default();
|
|
818
|
+
|
|
819
|
+
// Test 1: Buffer and env access
|
|
820
|
+
let bytes1 = Bytes::from_array(&env, &[0x01, 0x02, 0x03, 0x04]);
|
|
821
|
+
let mut reader1 = BufferReader::new(&bytes1);
|
|
822
|
+
reader1.read_u16();
|
|
823
|
+
let buffer = reader1.buffer();
|
|
824
|
+
assert_eq!(buffer.len(), 4);
|
|
825
|
+
assert_eq!(buffer.get(0).unwrap(), 0x01);
|
|
826
|
+
let _new_bytes = Bytes::from_array(reader1.env(), &[0x03, 0x04]);
|
|
827
|
+
|
|
828
|
+
// Test 2: Empty buffer
|
|
829
|
+
let bytes2 = Bytes::from_array(&env, &[]);
|
|
830
|
+
let reader2 = BufferReader::new(&bytes2);
|
|
831
|
+
assert!(reader2.is_empty());
|
|
832
|
+
assert_eq!(reader2.len(), 0);
|
|
833
|
+
assert_eq!(reader2.remaining_len(), 0);
|
|
834
|
+
assert_eq!(reader2.position(), 0);
|
|
835
|
+
}
|
|
836
|
+
|
|
837
|
+
#[test]
|
|
838
|
+
fn test_is_empty_semantics() {
|
|
839
|
+
// is_empty() checks if the BUFFER is empty, not if remaining bytes is zero
|
|
840
|
+
let env = Env::default();
|
|
841
|
+
|
|
842
|
+
// Non-empty buffer: is_empty should always be false regardless of position
|
|
843
|
+
let bytes = Bytes::from_array(&env, &[0x01, 0x02, 0x03, 0x04]);
|
|
844
|
+
let mut reader = BufferReader::new(&bytes);
|
|
845
|
+
|
|
846
|
+
assert!(!reader.is_empty());
|
|
847
|
+
reader.read_bytes(4); // Exhaust buffer
|
|
848
|
+
assert_eq!(reader.remaining_len(), 0);
|
|
849
|
+
assert!(!reader.is_empty()); // Buffer itself is NOT empty, just fully read
|
|
850
|
+
|
|
851
|
+
// Empty buffer: is_empty should be true
|
|
852
|
+
let empty_bytes = Bytes::from_array(&env, &[]);
|
|
853
|
+
let empty_reader = BufferReader::new(&empty_bytes);
|
|
854
|
+
assert!(empty_reader.is_empty());
|
|
855
|
+
}
|
|
856
|
+
|
|
857
|
+
#[test]
|
|
858
|
+
fn test_len_immutable_after_reads() {
|
|
859
|
+
// len() returns total buffer length, should not change after reads
|
|
860
|
+
let env = Env::default();
|
|
861
|
+
let bytes = Bytes::from_array(&env, &[0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08]);
|
|
862
|
+
let mut reader = BufferReader::new(&bytes);
|
|
863
|
+
|
|
864
|
+
assert_eq!(reader.len(), 8);
|
|
865
|
+
|
|
866
|
+
reader.read_u32();
|
|
867
|
+
assert_eq!(reader.len(), 8); // Still 8
|
|
868
|
+
|
|
869
|
+
reader.skip(2);
|
|
870
|
+
assert_eq!(reader.len(), 8); // Still 8
|
|
871
|
+
|
|
872
|
+
reader.read_bytes_until_end();
|
|
873
|
+
assert_eq!(reader.len(), 8); // Still 8
|
|
874
|
+
}
|
|
875
|
+
|
|
876
|
+
// ============================================
|
|
877
|
+
// insufficient_bytes_error tests
|
|
878
|
+
// ============================================
|
|
879
|
+
|
|
880
|
+
#[test]
|
|
881
|
+
fn test_buffer_reader_invalid_length_panics_table() {
|
|
882
|
+
const EXPECTED: &str = "Error(Contract, #1000)";
|
|
883
|
+
|
|
884
|
+
let cases: &[(&str, &[u8], ReaderStep)] = &[
|
|
885
|
+
("read_array<4> from 3", &[0x01, 0x02, 0x03], |r: &mut BufferReader| {
|
|
886
|
+
let _val: [u8; 4] = r.read_array();
|
|
887
|
+
}),
|
|
888
|
+
("read_i8 empty", &[], |r: &mut BufferReader| {
|
|
889
|
+
r.read_i8();
|
|
890
|
+
}),
|
|
891
|
+
("read_i16 1 byte", &[0x01], |r: &mut BufferReader| {
|
|
892
|
+
r.read_i16();
|
|
893
|
+
}),
|
|
894
|
+
("read_i32 3 bytes", &[0x01, 0x02, 0x03], |r: &mut BufferReader| {
|
|
895
|
+
r.read_i32();
|
|
896
|
+
}),
|
|
897
|
+
("read_i64 7 bytes", &[0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07], |r: &mut BufferReader| {
|
|
898
|
+
r.read_i64();
|
|
899
|
+
}),
|
|
900
|
+
("read_u8 empty", &[], |r: &mut BufferReader| {
|
|
901
|
+
r.read_u8();
|
|
902
|
+
}),
|
|
903
|
+
("read_u16 1 byte", &[0x01], |r: &mut BufferReader| {
|
|
904
|
+
r.read_u16();
|
|
905
|
+
}),
|
|
906
|
+
("read_u32 3 bytes", &[0x01, 0x02, 0x03], |r: &mut BufferReader| {
|
|
907
|
+
r.read_u32();
|
|
908
|
+
}),
|
|
909
|
+
("read_u64 7 bytes", &[0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07], |r: &mut BufferReader| {
|
|
910
|
+
r.read_u64();
|
|
911
|
+
}),
|
|
912
|
+
("read_u128 15 bytes", &[0x01; 15], |r: &mut BufferReader| {
|
|
913
|
+
r.read_u128();
|
|
914
|
+
}),
|
|
915
|
+
("read_i128 15 bytes", &[0x01; 15], |r: &mut BufferReader| {
|
|
916
|
+
r.read_i128();
|
|
917
|
+
}),
|
|
918
|
+
("read_u256 31 bytes", &[0x01; 31], |r: &mut BufferReader| {
|
|
919
|
+
r.read_u256();
|
|
920
|
+
}),
|
|
921
|
+
("read_i256 31 bytes", &[0x01; 31], |r: &mut BufferReader| {
|
|
922
|
+
r.read_i256();
|
|
923
|
+
}),
|
|
924
|
+
("read_bytes(10) from 4", &[0x01, 0x02, 0x03, 0x04], |r: &mut BufferReader| {
|
|
925
|
+
r.read_bytes(10);
|
|
926
|
+
}),
|
|
927
|
+
("read_bytes_n<4> from 3", &[0x01, 0x02, 0x03], |r: &mut BufferReader| {
|
|
928
|
+
let _val: BytesN<4> = r.read_bytes_n();
|
|
929
|
+
}),
|
|
930
|
+
("read_address from 32 (needs 33)", &[0x00; 32], |r: &mut BufferReader| {
|
|
931
|
+
r.read_address();
|
|
932
|
+
}),
|
|
933
|
+
("read_bool empty", &[], |r: &mut BufferReader| {
|
|
934
|
+
r.read_bool();
|
|
935
|
+
}),
|
|
936
|
+
];
|
|
937
|
+
|
|
938
|
+
for (name, raw, step) in cases {
|
|
939
|
+
assert_reader_panics_contains(name, raw, *step, EXPECTED);
|
|
940
|
+
}
|
|
941
|
+
}
|
|
942
|
+
|
|
943
|
+
#[test]
|
|
944
|
+
#[should_panic(expected = "Error(Contract, #1000)")]
|
|
945
|
+
fn test_read_after_buffer_exhausted() {
|
|
946
|
+
let env = Env::default();
|
|
947
|
+
let bytes = Bytes::from_array(&env, &[0x01, 0x02, 0x03, 0x04]);
|
|
948
|
+
let mut reader = BufferReader::new(&bytes);
|
|
949
|
+
|
|
950
|
+
let _val = reader.read_u32(); // Exhausts the buffer
|
|
951
|
+
assert_eq!(reader.remaining_len(), 0);
|
|
952
|
+
reader.read_u8(); // Should panic
|
|
953
|
+
}
|
|
954
|
+
|
|
955
|
+
#[test]
|
|
956
|
+
#[should_panic(expected = "Error(Contract, #1000)")]
|
|
957
|
+
fn test_read_insufficient_bytes_after_partial_read() {
|
|
958
|
+
let env = Env::default();
|
|
959
|
+
let bytes = Bytes::from_array(&env, &[0x01, 0x02, 0x03, 0x04]);
|
|
960
|
+
let mut reader = BufferReader::new(&bytes);
|
|
961
|
+
|
|
962
|
+
// Read 2 bytes successfully
|
|
963
|
+
let _chunk = reader.read_bytes(2);
|
|
964
|
+
assert_eq!(reader.remaining_len(), 2);
|
|
965
|
+
|
|
966
|
+
// Try to read 3 bytes when only 2 remain
|
|
967
|
+
// Should panic with InsufficientBytes error
|
|
968
|
+
reader.read_bytes(3);
|
|
969
|
+
}
|