#![allow(unused_variables)]
#![allow(non_snake_case)]
#![allow(non_camel_case_types)]
#![allow(unused_parens)]
#![allow(unused_assignments)]
#![allow(unused_mut)]
#![allow(dead_code)]
#[cfg(feature = "std")]
extern crate std;
use crate::tiny_internal::*;
use crate::zero_terminated::*;
use core::cmp::{min, Ordering};
use core::ops::Add;
use std::eprintln;
use std::string::String;
#[derive(Copy, Clone, Eq)]
pub struct fstr<const N: usize> {
chrs: [u8; N],
len: usize, } impl<const N: usize> fstr<N> {
pub fn make(s: &str) -> fstr<N> {
let bytes = s.as_bytes(); let mut blen = bytes.len();
if (blen > N) {
eprintln!("!Fixedstr Warning in fstr::make: length of string literal \"{}\" exceeds the capacity of type fstr<{}>; string truncated",s,N);
blen = N;
}
let mut chars = [0u8; N];
let mut i = 0;
let limit = min(N, blen);
chars[..limit].clone_from_slice(&bytes[..limit]);
fstr {
chrs: chars,
len: blen,
}
}
pub fn create(s: &str) -> fstr<N> {
let bytes = s.as_bytes(); let mut blen = bytes.len();
if (blen > N) {
blen = N;
}
let mut chars = [0u8; N];
let mut i = 0;
let limit = min(N, blen);
chars[..limit].clone_from_slice(&bytes[..limit]);
fstr {
chrs: chars,
len: blen,
}
}
pub fn try_make(s: &str) -> Result<fstr<N>, &str> {
if s.len() > N {
Err(s)
} else {
Ok(fstr::make(s))
}
}
pub const fn const_create(s:&str) -> fstr<N> {
let mut t = fstr::<N>::new();
let mut len = s.len();
if len>N { len = N; } t.len = len;
let bytes = s.as_bytes();
let mut i = 0;
while i<len {
t.chrs[i] = bytes[i];
i += 1;
}
t
}
pub const fn const_try_create(s:&str) -> Result<fstr<N>, &str> {
if s.len()+1>N { Err(s) }
else { Ok(fstr::const_create(s)) }
}
#[inline]
pub const fn new() -> fstr<N> {
fstr {
chrs:[0;N],
len: 0,
}
}
#[inline]
pub const fn len(&self) -> usize {
self.len
}
pub const fn capacity(&self) -> usize {
N
}
pub fn to_string(&self) -> String {
String::from(self.to_str())
}
pub const fn as_u8(&self) -> [u8; N] {
self.chrs
}
pub fn as_bytes(&self) -> &[u8] {
&self.chrs[0..self.len]
}
pub fn as_bytes_mut(&mut self) -> &mut [u8] {
let n = self.len;
&mut self.chrs[0..n]
}
pub fn to_str(&self) -> &str {
unsafe { std::str::from_utf8_unchecked(&self.chrs[0..self.len]) }
}
pub fn as_str(&self) -> &str {
std::str::from_utf8(&self.chrs[0..self.len]).unwrap()
}
pub fn as_str_safe(&self) -> Result<&str,core::str::Utf8Error> {
core::str::from_utf8(&self.chrs[0..self.len])
}
pub fn set(&mut self, i: usize, c: char) -> bool {
let ref mut cbuf = [0u8; 4]; c.encode_utf8(cbuf);
let clen = c.len_utf8();
if let Some((bi, rc)) = self.to_str().char_indices().nth(i) {
if clen == rc.len_utf8() {
self.chrs[bi..bi + clen].clone_from_slice(&cbuf[..clen]);
return true;
}
}
return false;
}
pub fn push<'t>(&mut self, s: &'t str) -> &'t str {
self.push_str(s)
}
pub fn push_str<'t>(&mut self, src: &'t str) -> &'t str {
let srclen = src.len();
let slen = self.len();
let bytes = &src.as_bytes();
let length = core::cmp::min(slen + srclen, N);
let remain = if N >= (slen + srclen) {
0
} else {
(srclen + slen) - N
};
let mut i = 0;
while i < srclen && i + slen < N {
self.chrs[slen + i] = bytes[i];
i += 1;
} self.len += i;
&src[srclen - remain..]
}
pub fn push_char(&mut self, c: char) -> bool {
let clen = c.len_utf8();
if self.len + clen > N {
return false;
}
let mut buf = [0u8; 4]; let bstr = c.encode_utf8(&mut buf);
self.push(bstr);
true
}
pub fn pop_char(&mut self) -> Option<char> {
if self.len() == 0 {
return None;
}
let (ci, lastchar) = self.char_indices().last().unwrap();
self.len = ci;
Some(lastchar)
}
pub fn charlen(&self) -> usize {
self.to_str().chars().count()
}
pub fn nth(&self, n: usize) -> Option<char> {
self.to_str().chars().nth(n)
}
pub const fn nth_bytechar(&self, n: usize) -> char {
self.chrs[n] as char
}
pub const fn nth_ascii(&self, n: usize) -> char {
self.chrs[n] as char
}
pub fn truncate(&mut self, n: usize) {
if let Some((bi, c)) = self.to_str().char_indices().nth(n) {
self.len = bi;
}
}
pub fn truncate_bytes(&mut self, n: usize) {
if (n < self.len) {
assert!(self.is_char_boundary(n));
self.len = n
}
}
pub fn right_ascii_trim(&mut self) {
let mut n = self.len;
while n > 0 && (self.chrs[n - 1] as char).is_ascii_whitespace() {
n -= 1;
}
assert!(self.is_char_boundary(n));
self.len = n;
}
pub fn clear(&mut self) {
self.len = 0;
}
pub fn make_ascii_lowercase(&mut self) {
assert!(self.is_ascii());
for b in &mut self.chrs[..self.len] {
if *b >= 65 && *b <= 90 {
*b |= 32;
}
}
}
pub fn make_ascii_uppercase(&mut self) {
assert!(self.is_ascii());
for b in &mut self.chrs[..self.len] {
if *b >= 97 && *b <= 122 {
*b -= 32;
}
}
}
pub fn to_ascii_upper(&self) -> Self {
let mut cp = self.clone();
cp.make_ascii_uppercase();
cp
}
pub fn to_ascii_lower(&self) -> Self {
let mut cp = *self;
cp.make_ascii_lowercase();
cp
}
pub fn case_insensitive_eq<TA>(&self, other: TA) -> bool
where
TA: AsRef<str>,
{
if self.len() != other.as_ref().len() {
return false;
}
let obytes = other.as_ref().as_bytes();
for i in 0..self.len() {
let mut c = self.chrs[i];
if (c > 64 && c < 91) {
c = c | 32;
} let mut d = obytes[i];
if (d > 64 && d < 91) {
d = d | 32;
} if c != d {
return false;
}
} true
}
pub fn from_utf16(v: &[u16]) -> Result<Self, Self> {
let mut s = Self::new();
for c in char::decode_utf16(v.iter().cloned()) {
if let Ok(c1) = c {
if !s.push_char(c1) {
return Err(s);
}
} else {
return Err(s);
}
}
Ok(s)
} }
impl<const N: usize> std::ops::Deref for fstr<N> {
type Target = str;
fn deref(&self) -> &Self::Target {
self.to_str()
}
}
impl<T: AsRef<str> + ?Sized, const N: usize> std::convert::From<&T> for fstr<N> {
fn from(s: &T) -> fstr<N> {
fstr::make(s.as_ref())
}
}
impl<T: AsMut<str> + ?Sized, const N: usize> std::convert::From<&mut T> for fstr<N> {
fn from(s: &mut T) -> fstr<N> {
fstr::make(s.as_mut())
}
}
impl<const N: usize> std::convert::From<String> for fstr<N> {
fn from(s: String) -> fstr<N> {
fstr::<N>::make(&s[..])
}
}
impl<const N: usize, const M: usize> std::convert::From<zstr<M>> for fstr<N> {
fn from(s: zstr<M>) -> fstr<N> {
fstr::<N>::make(&s.to_str())
}
}
impl<const N: usize, const M: usize> std::convert::From<tstr<M>> for fstr<N> {
fn from(s: tstr<M>) -> fstr<N> {
fstr::<N>::make(&s.to_str())
}
}
impl<const N: usize> std::cmp::PartialOrd for fstr<N> {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}
impl<const N: usize> std::cmp::Ord for fstr<N> {
fn cmp(&self, other: &Self) -> Ordering {
self.chrs[0..self.len].cmp(&other.chrs[0..other.len])
}
}
impl<const M: usize> fstr<M> {
pub fn resize<const N: usize>(&self) -> fstr<N> {
let length = if (self.len < N) { self.len } else { N };
let mut chars = [0u8; N];
chars[..length].clone_from_slice(&self.chrs[..length]);
fstr {
chrs: chars,
len: length,
}
}
pub fn reallocate<const N: usize>(&self) -> Option<fstr<N>> {
if self.len() <= N {
Some(self.resize())
} else {
None
}
}
}
impl<const N: usize> std::convert::AsRef<str> for fstr<N> {
fn as_ref(&self) -> &str {
self.to_str()
}
}
impl<const N: usize> std::convert::AsMut<str> for fstr<N> {
fn as_mut(&mut self) -> &mut str {
unsafe { std::str::from_utf8_unchecked_mut(&mut self.chrs[0..self.len]) }
}
}
impl<const N: usize> std::fmt::Display for fstr<N> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.pad(self.to_str())
}
}
impl<const N: usize> PartialEq<&str> for fstr<N> {
fn eq(&self, other: &&str) -> bool {
&self.to_str() == other } }
impl<const N: usize> PartialEq<&str> for &fstr<N> {
fn eq(&self, other: &&str) -> bool {
&self.to_str() == other
} }
impl<'t, const N: usize> PartialEq<fstr<N>> for &'t str {
fn eq(&self, other: &fstr<N>) -> bool {
&other.to_str() == self
}
}
impl<'t, const N: usize> PartialEq<&fstr<N>> for &'t str {
fn eq(&self, other: &&fstr<N>) -> bool {
&other.to_str() == self
}
}
impl<const N: usize> Default for fstr<N> {
fn default() -> Self {
fstr::<N>::make("")
}
}
impl<const N: usize> std::fmt::Debug for fstr<N> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.pad(&self.to_str())
}
}
impl<const N: usize> fstr<N> {
pub fn substr(&self, start: usize, end: usize) -> fstr<N> {
let mut chars = [0u8; N];
let mut inds = self.char_indices();
let len = self.len();
if start >= len || end <= start {
return fstr {
chrs: chars,
len: 0,
};
}
let (si, _) = inds.nth(start).unwrap();
let last = if (end >= len) {
len
} else {
match inds.nth(end - start - 1) {
Some((ei, _)) => ei,
None => len,
} };
chars[0..last - si].clone_from_slice(&self.chrs[si..last]);
fstr {
chrs: chars,
len: end - start,
}
} }
impl<const N: usize> core::fmt::Write for fstr<N> {
fn write_str(&mut self, s: &str) -> std::fmt::Result {
let rest = self.push(s);
if rest.len() > 0 {
return Err(core::fmt::Error::default());
}
Ok(())
} }
impl<const N: usize, TA: AsRef<str>> Add<TA> for fstr<N> {
type Output = fstr<N>;
fn add(self, other: TA) -> fstr<N> {
let mut a2 = self;
a2.push(other.as_ref());
a2
}
}
impl<const N: usize> Add<&fstr<N>> for &str {
type Output = fstr<N>;
fn add(self, other: &fstr<N>) -> fstr<N> {
let mut a2 = fstr::from(self);
a2.push(other);
a2
}
}
impl<const N: usize> Add<fstr<N>> for &str {
type Output = fstr<N>;
fn add(self, other: fstr<N>) -> fstr<N> {
let mut a2 = fstr::from(self);
a2.push(&other);
a2
}
}
impl<const N: usize> core::hash::Hash for fstr<N> {
fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
self.as_ref().hash(state);
}
}
impl<const N: usize> PartialEq for fstr<N> {
fn eq(&self, other: &Self) -> bool {
self.as_ref() == other.as_ref()
}
}
impl<const N: usize> core::str::FromStr for fstr<N> {
type Err = &'static str;
fn from_str(s: &str) -> Result<Self, Self::Err> {
if s.len() <= N {
Ok(fstr::from(s))
} else {
Err("capacity exceeded")
}
}
}