@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.
@@ -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
+ }