casper_contract_sdk/collections/
vector.rs1use crate::{
2 abi::{CasperABI, Declaration, Definition, Definitions, StructField},
3 casper::{self, read_into_vec},
4 prelude::{cmp::Ordering, marker::PhantomData},
5 serializers::borsh::{BorshDeserialize, BorshSerialize},
6};
7
8use casper_executor_wasm_common::keyspace::Keyspace;
9
10#[derive(BorshSerialize, BorshDeserialize, Debug, Clone)]
11#[borsh(crate = "crate::serializers::borsh")]
12pub struct Vector<T> {
13 pub(crate) prefix: String,
14 pub(crate) length: u64,
15 pub(crate) _marker: PhantomData<T>,
16}
17
18impl<T: CasperABI> CasperABI for Vector<T> {
19 fn populate_definitions(_definitions: &mut Definitions) {}
20
21 fn declaration() -> Declaration {
22 format!("Vector<{}>", T::declaration())
23 }
24
25 fn definition() -> Definition {
26 Definition::Struct {
27 items: vec![
28 StructField {
29 name: "prefix".into(),
30 decl: String::declaration(),
31 },
32 StructField {
33 name: "length".into(),
34 decl: u64::declaration(),
35 },
36 ],
37 }
38 }
39}
40
41impl<T> Vector<T>
42where
43 T: BorshSerialize + BorshDeserialize,
44{
45 pub fn new<S: Into<String>>(prefix: S) -> Self {
50 Self {
51 prefix: prefix.into(),
52 length: 0,
53 _marker: PhantomData,
54 }
55 }
56
57 pub fn push(&mut self, value: T) {
59 let prefix_bytes = self.compute_prefix_bytes_for_index(self.length);
60 let prefix = Keyspace::Context(&prefix_bytes);
61 casper::write(prefix, &borsh::to_vec(&value).unwrap()).unwrap();
62 self.length += 1;
63 }
64
65 pub fn pop(&mut self) -> Option<T> {
67 if self.is_empty() {
68 return None;
69 }
70 self.swap_remove(self.len() - 1)
71 }
72
73 pub fn contains(&self, value: &T) -> bool
77 where
78 T: PartialEq,
79 {
80 self.iter().any(|v| v == *value)
81 }
82
83 pub fn get(&self, index: u64) -> Option<T> {
85 let prefix = self.compute_prefix_bytes_for_index(index);
86 let item_keyspace = Keyspace::Context(&prefix);
87 read_into_vec(item_keyspace)
88 .unwrap()
89 .map(|vec| borsh::from_slice(&vec).unwrap())
90 }
91
92 pub fn iter(&self) -> impl Iterator<Item = T> + '_ {
94 (0..self.length).map(move |i| self.get(i).unwrap())
95 }
96
97 pub fn insert(&mut self, index: u64, value: T) {
100 assert!(index <= self.length, "index out of bounds");
101
102 for i in (index..self.length).rev() {
104 if let Some(src_value) = self.get(i) {
105 self.write(i + 1, src_value);
106 }
107 }
108
109 self.write(index, value);
111
112 self.length += 1;
113 }
114
115 pub fn clear(&mut self) {
119 for i in 0..self.length {
120 let prefix_bytes = self.compute_prefix_bytes_for_index(i);
121 let item_keyspace = Keyspace::Context(&prefix_bytes);
122 casper::remove(item_keyspace).unwrap();
123 }
124 self.length = 0;
125 }
126
127 #[inline(always)]
129 pub fn len(&self) -> u64 {
130 self.length
131 }
132
133 #[inline(always)]
135 pub fn is_empty(&self) -> bool {
136 self.length == 0
137 }
138
139 pub fn binary_search(&self, value: &T) -> Result<u64, u64>
142 where
143 T: Ord,
144 {
145 self.binary_search_by(|v| v.cmp(value))
146 }
147
148 pub fn binary_search_by<F>(&self, mut f: F) -> Result<u64, u64>
155 where
156 F: FnMut(&T) -> Ordering,
157 {
158 let mut size = self.len();
163 let mut left = 0;
164 let mut right = size;
165 while left < right {
166 let mid = left + size / 2;
167
168 let cmp = f(&self.get(mid).unwrap());
173
174 left = if cmp == Ordering::Less { mid + 1 } else { left };
179 right = if cmp == Ordering::Greater { mid } else { right };
180 if cmp == Ordering::Equal {
181 assert!(mid < self.len());
183 return Ok(mid);
184 }
185
186 size = right - left;
187 }
188
189 assert!(left <= self.len());
192 Err(left)
193 }
194
195 pub fn remove(&mut self, index: u64) -> Option<T> {
201 if index >= self.length {
202 return None;
203 }
204
205 let value_to_remove = self.get(index).unwrap();
206
207 for i in index..(self.length - 1) {
209 if let Some(next_value) = self.get(i + 1) {
210 self.write(i, next_value);
211 }
212 }
213
214 self.length -= 1;
216 casper::remove(Keyspace::Context(
217 &self.compute_prefix_bytes_for_index(self.length),
218 ))
219 .unwrap();
220
221 Some(value_to_remove)
222 }
223
224 pub fn swap_remove(&mut self, index: u64) -> Option<T> {
229 if index >= self.length {
230 return None;
231 }
232
233 let value_to_remove = self.get(index).unwrap();
234 let last_value = self.get(self.len() - 1).unwrap();
235
236 if index != self.len() - 1 {
237 self.write(index, last_value);
238 }
239
240 self.length -= 1;
241 casper::remove(Keyspace::Context(
242 &self.compute_prefix_bytes_for_index(self.length),
243 ))
244 .unwrap();
245
246 Some(value_to_remove)
247 }
248
249 pub fn retain<F>(&mut self, mut f: F)
251 where
252 F: FnMut(&T) -> bool,
253 {
254 let mut i = 0;
255 while i < self.length {
256 if !f(&self.get(i).unwrap()) {
257 self.remove(i).unwrap();
258 } else {
259 i += 1;
260 }
261 }
262 }
263
264 #[inline(always)]
265 fn compute_prefix_bytes_for_index(&self, index: u64) -> Vec<u8> {
266 compute_prefix_bytes_for_index(&self.prefix, index)
267 }
268
269 fn write(&self, index: u64, value: T) {
270 let prefix_bytes = self.compute_prefix_bytes_for_index(index);
271 let prefix = Keyspace::Context(&prefix_bytes);
272 casper::write(prefix, &borsh::to_vec(&value).unwrap()).unwrap();
273 }
274}
275
276fn compute_prefix_bytes_for_index(prefix: &str, index: u64) -> Vec<u8> {
277 let mut prefix_bytes = prefix.as_bytes().to_owned();
278 prefix_bytes.extend(&index.to_le_bytes());
279 prefix_bytes
280}
281
282#[cfg(all(test, feature = "std"))]
283pub(crate) mod tests {
284 use core::ptr::NonNull;
285
286 use self::casper::native::dispatch;
287
288 use super::*;
289
290 const TEST_VEC_PREFIX: &str = "test_vector";
291 type VecU64 = Vector<u64>;
292
293 fn get_vec_elements_from_storage(prefix: &str) -> Vec<u64> {
294 let mut values = Vec::new();
295 for idx in 0..64 {
296 let prefix = compute_prefix_bytes_for_index(prefix, idx);
297 let mut value: [u8; 8] = [0; 8];
298 let result = casper::read(Keyspace::Context(&prefix), |size| {
299 assert_eq!(size, 8);
300 NonNull::new(value.as_mut_ptr())
301 })
302 .unwrap();
303
304 if result.is_some() {
305 values.push(u64::from_le_bytes(value));
306 }
307 }
308 values
309 }
310
311 #[test]
312 fn should_not_panic_with_empty_vec() {
313 dispatch(|| {
314 let mut vec = VecU64::new(TEST_VEC_PREFIX);
315 assert_eq!(vec.len(), 0);
316 assert_eq!(vec.remove(0), None);
317 vec.retain(|_| false);
318 let _ = vec.binary_search(&123);
319 assert_eq!(
320 get_vec_elements_from_storage(TEST_VEC_PREFIX),
321 Vec::<u64>::new()
322 );
323 })
324 .unwrap();
325 }
326
327 #[test]
328 fn should_retain() {
329 dispatch(|| {
330 let mut vec = VecU64::new(TEST_VEC_PREFIX);
331
332 vec.push(1);
333 vec.push(2);
334 vec.push(3);
335 vec.push(4);
336 vec.push(5);
337
338 vec.retain(|v| *v % 2 == 0);
339
340 let vec: Vec<_> = vec.iter().collect();
341 assert_eq!(vec, vec![2, 4]);
342
343 assert_eq!(get_vec_elements_from_storage(TEST_VEC_PREFIX), vec![2, 4]);
344 })
345 .unwrap();
346 }
347
348 #[test]
349 fn test_vec() {
350 dispatch(|| {
351 let mut vec = VecU64::new(TEST_VEC_PREFIX);
352
353 assert!(vec.get(0).is_none());
354 vec.push(111);
355 assert_eq!(vec.get(0), Some(111));
356 vec.push(222);
357 assert_eq!(vec.get(1), Some(222));
358
359 vec.insert(0, 42);
360 vec.insert(0, 41);
361 vec.insert(1, 43);
362 vec.insert(5, 333);
363 vec.insert(5, 334);
364 assert_eq!(vec.remove(5), Some(334));
365 assert_eq!(vec.remove(55), None);
366
367 let mut iter = vec.iter();
368 assert_eq!(iter.next(), Some(41));
369 assert_eq!(iter.next(), Some(43));
370 assert_eq!(iter.next(), Some(42));
371 assert_eq!(iter.next(), Some(111));
372 assert_eq!(iter.next(), Some(222));
373 assert_eq!(iter.next(), Some(333));
374 assert_eq!(iter.next(), None);
375
376 {
377 let ser = borsh::to_vec(&vec).unwrap();
378 let deser: Vector<u64> = borsh::from_slice(&ser).unwrap();
379 let mut iter = deser.iter();
380 assert_eq!(iter.next(), Some(41));
381 assert_eq!(iter.next(), Some(43));
382 assert_eq!(iter.next(), Some(42));
383 assert_eq!(iter.next(), Some(111));
384 assert_eq!(iter.next(), Some(222));
385 assert_eq!(iter.next(), Some(333));
386 assert_eq!(iter.next(), None);
387 }
388
389 assert_eq!(
390 get_vec_elements_from_storage(TEST_VEC_PREFIX),
391 vec![41, 43, 42, 111, 222, 333]
392 );
393
394 let vec2 = VecU64::new("test1");
395 assert_eq!(vec2.get(0), None);
396
397 assert_eq!(get_vec_elements_from_storage("test1"), Vec::<u64>::new());
398 })
399 .unwrap();
400 }
401
402 #[test]
403 fn test_pop() {
404 dispatch(|| {
405 let mut vec = VecU64::new(TEST_VEC_PREFIX);
406 assert_eq!(vec.pop(), None);
407 vec.push(1);
408 vec.push(2);
409 assert_eq!(vec.pop(), Some(2));
410 assert_eq!(vec.len(), 1);
411 assert_eq!(vec.pop(), Some(1));
412 assert!(vec.is_empty());
413
414 assert_eq!(
415 get_vec_elements_from_storage(TEST_VEC_PREFIX),
416 Vec::<u64>::new()
417 );
418 })
419 .unwrap();
420 }
421
422 #[test]
423 fn test_contains() {
424 dispatch(|| {
425 let mut vec = VecU64::new(TEST_VEC_PREFIX);
426 vec.push(1);
427 vec.push(2);
428 assert!(vec.contains(&1));
429 assert!(vec.contains(&2));
430 assert!(!vec.contains(&3));
431 vec.remove(0);
432 assert!(!vec.contains(&1));
433 assert_eq!(get_vec_elements_from_storage(TEST_VEC_PREFIX), vec![2]);
434 })
435 .unwrap();
436 }
437
438 #[test]
439 fn test_clear() {
440 dispatch(|| {
441 let mut vec = VecU64::new(TEST_VEC_PREFIX);
442 vec.push(1);
443 vec.push(2);
444 vec.clear();
445 assert_eq!(vec.len(), 0);
446 assert!(vec.is_empty());
447 assert_eq!(vec.get(0), None);
448 vec.push(3);
449 assert_eq!(vec.get(0), Some(3));
450
451 assert_eq!(get_vec_elements_from_storage(TEST_VEC_PREFIX), vec![3]);
452 })
453 .unwrap();
454 }
455
456 #[test]
457 fn test_binary_search() {
458 dispatch(|| {
459 let mut vec = VecU64::new(TEST_VEC_PREFIX);
460 vec.push(1);
461 vec.push(2);
462 vec.push(3);
463 vec.push(4);
464 vec.push(5);
465 assert_eq!(vec.binary_search(&3), Ok(2));
466 assert_eq!(vec.binary_search(&0), Err(0));
467 assert_eq!(vec.binary_search(&6), Err(5));
468 })
469 .unwrap();
470 }
471
472 #[test]
473 fn test_swap_remove() {
474 dispatch(|| {
475 let mut vec = VecU64::new(TEST_VEC_PREFIX);
476 vec.push(1);
477 vec.push(2);
478 vec.push(3);
479 vec.push(4);
480 assert_eq!(vec.swap_remove(1), Some(2));
481 assert_eq!(vec.iter().collect::<Vec<_>>(), vec![1, 4, 3]);
482 assert_eq!(vec.swap_remove(2), Some(3));
483 assert_eq!(vec.iter().collect::<Vec<_>>(), vec![1, 4]);
484
485 assert_eq!(get_vec_elements_from_storage(TEST_VEC_PREFIX), vec![1, 4]);
486 })
487 .unwrap();
488 }
489
490 #[test]
491 fn test_insert_at_len() {
492 dispatch(|| {
493 let mut vec = VecU64::new(TEST_VEC_PREFIX);
494 vec.push(1);
495 vec.insert(1, 2);
496 assert_eq!(vec.iter().collect::<Vec<_>>(), vec![1, 2]);
497 assert_eq!(get_vec_elements_from_storage(TEST_VEC_PREFIX), vec![1, 2]);
498 })
499 .unwrap();
500 }
501
502 #[test]
503 fn test_struct_elements() {
504 #[derive(BorshSerialize, BorshDeserialize, PartialEq, Debug)]
505 struct TestStruct {
506 field: u64,
507 }
508
509 dispatch(|| {
510 let mut vec = Vector::new(TEST_VEC_PREFIX);
511 vec.push(TestStruct { field: 1 });
512 vec.push(TestStruct { field: 2 });
513 assert_eq!(vec.get(1), Some(TestStruct { field: 2 }));
514 })
515 .unwrap();
516 }
517
518 #[test]
519 fn test_multiple_operations() {
520 dispatch(|| {
521 let mut vec = VecU64::new(TEST_VEC_PREFIX);
522 assert!(vec.is_empty());
523 vec.push(1);
524 vec.insert(0, 2);
525 vec.push(3);
526 assert_eq!(vec.iter().collect::<Vec<_>>(), vec![2, 1, 3]);
527 assert_eq!(vec.swap_remove(0), Some(2));
528 assert_eq!(vec.iter().collect::<Vec<_>>(), vec![3, 1]);
529 assert_eq!(vec.pop(), Some(1));
530 assert_eq!(vec.get(0), Some(3));
531 vec.clear();
532 assert!(vec.is_empty());
533
534 assert_eq!(
535 get_vec_elements_from_storage(TEST_VEC_PREFIX),
536 Vec::<u64>::new()
537 );
538 })
539 .unwrap();
540 }
541
542 #[test]
543 fn test_remove_invalid_index() {
544 dispatch(|| {
545 let mut vec = VecU64::new(TEST_VEC_PREFIX);
546 vec.push(1);
547 assert_eq!(vec.remove(1), None);
548 assert_eq!(vec.remove(0), Some(1));
549 assert_eq!(vec.remove(0), None);
550 })
551 .unwrap();
552 }
553
554 #[test]
555 #[should_panic(expected = "index out of bounds")]
556 fn test_insert_out_of_bounds() {
557 dispatch(|| {
558 let mut vec = VecU64::new(TEST_VEC_PREFIX);
559 vec.insert(1, 1);
560 })
561 .unwrap();
562 }
563}