#![allow(unused_variables)]
#![allow(non_snake_case)]
#![allow(non_camel_case_types)]
#![allow(unused_parens)]
#![allow(unused_assignments)]
#![allow(unused_mut)]
#![allow(unused_imports)]
#![allow(dead_code)]
extern crate alloc;
use crate::tstr;
use crate::zstr;
#[cfg(feature = "std")]
use crate::fstr;
use crate::{str12, str128, str16, str192, str24, str256, str32, str4, str48, str64, str8, str96};
use alloc::string::String;
use alloc::vec::Vec;
use core::cmp::{min, Ordering};
use core::ops::Add;
use crate::shared_structs::Strunion;
use crate::shared_structs::Strunion::*;
#[derive(Clone, Eq, PartialEq, Hash)]
pub struct Flexstr<const N: usize = 32> {
inner: Strunion<N>,
}
impl<const N: usize> Flexstr<N> {
pub fn make(s: &str) -> Self {
if s.len() < N && N <= 256 {
Flexstr {
inner: fixed(tstr::<N>::from(s)),
}
} else {
Flexstr {
inner: owned(String::from(s)),
}
}
}
pub fn from_string(s: String) -> Self {
if s.len() < N && N <= 256 {
Flexstr {
inner: fixed(tstr::<N>::from(&s[..])),
}
} else {
Flexstr { inner: owned(s) }
}
}
pub fn from_tstr(s: tstr<N>) -> Self {
Flexstr { inner: fixed(s) }
}
#[cfg(feature = "serde")]
pub fn try_make(s: &str) -> Result<Flexstr<N>, &str> {
Ok(Flexstr::make(s))
}
pub fn len(&self) -> usize {
match &self.inner {
fixed(s) => s.len(),
owned(s) => s.len(),
} }
pub fn new() -> Self {
Self::default()
}
pub fn charlen(&self) -> usize {
match &self.inner {
fixed(s) => s.charlen(),
owned(s) => {
s.chars().count()
}
} }
pub fn to_str(&self) -> &str {
match &self.inner {
fixed(s) => s.to_str(),
owned(s) => &s[..],
} }
pub fn as_str(&self) -> &str {
match &self.inner {
fixed(s) => s.as_str(),
owned(s) => &s[..],
} }
pub fn get_str(&self) -> Option<tstr<N>> {
if let fixed(s) = &self.inner {
Some(*s)
} else {
None
}
}
pub fn take_string(&mut self) -> Option<String> {
if let owned(s) = &mut self.inner {
let mut temp = fixed(tstr::new());
core::mem::swap(&mut self.inner, &mut temp);
if let owned(t) = temp {
Some(t)
} else {
None
}
} else {
None
}
}
pub fn to_string(self) -> String {
match self.inner {
fixed(s) => s.to_string(),
owned(s) => s,
} }
pub fn nth(&self, n: usize) -> Option<char> {
self.to_str().chars().nth(n)
}
pub fn nth_bytechar(&self, n: usize) -> char {
match &self.inner {
fixed(s) => s.nth_ascii(n),
owned(s) => s.as_bytes()[n] as char,
}
}
pub fn nth_ascii(&self, n: usize) -> char {
self.nth_bytechar(n)
}
pub fn as_bytes(&self) -> &[u8] {
match &self.inner {
fixed(f) => f.as_bytes(),
owned(s) => s.as_bytes(),
} }
pub fn set(&mut self, i: usize, c: char) -> bool {
match &mut self.inner {
fixed(s) => s.set(i, c),
owned(s) => unsafe {
let ref mut cbuf = [0u8; 4];
c.encode_utf8(cbuf);
let clen = c.len_utf8();
if let Some((bi, rc)) = s.char_indices().nth(i) {
if clen == rc.len_utf8() {
s.as_bytes_mut()[bi..bi + clen].copy_from_slice(&cbuf[..clen]);
return true;
}
}
return false;
},
} }
pub fn is_fixed(&self) -> bool {
match &self.inner {
fixed(_) => true,
owned(_) => false,
}
}
pub fn is_owned(&self) -> bool {
!self.is_fixed()
}
pub fn if_fixed<F>(&mut self, f: F)
where
F: FnOnce(&mut tstr<N>),
{
if let fixed(s) = &mut self.inner {
f(s);
}
}
pub fn if_owned<F>(&mut self, f: F)
where
F: FnOnce(&mut str),
{
if let owned(s) = &mut self.inner {
f(s);
}
}
pub fn map_or<F, G, U>(&self, f: F, g: G) -> U
where
F: FnOnce(&tstr<N>) -> U,
G: FnOnce(&str) -> U,
{
match &self.inner {
fixed(s) => f(s),
owned(s) => g(&s[..]),
} }
pub fn map_or_mut<F, G, U>(&mut self, f: &mut F, g: &mut G) -> U
where
F: FnMut(&mut tstr<N>) -> U,
G: FnMut(&mut str) -> U,
{
match &mut self.inner {
fixed(s) => f(s),
owned(s) => g(&mut s[..]),
} }
pub fn push_str(&mut self, s: &str) -> bool {
match &mut self.inner {
fixed(fs) if fs.len() + s.len() < N => {
fs.push(s);
true
}
fixed(fs) => {
let fss = fs.to_string() + s;
self.inner = owned(fss);
false
}
owned(ns) => {
ns.push_str(s);
false
}
} }
pub fn push(&mut self, c: char) -> bool {
let clen = c.len_utf8();
match &mut self.inner {
owned(s) => {
s.push(c);
false
}
fixed(s) if s.len() + clen >= N => {
let mut fss = s.to_string();
fss.push(c);
self.inner = owned(fss);
false
}
fixed(s) => {
let mut buf = [0u8; 4];
let bstr = c.encode_utf8(&mut buf);
s.push(bstr);
true
}
} }
pub fn pop(&mut self) -> Option<char> {
if self.len() == 0 {
return None;
}
match &mut self.inner {
fixed(s) => s.pop_char(),
owned(s) if s.len() > N => s.pop(),
owned(s) => {
let lastchar = s.pop();
self.inner = fixed(tstr::from(&s));
lastchar
}
} }
pub fn pop_char(&mut self) -> Option<char> {
self.pop()
}
pub fn truncate(&mut self, n: usize) -> bool {
match &mut self.inner {
fixed(fs) if n < fs.len() => {
fs.truncate_bytes(n);
true
}
fixed(_) => true,
owned(s) if n < N => {
assert!(s.is_char_boundary(n));
self.inner = fixed(tstr::<N>::from(&s[..n]));
true
}
owned(s) => {
if n < s.len() {
s.truncate(n);
}
false
}
} }
pub fn clear(&mut self) {
match &mut self.inner {
fixed(s) => {
s.clear();
}
owned(s) => {
self.inner = fixed(tstr::default());
}
}
}
pub fn substr(&self, start: usize, end: usize) -> Flexstr<N> {
match &self.inner {
fixed(s) => Flexstr {
inner: fixed(s.substr(start, end)),
},
owned(s) => Self::from(&s[start..end]),
}
}
pub fn split_off(&mut self) -> String {
match &mut self.inner {
fixed(s) => String::default(),
owned(s) => {
let answer = String::from(&s[N - 1..]);
self.inner = fixed(tstr::<N>::from(&s[..N - 1]));
answer
}
} }
pub fn make_ascii_lowercase(&mut self) {
match &mut self.inner {
fixed(s) => {
s.make_ascii_lowercase();
}
owned(s) => {
s.as_mut_str().make_ascii_lowercase();
}
} }
pub fn make_ascii_uppercase(&mut self) {
match &mut self.inner {
fixed(s) => {
s.make_ascii_uppercase();
}
owned(s) => {
s.as_mut_str().make_ascii_uppercase();
}
} }
}
impl<const N: usize> Default for Flexstr<N> {
fn default() -> Self {
Flexstr {
inner: fixed(tstr::<N>::default()),
}
}
}
impl<const N: usize> core::ops::Deref for Flexstr<N> {
type Target = str;
fn deref(&self) -> &Self::Target {
self.to_str()
}
}
impl<T: AsRef<str> + ?Sized, const N: usize> core::convert::From<&T> for Flexstr<N> {
fn from(s: &T) -> Self {
Self::make(s.as_ref())
}
}
impl<T: AsMut<str> + ?Sized, const N: usize> core::convert::From<&mut T> for Flexstr<N> {
fn from(s: &mut T) -> Self {
Self::make(s.as_mut())
}
}
impl<const N: usize> core::cmp::PartialOrd for Flexstr<N> {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}
impl<const N: usize> core::cmp::Ord for Flexstr<N> {
fn cmp(&self, other: &Self) -> Ordering {
self.to_str().cmp(other.to_str())
}
}
impl<const N: usize> core::convert::AsRef<str> for Flexstr<N> {
fn as_ref(&self) -> &str {
self.to_str()
}
}
impl<const N: usize> core::convert::AsMut<str> for Flexstr<N> {
fn as_mut(&mut self) -> &mut str {
match &mut self.inner {
fixed(f) => f.as_mut(),
owned(s) => s.as_mut(),
} }
}
impl<const N: usize> PartialEq<&str> for Flexstr<N> {
fn eq(&self, other: &&str) -> bool {
&self.to_str() == other } }
impl<const N: usize> PartialEq<&str> for &Flexstr<N> {
fn eq(&self, other: &&str) -> bool {
&self.to_str() == other
} }
impl<'t, const N: usize> PartialEq<Flexstr<N>> for &'t str {
fn eq(&self, other: &Flexstr<N>) -> bool {
&other.to_str() == self
}
}
impl<'t, const N: usize> PartialEq<&Flexstr<N>> for &'t str {
fn eq(&self, other: &&Flexstr<N>) -> bool {
&other.to_str() == self
}
}
impl<const N: usize> core::fmt::Debug for Flexstr<N> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.pad(&self.to_str())
}
}
impl<const N: usize> core::fmt::Display for Flexstr<N> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "{}", self.to_str())
}
}
impl<const N: usize> core::fmt::Write for Flexstr<N> {
fn write_str(&mut self, s: &str) -> core::fmt::Result {
self.push_str(s);
Ok(())
} }
impl<const N: usize> core::convert::From<String> for Flexstr<N> {
fn from(s: String) -> Self {
if s.len() >= N {
Flexstr { inner: owned(s) }
} else {
Flexstr {
inner: fixed(tstr::<N>::from(&s[..])),
}
}
}
}
impl<const M: usize> Flexstr<M> {
pub fn resize<const N: usize>(&self) -> Flexstr<N> {
Flexstr::from(self)
}
}
impl<const N: usize> Add<&str> for &Flexstr<N> {
type Output = Flexstr<N>;
fn add(self, other: &str) -> Self::Output {
match (&self.inner, other) {
(owned(a), b) => {
let mut a2 = a.clone();
a2.push_str(other);
Flexstr { inner: owned(a2) }
}
(fixed(a), b) if a.len() + b.len() >= N => {
let mut a2 = a.to_string();
a2.push_str(b);
Flexstr { inner: owned(a2) }
}
(fixed(a), b) => {
let mut a2 = *a; a2.push(b);
Flexstr { inner: fixed(a2) }
}
} }
}
impl<const N: usize> Add<&Flexstr<N>> for &str {
type Output = Flexstr<N>;
fn add(self, other: &Flexstr<N>) -> Flexstr<N> {
let mut a2 = Flexstr::from(self);
a2.push_str(other);
a2
}
}
impl<const N: usize> Add<Flexstr<N>> for &str {
type Output = Flexstr<N>;
fn add(self, other: Flexstr<N>) -> Flexstr<N> {
let mut a2 = Flexstr::from(self);
a2.push_str(&other);
a2
}
}
pub type flexstr8 = Flexstr<8>;
pub type flexstr16 = Flexstr<16>;
pub type flexstr32 = Flexstr<32>;
pub type flexstr64 = Flexstr<64>;
pub type flexstr128 = Flexstr<128>;
pub type flexstr256 = Flexstr<256>;