xrpl_wasm_stdlib/core/
locator.rs1const LOCATOR_BUFFER_SIZE: usize = 64; #[derive(Clone, PartialEq, Eq, Debug)]
33#[repr(C)]
34pub struct Locator {
35 buffer: [u8; LOCATOR_BUFFER_SIZE],
36
37 cur_buffer_index: usize,
39}
40
41impl Default for Locator {
42 fn default() -> Self {
43 Self::new()
44 }
45}
46
47impl Locator {
48 pub fn new() -> Locator {
50 Self {
51 buffer: [0; LOCATOR_BUFFER_SIZE],
52 cur_buffer_index: 0,
53 }
54 }
55
56 pub fn pack(&mut self, sfield_or_index: impl Into<i32>) -> bool {
57 if self.cur_buffer_index + 4 > LOCATOR_BUFFER_SIZE {
58 return false;
59 }
60
61 let value_bytes: [u8; 4] = sfield_or_index.into().to_le_bytes();
62 self.buffer[self.cur_buffer_index..self.cur_buffer_index + 4].copy_from_slice(&value_bytes);
63 self.cur_buffer_index += 4;
64
65 true
66 }
67
68 pub fn as_ptr(&self) -> *const u8 {
69 self.buffer.as_ptr()
70 }
71
72 pub fn num_packed_bytes(&self) -> usize {
73 self.cur_buffer_index
74 }
75
76 pub fn len(&self) -> usize {
77 self.cur_buffer_index
78 }
79
80 pub fn is_empty(&self) -> bool {
81 self.cur_buffer_index == 0
82 }
83
84 pub fn repack_last(&mut self, sfield_or_index: impl Into<i32>) -> bool {
85 if self.cur_buffer_index < 4 {
86 return false;
87 }
88
89 self.cur_buffer_index -= 4;
90
91 let value_bytes: [u8; 4] = sfield_or_index.into().to_le_bytes();
92 self.buffer[self.cur_buffer_index..self.cur_buffer_index + 4].copy_from_slice(&value_bytes);
93 self.cur_buffer_index += 4;
94
95 true
96 }
97}
98
99#[cfg(test)]
100mod tests {
101 use super::*;
102 use crate::sfield;
103
104 #[test]
105 fn test_pack_with_sfield_no_into_needed() {
106 let mut locator = Locator::new();
108
109 assert!(locator.pack(sfield::Memos));
111 assert!(locator.pack(0));
112 assert!(locator.pack(sfield::MemoData));
113
114 assert_eq!(locator.len(), 12); }
116
117 #[test]
118 fn test_pack_with_i32_still_works() {
119 let mut locator = Locator::new();
121
122 assert!(locator.pack(123i32));
123 assert!(locator.pack(456i32));
124
125 assert_eq!(locator.len(), 8); }
127
128 #[test]
129 fn test_repack_last_with_sfield() {
130 let mut locator = Locator::new();
131
132 locator.pack(sfield::Memos);
133 locator.pack(0);
134
135 assert!(locator.repack_last(sfield::MemoData));
137
138 assert_eq!(locator.len(), 8); }
140
141 #[test]
142 fn test_new_starts_empty() {
143 let locator = Locator::new();
144 assert_eq!(locator.len(), 0);
145 assert!(locator.is_empty());
146 }
147
148 #[test]
149 fn test_default_same_as_new() {
150 assert_eq!(Locator::default(), Locator::new());
151 }
152
153 #[test]
154 fn test_pack_writes_correct_bytes() {
155 let mut locator = Locator::new();
156 assert!(locator.pack(0x12345678i32));
157 assert_eq!(locator.len(), 4);
158
159 let bytes = unsafe { core::slice::from_raw_parts(locator.as_ptr(), 4) };
160 assert_eq!(bytes, &0x12345678i32.to_le_bytes());
161 }
162
163 #[test]
164 fn test_pack_returns_false_when_buffer_full() {
165 let mut locator = Locator::new();
166
167 for i in 0..16 {
169 assert!(locator.pack(i));
170 }
171 assert_eq!(locator.len(), 64);
172
173 assert!(!locator.pack(999i32));
175 assert_eq!(locator.len(), 64);
176 }
177
178 #[test]
179 fn test_is_empty_false_after_pack() {
180 let mut locator = Locator::new();
181 assert!(locator.is_empty());
182
183 locator.pack(sfield::Memos);
184 assert!(!locator.is_empty());
185 assert_eq!(locator.len(), 4);
186 }
187
188 #[test]
189 fn test_num_packed_bytes_equals_len() {
190 let mut locator = Locator::new();
191 assert_eq!(locator.num_packed_bytes(), locator.len());
192
193 locator.pack(sfield::Memos);
194 assert_eq!(locator.num_packed_bytes(), locator.len());
195 assert_eq!(locator.num_packed_bytes(), 4);
196
197 locator.pack(0);
198 assert_eq!(locator.num_packed_bytes(), locator.len());
199 assert_eq!(locator.num_packed_bytes(), 8);
200 }
201
202 #[test]
203 fn test_repack_last_on_empty_returns_false() {
204 let mut locator = Locator::new();
205 assert!(!locator.repack_last(sfield::Memos));
206 assert_eq!(locator.len(), 0);
207 }
208
209 #[test]
210 fn test_repack_last_overwrites_correct_bytes() {
211 let mut locator = Locator::new();
212 locator.pack(0x11111111i32);
213 locator.pack(0x22222222i32);
214 assert_eq!(locator.len(), 8);
215
216 assert!(locator.repack_last(0x33333333i32));
217 assert_eq!(locator.len(), 8);
218
219 let bytes = unsafe { core::slice::from_raw_parts(locator.as_ptr(), 8) };
220 assert_eq!(&bytes[0..4], &0x11111111i32.to_le_bytes());
222 assert_eq!(&bytes[4..8], &0x33333333i32.to_le_bytes());
224 }
225}