xrpl_std/core/
locator.rs

1/// The size of the buffer, in bytes, to use for any new locator
2const LOCATOR_BUFFER_SIZE: usize = 64;
3
4// /// A Locator may only pack this many levels deep in an object hierarchy (inclusive of the first
5// /// field)
6// const MAX_DEPTH: u8 = 12; // 1 byte for slot; 5 bytes for each packed object.
7
8/// A Locator allows a WASM developer located any field in any object (even nested fields) by
9/// specifying a `slot_num` (1 byte); a `locator_field_type` (1 byte); then one of an `sfield` (4
10/// bytes) or an `index` (4 bytes).
11#[derive(Debug, Clone, Copy, Eq, PartialEq)]
12#[repr(C)]
13pub struct Locator {
14    // The first packed value is 6 bytes; All nested/packed values are 5 bytes; so 64 bytes allow
15    // 12 nested levels of access.
16    buffer: [u8; LOCATOR_BUFFER_SIZE],
17
18    /// An index into `buffer` where the next packing operation can be stored.
19    cur_buffer_index: usize,
20}
21
22impl Default for Locator {
23    fn default() -> Self {
24        Self::new()
25    }
26}
27
28impl Locator {
29    /// Create a new Locator using an unsigned 8-bit slot number. Valid slots are 0 to 255.
30    pub fn new_with_slot(slot_num: u8) -> Locator {
31        let mut buffer: [u8; 64] = [0; 64];
32        buffer[0] = slot_num;
33        Self {
34            buffer,
35            cur_buffer_index: 1,
36        }
37    }
38
39    /// Create a new Locator. Valid slots are 0 to 255.
40    pub fn new() -> Locator {
41        Self {
42            buffer: [0; 64],
43            cur_buffer_index: 0,
44        }
45    }
46
47    pub fn pack(&mut self, sfield_or_index: i32) -> bool {
48        if self.cur_buffer_index + 4 > LOCATOR_BUFFER_SIZE {
49            return false;
50        }
51
52        let value_bytes: [u8; 4] = sfield_or_index.to_le_bytes();
53
54        for byte in value_bytes.iter() {
55            match self.buffer.get_mut(self.cur_buffer_index) {
56                Some(b) => *b = *byte,
57                None => return false,
58            }
59            self.cur_buffer_index += 1;
60        }
61
62        true
63    }
64
65    pub fn get_addr(&self) -> *const u8 {
66        self.buffer.as_ptr()
67    }
68
69    pub fn as_ptr(&self) -> *const u8 {
70        self.buffer.as_ptr()
71    }
72
73    pub fn num_packed_bytes(&self) -> usize {
74        self.cur_buffer_index
75    }
76
77    pub fn len(&self) -> usize {
78        self.cur_buffer_index
79    }
80
81    pub fn is_empty(&self) -> bool {
82        self.cur_buffer_index == 0
83    }
84
85    pub fn repack_last(&mut self, sfield_or_index: i32) -> bool {
86        self.cur_buffer_index -= 4;
87
88        let value_bytes: [u8; 4] = sfield_or_index.to_le_bytes();
89
90        for byte in value_bytes.iter() {
91            match self.buffer.get_mut(self.cur_buffer_index) {
92                Some(b) => *b = *byte,
93                None => return false,
94            }
95            self.cur_buffer_index += 1;
96        }
97
98        true
99    }
100}