use std::borrow::Borrow;
use std::borrow::BorrowMut;
use std::fmt::Display;
use std::ops::{Add, Sub, Mul, Div};
use std::mem;
use crate::helper as helper;
use crate::errors as err;
pub type NecResult = Result<(), err::NotEnoughCapacity>;
pub type IidxResult = Result<(), err::InvalidIndex>;
pub const DEFCAPACITY: usize = 256;
#[derive(Debug, Hash)]
pub struct BFRDYN<const CAPACITY: usize = DEFCAPACITY> {
arr: [u8; CAPACITY],
len: usize
}
impl<const CAPACITY: usize> Display for BFRDYN<CAPACITY> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
helper::fmt(&self.len, &self.arr, f)
}
}
impl<const S1: usize, const S2: usize> From<&BFRDYN<S1>> for BFRDYN<S2> {
fn from(value: &BFRDYN<S1>) -> Self {
let mut arr = [0u8; S2];
let newlen = helper::from_slice2(value, &mut arr);
Self { arr, len: newlen }
}
}
impl<const CAPACITY: usize> From<&str> for BFRDYN<CAPACITY> {
fn from(value: &str) -> Self {
let mut arr = [0u8; CAPACITY];
helper::from_slice(value.as_bytes(), &mut arr);
Self { arr, len: value.len() }
}
}
impl<const CAPACITY: usize> From<&[u8]> for BFRDYN<CAPACITY> {
fn from(value: &[u8]) -> Self {
let mut me = Self::new();
helper::from_slice(value, &mut me.arr);
me.len = value.len();
me
}
}
impl<const CAPACITY: usize> Clone for BFRDYN<CAPACITY> {
fn clone(&self) -> Self { Self { arr: self.arr.clone(), len: self.len.clone() } }
}
impl<const CAPACITY: usize> PartialEq for BFRDYN<CAPACITY> {
fn eq(&self, other: &Self) -> bool {
helper::eq(&self.len, &self.arr, &other.len, &other.arr)
}
fn ne(&self, other: &Self) -> bool {
helper::ne(&self.len, &self.arr, &other.len, &other.arr)
}
}
impl<const CAPACITY: usize> PartialOrd for BFRDYN<CAPACITY> {
fn lt(&self, other: &Self) -> bool { self.checksum() < other.checksum() }
fn gt(&self, other: &Self) -> bool { self.checksum() > other.checksum() }
fn le(&self, other: &Self) -> bool { self.checksum() <= other.checksum() }
fn ge(&self, other: &Self) -> bool { self.checksum() >= other.checksum() }
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> { Some(self.cmp(other)) }
}
impl<const CAPACITY: usize> Eq for BFRDYN<CAPACITY> {}
impl<const CAPACITY: usize> Ord for BFRDYN<CAPACITY> {
fn max(self, other: Self) -> Self
where Self: Sized
{
if self.checksum() > other.checksum() { self } else { other }
}
fn min(self, other: Self) -> Self
where Self: Sized
{
if self.checksum() < other.checksum() { self } else { other }
}
fn clamp(self, min: Self, max: Self) -> Self
where Self: Sized
{
if self.checksum() < min.checksum() { min }
else if self.checksum() > max.checksum() { max }
else { self }
}
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
if self.checksum() < other.checksum() { std::cmp::Ordering::Less }
else if self.checksum() == other.checksum() { std::cmp::Ordering::Equal }
else { std::cmp::Ordering::Greater }
}
}
impl<const CAPACITY: usize> Add for BFRDYN<CAPACITY> {
type Output = usize;
fn add(self, rhs: Self) -> Self::Output {
self.checksum() + rhs.checksum()
}
}
impl<const CAPACITY: usize> Sub for BFRDYN<CAPACITY> {
type Output = usize;
fn sub(self, rhs: Self) -> Self::Output {
self.checksum() - rhs.checksum()
}
}
impl<const CAPACITY: usize> Mul for BFRDYN<CAPACITY> {
type Output = usize;
fn mul(self, rhs: Self) -> Self::Output {
self.checksum() * rhs.checksum()
}
}
impl<const CAPACITY: usize> Div for BFRDYN<CAPACITY> {
type Output = f64;
fn div(self, rhs: Self) -> Self::Output {
self.checksum() as f64 / rhs.checksum() as f64
}
}
impl<const CAPACITY: usize> AsRef<str> for BFRDYN<CAPACITY> {
fn as_ref(&self) -> &str {
unsafe {
std::str::from_utf8_unchecked(&self.arr[0..self.len])
}
}
}
impl<const CAPACITY: usize> AsRef<[u8]> for BFRDYN<CAPACITY> {
fn as_ref(&self) -> &[u8] {
&self.arr[0..self.len]
}
}
impl<const CAPACITY: usize> Borrow<[u8]> for BFRDYN<CAPACITY> {
fn borrow(&self) -> &[u8] {
self.as_ref()
}
}
impl<const CAPACITY: usize> BorrowMut<[u8]> for BFRDYN<CAPACITY> {
fn borrow_mut(&mut self) -> &mut [u8] {
&mut self.arr
}
}
impl<const CAPACITY: usize> std::ops::Deref for BFRDYN<CAPACITY> {
type Target = [u8];
fn deref(&self) -> &Self::Target {
self.as_ref()
}
}
impl BFRDYN {
pub const fn def() -> Self {
Self { arr: [0u8; DEFCAPACITY], len: 0 }
}
pub fn withcap<const CAP: usize>() -> BFRDYN<CAP> {
BFRDYN {
arr: [0u8; CAP],
len: 0
}
}
}
impl<const CAPACITY: usize> BFRDYN<CAPACITY> {
pub const fn new() -> Self { Self { arr: [0u8; CAPACITY], len: 0 } }
pub const fn from_slice(slice: &[u8]) -> Self {
let me = Self::new();
assert!(slice.len() <= me.arr.len(), "Not enough capacity");
let arr_ptr = me.arr.as_slice().as_ptr() as *mut u8; let len_ptr = (&me.len) as *const usize;
unsafe {
std::ptr::copy(slice.as_ptr(), arr_ptr, slice.len());
std::ptr::copy(&slice.len() as *const usize, len_ptr as *mut usize, 1);
}
me
}
pub fn as_str(&self) -> &str {
unsafe {
std::str::from_utf8_unchecked(&self.arr[0..self.len])
}
}
pub const fn as_bytes(&self) -> [u8; CAPACITY] {
self.arr
}
pub unsafe fn bytes_mut(&mut self) -> &mut[u8; CAPACITY] {
&mut self.arr
}
pub fn take_inner(self) -> [u8; CAPACITY] {
self.arr
}
pub fn auto_len(&mut self) {
let mut newlen = 0;
for i in self.arr.iter() {
if *i != 0u8 { newlen += 1 }
else { break; }
}
self.len = newlen;
}
pub unsafe fn increase_len(&mut self, by: usize) {
self.len += by
}
pub unsafe fn decrease_len(&mut self, by: usize) {
self.len -= by
}
pub const fn capacity(&self) -> usize { self.arr.len() }
pub const fn len(&self) -> usize { self.len }
pub const fn checksum(&self) -> usize {
let mut result = 0;
let mut i = 0;
while i < self.len {
result += self.arr[i] as usize;
i += 1;
}
result
}
pub const fn contain_str(&self, criteria: &str) -> bool {
let mut i = 0;
if criteria.len() > self.len { return false; }
let criteria = criteria.as_bytes();
while i < (1 + self.len - criteria.len()) {
let mut j = 0;
let mut current = criteria[j];
while current == self.arr[i+j] {
j += 1;
if j >= criteria.len() { return true; }
current = criteria[j];
}
i += 1;
}
false
}
pub fn contains(&self, criteria: &str) -> bool {
if criteria.len() > self.len { return false; }
let mut i = 0;
while i <= (self.len - criteria.len()) {
let current = &self.arr[i..criteria.len()+i];
if criteria.as_bytes() == current { return true; }
i += 1;
}
false
}
pub const fn last(&self) -> u8 {
if self.len > 0 {
self.arr[self.len-1]
}
else { 0u8 }
}
pub fn last_char(&self) -> char {
if self.len > 0 {
self.arr[self.len-1].into()
}
else { '\0' }
}
pub fn clear(&mut self) {
self.arr = [0u8; CAPACITY];
self.len = 0;
}
pub unsafe fn prepend_unchecked(&mut self, other: &mut Self) {
mem::swap(&mut self.arr, &mut other.arr);
for i in 0..self.len {
self.arr[other.len+i] = other.arr[i]
}
let self_len_temp = self.len;
self.len += other.len;
other.len = self_len_temp;
}
pub fn prepend(&mut self, mut other: Self) -> NecResult {
let total_len = self.len + other.len;
if total_len <= self.capacity() {
unsafe {self.prepend_unchecked(&mut other);}
Ok(())
} else {
Err(err::NotEnoughCapacity::throw(self.capacity(), total_len))
}
}
pub fn prepend_str(&mut self, text: &str) -> NecResult {
let total_len = self.len + text.len();
if total_len <= self.capacity() {
let mut other: Self = text.into();
unsafe {self.prepend_unchecked(&mut other);}
Ok(())
} else {
Err(err::NotEnoughCapacity::throw(self.capacity(), total_len))
}
}
pub fn append(&mut self, other: Self) -> NecResult {
let total_len = self.len + other.len;
if total_len <= self.capacity() {
for i in 0..(other.len) {
self.arr[self.len+i] = other.arr[i]
}
self.len += other.len;
Ok(())
} else {
Err(err::NotEnoughCapacity::throw(self.capacity(), total_len))
}
}
pub fn append_str(&mut self, text: &str) -> NecResult {
let total_len = self.len + text.len();
if total_len <= self.capacity() {
for i in 0..text.len() {
self.arr[self.len+i] = text.as_bytes()[i]
}
self.len += text.len();
Ok(())
} else {
Err(err::NotEnoughCapacity::throw(self.capacity(), total_len))
}
}
pub fn append_ch(&mut self, c: char) -> NecResult {
let total_len = self.len + c.len_utf8();
if total_len <= self.capacity() {
for i in 0..c.len_utf8() {
self.arr[self.len+i] = c as u8
}
self.len += c.len_utf8();
Ok(())
} else {
Err(err::NotEnoughCapacity::throw(self.capacity(), total_len))
}
}
pub fn rshift(&mut self, pos: usize) -> IidxResult {
if pos < self.len && self.len < self.capacity() {
let mut idx = self.len;
while idx > pos {
self.arr[idx] = self.arr[idx-1];
idx -= 1;
}
self.len += 1;
Ok(())
} else {
Err(err::InvalidIndex::throw(self.len, pos))
}
}
pub fn lshift(&mut self, pos: usize) -> IidxResult {
if pos < self.len {
for i in pos..self.len {
self.arr[i] = self.arr[i+1]
}
self.arr[self.len] = 0u8;
self.len -= 1;
Ok(())
} else {
Err(err::InvalidIndex::throw(self.len, pos))
}
}
pub fn take(&mut self, pos: usize) -> Option<u8> {
if pos < self.len {
let result = self.arr[pos];
self.lshift(pos).unwrap();
Some(result)
}
else { None }
}
pub fn insert(&mut self, other: Self, pos: usize) -> NecResult {
let total_len = self.len + other.len;
if total_len <= self.capacity() && pos < self.len {
let mut idx = pos;
for i in 0..other.len {
self.rshift(idx)?;
self.arr[idx] = other.arr[i];
idx += 1;
}
Ok(())
} else {
Err(err::NotEnoughCapacity::throw(self.capacity(), total_len))
}
}
pub fn insert_ch(&mut self, c: char, pos: usize) -> NecResult {
if self.len < self.capacity() {
self.rshift(pos)?;
self.arr[pos] = c as u8;
Ok(())
}
else {
Err(err::NotEnoughCapacity::throw(self.capacity(), self.len+1))
}
}
pub fn reverse(&mut self) {
let mid = self.len/2;
let mut idx = (0usize, self.len-1);
while idx.0 < mid {
let temp = self.arr[idx.0];
self.arr[idx.0] = self.arr[idx.1];
self.arr[idx.1] = temp;
idx.0 += 1;
idx.1 -= 1;
}
}
pub fn isort(&mut self) {
for i in 1..self.len() {
let mut j;
for x in 0..i {
j = i - x;
if self.arr[j] < self.arr[j-1] {
let temp = self.arr[j];
self.arr[j] = self.arr[j-1];
self.arr[j-1] = temp;
} else { break; }
}
}
}
pub fn isort_desc(&mut self) {
for i in 1..self.len() {
let mut j;
for x in 0..i {
j = i - x;
if self.arr[j] > self.arr[j-1] {
let temp = self.arr[j];
self.arr[j] = self.arr[j-1];
self.arr[j-1] = temp;
} else { break; }
}
}
}
pub fn sort(&mut self) {
let mut sorted = false;
while !sorted {
sorted = true;
for i in 0..(self.len-1) {
if self.arr[i+1] < self.arr[i] {
let temp = self.arr[i];
self.arr[i] = self.arr[i+1];
self.arr[i+1] = temp;
sorted = false;
}
}
}
}
pub fn sort_desc(&mut self) {
let mut sorted = false;
while !sorted {
sorted = true;
for i in 0..(self.len-1) {
if self.arr[i+1] > self.arr[i] {
let temp = self.arr[i];
self.arr[i] = self.arr[i+1];
self.arr[i+1] = temp;
sorted = false;
}
}
}
}
pub fn ltrim(&mut self) {
let mut idx = self.len;
while self.arr[0] == ' ' as u8 && idx > 1 {
self.lshift(0).unwrap();
idx -= 1;
}
}
pub fn rtrim(&mut self) {
while self.arr[self.len-1] == ' ' as u8 && self.len > 1 {
self.arr[self.len-1] = 0u8;
self.len -= 1;
}
}
pub fn trim(&mut self) { self.ltrim(); self.rtrim(); }
pub fn lower(&mut self) {
for (i, c) in self.arr.iter_mut().enumerate() {
if i > (self.len-1) { break; }
if *c <= 90 && *c >= 65 {
*c = *c + 32;
}
}
}
pub fn upper(&mut self) {
for (i, c) in self.arr.iter_mut().enumerate() {
if i > (self.len-1) { break; }
if *c >= 97 && *c <= 122 {
*c = *c - 32;
}
}
}
pub fn title(&mut self) {
self.lower();
self.arr[0] -= 32;
}
pub fn proper(&mut self) {
let mut change_next = false;
self.title();
for (idx, c) in self.arr.iter_mut().enumerate() {
if change_next && *c != ' ' as u8 {
*c = *c - 32;
change_next = false;
}
if idx < self.len-1 && *c == ' ' as u8 {
change_next = true;
}
}
}
pub unsafe fn get_slice_unchecked(&self, start: usize, end: usize) -> &[u8] {
&self.arr[start..end]
}
pub fn get_slice(&self, start: usize, end: usize) -> Result<&[u8], err::InvalidIndex> {
if start >= (self.len-1) || end > (self.len) || start > end {
Err(err::InvalidIndex::throw(start, end))
} else {
Ok(&self.arr[start..end])
}
}
pub fn to_vecir(&self, c: char) -> Vec<String> {
let mut v = Vec::<String>::new();
let mut start: usize = 0;
let mut end: usize = 0;
for i in self.arr {
end += 1;
if i == c as u8 {
let x = &self.arr[start..end-1];
let bfr: BFRDYN<CAPACITY> = x.into();
v.push(bfr.to_string());
start = end-1;
}
}
let last = &self.arr[start..self.len];
let bfr: BFRDYN<CAPACITY> = last.into();
v.push(bfr.to_string());
v
}
pub fn to_vecil(&self, c: char) -> Vec<String> {
let mut v = Vec::<String>::new();
let mut start: usize = 0;
let mut end: usize = 0;
for i in self.arr {
end += 1;
if i == c as u8 {
let x = &self.arr[start..end];
let bfr: BFRDYN<CAPACITY> = x.into();
v.push(bfr.to_string());
start = end;
}
}
let last = &self.arr[start..self.len];
let bfr: BFRDYN<CAPACITY> = last.into();
v.push(bfr.to_string());
v
}
pub fn to_vec(&self, c: char) -> Vec<String> {
let mut v = Vec::<String>::new();
let mut start: usize = 0;
let mut end: usize = 0;
for i in self.arr {
end += 1;
if i == c as u8 {
let x = &self.arr[start..end-1];
let bfr: BFRDYN<CAPACITY> = x.into();
v.push(bfr.to_string());
start = end;
}
}
let last = &self.arr[start..self.len];
let bfr: BFRDYN<CAPACITY> = last.into();
v.push(bfr.to_string());
v
}
pub fn to_vec2(&self, s: &str) -> Vec<String> {
let mut v = Vec::<String>::new();
let mut start: usize = 0;
for (i, _) in self.arr.iter().enumerate() {
if i + s.len() > self.len { break; }
if self.arr[i..i+s.len()] == s.as_bytes()[..] {
let x = &self.arr[start..i];
let bfr: BFRDYN<CAPACITY> = x.into();
v.push(bfr.to_string());
start = i+s.len();
}
}
let last = &self.arr[start..self.len];
let bfr: BFRDYN<CAPACITY> = last.into();
v.push(bfr.to_string());
v
}
pub fn to_vecr(&self, s: &str, r: char) -> Vec<String> {
let mut v = Vec::<String>::new();
let mut start: usize = 0;
for (i, _) in self.arr.iter().enumerate() {
if i + s.len() > self.len { break; }
let end = i+s.len();
if (self.arr[i..end] == s.as_bytes()[..]) && self.arr[end..end+1][0] != r as u8 {
let x = &self.arr[start..i];
let bfr: BFRDYN<CAPACITY> = x.into();
v.push(bfr.to_string());
start = i+s.len();
}
}
let last = &self.arr[start..self.len];
let bfr: BFRDYN<CAPACITY> = last.into();
v.push(bfr.to_string());
v
}
pub fn to_veclr(&self, c: char, lchar: char, rchar: char) -> Vec<String> {
let mut v = Vec::<String>::new();
let mut start: usize = 0;
for (i, _) in self.arr.iter().enumerate() {
if i == 1 { continue; }
if i+1 > self.len { break; }
let end = i+1;
if self.arr[i..end][0] == c as u8 && (self.arr[end-2..end-1][0] == lchar as u8) && (self.arr[end..end+1][0] == rchar as u8) {
let x = &self.arr[start..i];
let bfr: BFRDYN<CAPACITY> = x.into();
v.push(bfr.to_string());
start = i+1;
}
}
let last = &self.arr[start..self.len];
let bfr: BFRDYN<CAPACITY> = last.into();
v.push(bfr.to_string());
v
}
pub fn split(self, criteria: char) -> Option<(Self, Self)> {
for (i, c) in self.arr.iter().enumerate() {
if *c as char == criteria {
let left: Self = self.arr[0..i].into();
let right: Self = self.arr[i+1..self.len].into();
return Some((left, right));
}
}
None
}
pub fn split_incl(self, criteria: char) -> Option<(Self, Self)> {
for (i, c) in self.arr.iter().enumerate() {
if *c as char == criteria {
let left: Self = self.arr[0..i].into();
let right: Self = self.arr[i..self.len].into();
return Some((left, right));
}
}
None
}
pub fn split_incl_left(self, criteria: char) -> Option<(Self, Self)> {
for (i, c) in self.arr.iter().enumerate() {
if *c as char == criteria {
let left: Self = self.arr[0..i+1].into();
let right: Self = self.arr[i+1..self.len].into();
return Some((left, right));
}
}
None
}
pub fn split2(self, criteria: &str) -> Option<(Self, Self)> {
for (i, _) in self.arr.iter().enumerate() {
if i + criteria.len() > self.len { break; }
if self.arr[i..i+criteria.len()] == criteria.as_bytes()[..] {
let left = &self.arr[0..i];
let right = &self.arr[i+criteria.len()..self.len];
let lf: Self = left.into();
let rg: Self = right.into();
return Some((lf, rg))
}
}
None
}
pub fn split2_incl(self, criteria: &str) -> Option<(Self, Self)> {
for (i, _) in self.arr.iter().enumerate() {
if i + criteria.len() > self.len { break; }
if self.arr[i..i+criteria.len()] == criteria.as_bytes()[..] {
let left = &self.arr[0..i];
let right = &self.arr[i..self.len];
let lf: Self = left.into();
let rg: Self = right.into();
return Some((lf, rg))
}
}
None
}
pub fn split2_incl_left(self, criteria: &str) -> Option<(Self, Self)> {
for (i, _) in self.arr.iter().enumerate() {
if i + criteria.len() > self.len { break; }
if self.arr[i..i+criteria.len()] == criteria.as_bytes()[..] {
let left = &self.arr[0..i+criteria.len()];
let right = &self.arr[i+criteria.len()..self.len];
let lf: Self = left.into();
let rg: Self = right.into();
return Some((lf, rg))
}
}
None
}
pub fn starts_with(&self, criteria: &str) -> bool {
&self.arr[0..criteria.len()] == criteria.as_bytes()
}
pub fn ends_with(&self, criteria: &str) -> bool {
&self.arr[self.len()-criteria.len()..self.len()] == criteria.as_bytes()
}
pub fn pop(&mut self) -> Option<char> {
if self.len > 0 {
self.len -= 1;
let last = self.arr[self.len];
self.arr[self.len] = 0u8;
return Some(last as char);
}
None
}
pub fn popn(&mut self, n: usize) -> Option<Self> {
if self.len >= n {
self.len -= n;
let popped: Self = self.arr[self.len..self.len+n].into();
let newlen = self.len;
self.arr[newlen..].fill(0u8);
return Some(popped);
}
None
}
pub fn take_head(&mut self, n: usize) -> Option<Self> {
if self.len >= n {
let popped: Self = self.arr[0..n].into();
for _ in 0..n {
self.lshift(0).unwrap();
}
return Some(popped);
}
None
}
}