use crate::as_slice_mut;
use crate::base::*;
use crate::buffers::RUMBuffer;
use crate::cpu::*;
use crate::mem::AsPtr;
use rand::{distr::Alphanumeric, RngExt};
use std::alloc::{alloc, Layout};
#[inline(always)]
pub fn slice_to_buffer(buffer: &[u8]) -> RUMBuffer {
RUMBuffer::from(buffer)
}
#[inline(always)]
pub fn new_random_buffer<'a, const N: usize>() -> RUMVec<u8> {
let buffer = unsafe { alloc(Layout::from_size_align_unchecked(N, size_of::<u8>())) };
let slice = as_slice_mut(buffer, N * size_of::<u8>());
rand::fill(slice);
unsafe { RUMVec::from_raw_parts(buffer, N, N) }
}
#[inline(always)]
pub fn new_random_rumbuffer<const N: usize>() -> RUMBuffer {
slice_to_buffer(&new_random_buffer::<N>())
}
pub fn new_random_string_buffer<const N: usize>() -> RUMString {
rand::rng()
.sample_iter(&Alphanumeric)
.take(N) .map(char::from)
.collect()
}
pub fn new_random_string_set<const N: usize>(item_count: usize) -> RUMVec<RUMString> {
let mut set = RUMVec::<RUMString>::with_capacity(item_count);
for _ in 0..item_count {
set.push(new_random_string_buffer::<N>())
}
set
}
#[inline(always)]
pub fn buffer_to_string(buffer: &[u8]) -> RUMResult<RUMString> {
match RUMString::from_utf8(buffer.to_vec()) {
Ok(string) => Ok(string),
Err(e) => Err(rumtk_format!("Failure to parse incoming UTF-8 string: {}", e)),
}
}
#[inline(always)]
pub fn buffer_to_str(buffer: &[u8]) -> RUMResult<&str> {
match std::str::from_utf8(buffer) {
Ok(string) => Ok(string),
Err(e) => Err(rumtk_format!("Failure to parse incoming UTF-8 string: {}", e)),
}
}
#[inline(always)]
pub fn buffer_count(buffer: &[u8], pattern: u8) -> usize {
bytecount::count(buffer, pattern)
}
#[inline(always)]
pub fn buffer_contains(buffer: &[u8], pattern: u8) -> bool {
buffer_find_byte(buffer, pattern).unwrap_or(buffer.len()) < buffer.len()
}
#[inline(always)]
pub fn buffer_find_byte(buffer: &[u8], byte: u8) -> Option<usize> {
if buffer.is_empty() { return None }
if buffer[0] == byte { return Some(0) }
cpu_find(buffer, byte)
}
#[inline(always)]
pub fn buffer_find(buffer: &[u8], pattern: &[u8]) -> usize {
if buffer.is_empty() {
return buffer.len();
}
let start_pattern_byte = pattern[0];
let pattern_length = pattern.len();
let mut working_buffer = buffer;
let mut cumulative = 0;
let mut end = 0;
while (end + pattern_length) < working_buffer.len() {
working_buffer = &working_buffer[end..];
if working_buffer[..pattern_length] == *pattern {
return cumulative;
} else {
working_buffer = &working_buffer[pattern_length..];
cumulative += pattern_length;
}
end = buffer_find_byte(&working_buffer, start_pattern_byte).unwrap_or(working_buffer.len());
cumulative += end;
}
buffer.len()
}
#[inline(always)]
pub fn buffer_find_instances<'a>(buffer: &'a [u8], pattern: &[u8]) -> RUMVec<(usize, &'a [u8])> {
if buffer.is_empty() {
return RUMVec::new();
}
let pattern_length = pattern.len();
let buffer_length = buffer.len() - pattern_length;
let mut instances = RUMVec::<(usize, &[u8])>::with_capacity(100);
let mut cursor = buffer_find(buffer, pattern);
let mut cumulative = cursor;
let mut remainder = &buffer[..];
while cumulative < buffer_length {
instances.push((cumulative, &remainder[..cursor]));
let next = cursor + pattern_length;
if next <= remainder.len() {
remainder = &remainder[cursor + pattern_length..];
cursor = buffer_find(remainder, pattern);
cumulative += cursor;
} else {
cumulative += remainder.len();
}
}
instances
}
#[inline(always)]
pub fn buffer_replace_in_place<'a>(buffer: &'a mut [u8], pattern: &[u8], replacement: &[u8]) {
if buffer.is_empty() || pattern.is_empty() || replacement.is_empty() {
return;
}
if pattern.len() == 1 {
cpu_replace_byte(buffer, pattern[0], replacement[0]);
return;
}
let replacement_length = replacement.len();
let mut cursor = buffer_find(&buffer, pattern);
let mut remainder = buffer;
while cursor < remainder.len() {
for i in 0..replacement_length {
remainder[cursor + i] = replacement[i];
}
remainder = &mut remainder[cursor + pattern.len()..];
cursor = buffer_find(remainder, pattern);
}
}
#[inline(always)]
pub fn buffer_replace(buffer: &[u8], pattern: &[u8], replacement: &[u8]) -> RUMBuffer {
match buffer.is_empty() {
true => RUMBuffer::from(buffer),
false => {
let pattern_length = pattern.len();
let replacement_length = replacement.len();
let instances = buffer_find_instances(&buffer, pattern);
let mut new_buffer = RUMVec::with_capacity(buffer.len() + (instances.len() * (replacement_length)));
let mut last = 0;
for (indx, chunk) in instances {
new_buffer.extend_from_slice(chunk);
new_buffer.extend_from_slice(replacement);
last = indx + pattern_length;
}
new_buffer.extend_from_slice(&buffer[last..]);
RUMBuffer::from(new_buffer)
}
}
}
#[inline]
pub fn buffer_trim(buffer: &[u8]) -> RUMBuffer {
let trimmed = buffer_slice_trim(buffer);
RUMBuffer::from_parts(trimmed.as_ptr(), trimmed.len(), false)
}
#[inline(always)]
pub fn buffer_slice_trim(buffer: &[u8]) -> &[u8] {
buffer.trim_ascii()
}
pub fn buffer_has_pattern(buffer: &[u8], pattern: &[u8]) -> bool {
buffer_find(buffer, pattern) != buffer.len()
}
pub fn is_unique_bytes(data: &[u8]) -> bool {
let mut items = ahash::AHashSet::with_capacity(data.len());
for i in 0..data.len() {
if !items.insert(data[i]) {
return false;
}
}
true
}