rumtk_arena/buffers/
helpers.rs1use crate::as_slice_mut;
21use crate::base::*;
22use crate::buffers::RUMBuffer;
23use crate::cpu::*;
24use crate::mem::AsPtr;
25use rand::{distr::Alphanumeric, RngExt};
26use std::alloc::{alloc, Layout};
27
28#[inline(always)]
44pub fn slice_to_buffer(buffer: &[u8]) -> RUMBuffer {
45 RUMBuffer::from(buffer)
46}
47
48#[inline(always)]
65pub fn new_random_buffer<'a, const N: usize>() -> RUMVec<u8> {
66 let buffer = unsafe { alloc(Layout::from_size_align_unchecked(N, size_of::<u8>())) };
67 let slice = as_slice_mut(buffer, N * size_of::<u8>());
68
69 rand::fill(slice);
70 unsafe { RUMVec::from_raw_parts(buffer, N, N) }
71}
72
73#[inline(always)]
90pub fn new_random_rumbuffer<const N: usize>() -> RUMBuffer {
91 slice_to_buffer(&new_random_buffer::<N>())
92}
93
94pub fn new_random_string_buffer<const N: usize>() -> RUMString {
111 rand::rng()
112 .sample_iter(&Alphanumeric)
113 .take(N) .map(char::from)
115 .collect()
116}
117
118pub fn new_random_string_set<const N: usize>(item_count: usize) -> RUMVec<RUMString> {
137 let mut set = RUMVec::<RUMString>::with_capacity(item_count);
138
139 for _ in 0..item_count {
140 set.push(new_random_string_buffer::<N>())
141 }
142
143 set
144}
145
146#[inline(always)]
162pub fn buffer_to_string(buffer: &[u8]) -> RUMResult<RUMString> {
163 match RUMString::from_utf8(buffer.to_vec()) {
164 Ok(string) => Ok(string),
165 Err(e) => Err(rumtk_format!("Failure to parse incoming UTF-8 string: {}", e)),
166 }
167}
168
169#[inline(always)]
170pub fn buffer_to_str(buffer: &[u8]) -> RUMResult<&str> {
171 match std::str::from_utf8(buffer) {
172 Ok(string) => Ok(string),
173 Err(e) => Err(rumtk_format!("Failure to parse incoming UTF-8 string: {}", e)),
174 }
175}
176
177#[inline(always)]
178pub fn buffer_count(buffer: &[u8], pattern: u8) -> usize {
179 bytecount::count(buffer, pattern)
180}
181
182#[inline(always)]
183pub fn buffer_contains(buffer: &[u8], pattern: u8) -> bool {
184 buffer_find_byte(buffer, pattern).unwrap_or(buffer.len()) < buffer.len()
185}
186
187#[inline(always)]
188pub fn buffer_find_byte(buffer: &[u8], byte: u8) -> Option<usize> {
189 if buffer.is_empty() { return None }
191
192 if buffer[0] == byte { return Some(0) }
194
195 cpu_find(buffer, byte)
197}
198
199#[inline(always)]
200pub fn buffer_find(buffer: &[u8], pattern: &[u8]) -> usize {
201 if buffer.is_empty() {
202 return buffer.len();
203 }
204
205 let start_pattern_byte = pattern[0];
206 let pattern_length = pattern.len();
207 let mut working_buffer = buffer;
208 let mut cumulative = 0;
209 let mut end = 0;
210
211 while (end + pattern_length) < working_buffer.len() {
212 working_buffer = &working_buffer[end..];
213
214 if working_buffer[..pattern_length] == *pattern {
215 return cumulative;
216 } else {
217 working_buffer = &working_buffer[pattern_length..];
218 cumulative += pattern_length;
219 }
220
221 end = buffer_find_byte(&working_buffer, start_pattern_byte).unwrap_or(working_buffer.len());
222 cumulative += end;
223 }
224
225 buffer.len()
226}
227
228#[inline(always)]
229pub fn buffer_find_instances<'a>(buffer: &'a [u8], pattern: &[u8]) -> RUMVec<(usize, &'a [u8])> {
230 if buffer.is_empty() {
231 return RUMVec::new();
232 }
233
234 let pattern_length = pattern.len();
235 let buffer_length = buffer.len() - pattern_length;
236 let mut instances = RUMVec::<(usize, &[u8])>::with_capacity(100);
237
238 let mut cursor = buffer_find(buffer, pattern);
239 let mut cumulative = cursor;
240 let mut remainder = &buffer[..];
241
242 while cumulative < buffer_length {
243 instances.push((cumulative, &remainder[..cursor]));
244 let next = cursor + pattern_length;
245 if next <= remainder.len() {
246 remainder = &remainder[cursor + pattern_length..];
247 cursor = buffer_find(remainder, pattern);
248 cumulative += cursor;
249 } else {
250 cumulative += remainder.len();
251 }
252 }
253
254 instances
255}
256
257#[inline(always)]
258pub fn buffer_replace_in_place<'a>(buffer: &'a mut [u8], pattern: &[u8], replacement: &[u8]) {
259 if buffer.is_empty() || pattern.is_empty() || replacement.is_empty() {
261 return;
262 }
263
264 if pattern.len() == 1 {
266 cpu_replace_byte(buffer, pattern[0], replacement[0]);
267 return;
268 }
269
270 let replacement_length = replacement.len();
271 let mut cursor = buffer_find(&buffer, pattern);
272 let mut remainder = buffer;
273
274 while cursor < remainder.len() {
275 for i in 0..replacement_length {
276 remainder[cursor + i] = replacement[i];
277 }
278
279 remainder = &mut remainder[cursor + pattern.len()..];
280 cursor = buffer_find(remainder, pattern);
281 }
282}
283
284#[inline(always)]
285pub fn buffer_replace(buffer: &[u8], pattern: &[u8], replacement: &[u8]) -> RUMBuffer {
286 match buffer.is_empty() {
287 true => RUMBuffer::from(buffer),
288 false => {
289 let pattern_length = pattern.len();
290 let replacement_length = replacement.len();
291 let instances = buffer_find_instances(&buffer, pattern);
292 let mut new_buffer = RUMVec::with_capacity(buffer.len() + (instances.len() * (replacement_length)));
293 let mut last = 0;
294
295 for (indx, chunk) in instances {
296 new_buffer.extend_from_slice(chunk);
297 new_buffer.extend_from_slice(replacement);
298 last = indx + pattern_length;
299 }
300
301 new_buffer.extend_from_slice(&buffer[last..]);
302 RUMBuffer::from(new_buffer)
303 }
304 }
305}
306
307#[inline]
308pub fn buffer_trim(buffer: &[u8]) -> RUMBuffer {
309 let trimmed = buffer_slice_trim(buffer);
310 RUMBuffer::from_parts(trimmed.as_ptr(), trimmed.len(), false)
311}
312
313#[inline(always)]
314pub fn buffer_slice_trim(buffer: &[u8]) -> &[u8] {
315 buffer.trim_ascii()
316}
317
318pub fn buffer_has_pattern(buffer: &[u8], pattern: &[u8]) -> bool {
319 buffer_find(buffer, pattern) != buffer.len()
320}
321
322pub fn is_unique_bytes(data: &[u8]) -> bool {
323 let mut items = ahash::AHashSet::with_capacity(data.len());
324 for i in 0..data.len() {
325 if !items.insert(data[i]) {
326 return false;
327 }
328 }
329 true
330}