#![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)]
use crate::shared_structs::Strunion;
use crate::shared_structs::Strunion::*;
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 core::cmp::{min, Ordering};
use core::ops::Add;
extern crate alloc;
use alloc::rc::Rc;
use alloc::string::String;
use core::cell::RefCell;
#[derive(Eq, Clone)]
pub struct Sharedstr<const N: usize = 32> {
inner: Rc<RefCell<Strunion<N>>>,
}
impl<const N: usize> Sharedstr<N> {
pub fn make(s: &str) -> Self {
if s.len() < N && N <= 256 {
Sharedstr {
inner: Rc::new(RefCell::new(fixed(tstr::<N>::from(s)))),
}
} else {
Sharedstr {
inner: Rc::new(RefCell::new(owned(String::from(s)))),
}
}
}
pub fn from_string(s: String) -> Self {
if s.len() < N && N <= 256 {
Sharedstr {
inner: Rc::new(RefCell::new(fixed(tstr::<N>::from(&s[..])))),
}
} else {
Sharedstr {
inner: Rc::new(RefCell::new(owned(s))),
}
}
}
pub fn from_tstr(s: tstr<N>) -> Self {
Sharedstr {
inner: Rc::new(RefCell::new(fixed(s))),
}
}
pub fn len(&self) -> usize {
match &*self.inner.borrow() {
fixed(s) => s.len(),
owned(s) => s.len(),
} }
pub fn as_str(&self) -> &str {
unsafe {
match self.inner.as_ptr().as_ref().unwrap() {
fixed(s) => s.as_str(),
owned(s) => s.as_str(),
} } }
pub fn as_str_utf8(&self) -> Result<&str,core::str::Utf8Error>
{
unsafe {
match self.inner.as_ptr().as_ref().unwrap() {
fixed(s) => s.as_str_safe(),
owned(s) => Ok(s.as_str()),
} } }
pub fn new() -> Self {
Self::default()
}
pub fn charlen(&self) -> usize {
match &*self.inner.borrow() {
fixed(s) => s.charlen(),
owned(s) => s.chars().count(),
} }
pub fn to_str(&self) -> &str {
self.as_str()
}
pub fn get_str(&self) -> Option<tstr<N>> {
if let fixed(s) = &*self.inner.borrow() {
Some(*s)
} else {
None
}
}
pub fn take_string(&mut self) -> Option<String> {
if let (ss @ owned(_)) = &mut *self.inner.borrow_mut() {
let mut temp = fixed(tstr::new());
core::mem::swap(ss, &mut temp);
if let owned(t) = temp {
Some(t)
} else {
None
}
} else {
None
}
}
pub fn to_string(self) -> String {
match &*self.inner.borrow() {
fixed(s) => s.to_string(),
owned(s) => s.clone(),
} }
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.borrow() {
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] {
self.as_str().as_bytes()
}
pub fn set(&mut self, i: usize, c: char) -> bool {
match &mut *self.inner.borrow_mut() {
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.borrow() {
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.borrow_mut() {
f(s);
}
}
pub fn if_owned<F>(&mut self, f: F)
where
F: FnOnce(&mut str),
{
if let owned(s) = &mut *self.inner.borrow_mut() {
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.borrow() {
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.borrow_mut() {
fixed(s) => f(s),
owned(s) => g(&mut s[..]),
} }
pub fn push_str(&mut self, s: &str) -> bool {
let mut replacer = None;
let answer;
match &mut *self.inner.borrow_mut() {
fixed(fs) if fs.len() + s.len() < N => {
fs.push(s);
answer = true;
}
fixed(fs) => {
let fss = fs.to_string() + s;
replacer = Some(owned(fss));
answer = false;
}
owned(ns) => {
ns.push_str(s);
answer = false;
}
} if let Some(r) = replacer {
self.inner.replace(r);
}
answer
}
pub fn push(&mut self, c: char) -> bool {
let clen = c.len_utf8();
let answer;
let mut replacer = None;
match &mut *self.inner.borrow_mut() {
owned(s) => {
s.push(c);
answer = false;
}
fixed(s) if s.len() + clen >= N => {
let mut fss = s.to_string();
fss.push(c);
replacer = Some(owned(fss));
answer = false;
}
fixed(s) => {
let mut buf = [0u8; 4];
let bstr = c.encode_utf8(&mut buf);
s.push(bstr);
answer = true;
}
} if let Some(r) = replacer {
self.inner.replace(r);
}
answer
}
pub fn push_char(&mut self, c: char) -> bool {
self.push(c)
}
pub fn pop(&mut self) -> Option<char> {
if self.len() == 0 {
return None;
}
let answer;
let mut replacer = None;
match &mut *self.inner.borrow_mut() {
fixed(s) => {
answer = s.pop_char();
}
owned(s) if s.len() > N => {
answer = s.pop();
}
owned(s) => {
answer = s.pop();
replacer = Some(fixed(tstr::from(&s)));
}
} if let Some(r) = replacer {
self.inner.replace(r);
}
answer
}
pub fn pop_char(&mut self) -> Option<char> {
self.pop()
}
pub fn truncate(&mut self, n: usize) -> bool {
let mut replacer = None;
let answer;
match &mut *self.inner.borrow_mut() {
fixed(fs) if n < fs.len() => {
fs.truncate_bytes(n);
answer = true;
}
fixed(_) => {
answer = true;
}
owned(s) if n < N => {
assert!(s.is_char_boundary(n));
replacer = Some(fixed(tstr::<N>::from(&s[..n])));
answer = true;
}
owned(s) => {
if n < s.len() {
s.truncate(n);
}
answer = false;
}
} if let Some(r) = replacer {
self.inner.replace(r);
}
answer
}
pub fn clear(&mut self) {
let mut replacer = None;
match &mut *self.inner.borrow_mut() {
fixed(s) => {
s.clear();
}
owned(s) => {
replacer = Some(fixed(tstr::default()));
}
}
if let Some(r) = replacer {
self.inner.replace(r);
}
}
pub fn substr(&self, start: usize, end: usize) -> Sharedstr<N> {
match &*self.inner.borrow() {
fixed(s) => Sharedstr {
inner: Rc::new(RefCell::new(fixed(s.substr(start, end)))),
},
owned(s) => Self::from(&s[start..end]),
}
}
pub fn split_off(&mut self) -> String {
let answer;
let mut replacer = None;
match &mut *self.inner.borrow_mut() {
fixed(s) => {
answer = String::default();
}
owned(s) => {
answer = String::from(&s[N - 1..]);
replacer = Some(fixed(tstr::<N>::from(&s[..N - 1])));
}
} if let Some(r) = replacer {
self.inner.replace(r);
}
answer
}
pub fn equals<T: AsRef<str>>(&self, other: &T) -> bool {
self == other.as_ref()
}
pub fn ptr_eq(&self, other: &Self) -> bool {
Rc::ptr_eq(&self.inner, &other.inner)
}
pub fn deep_clone(&self) -> Self {
Sharedstr::from(self.as_str())
}
pub fn ptr_count(&self) -> usize {
Rc::strong_count(&self.inner)
}
pub fn make_ascii_lowercase(&mut self) {
match &mut *self.inner.borrow_mut() {
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.borrow_mut() {
fixed(s) => {
s.make_ascii_uppercase();
}
owned(s) => {
s.as_mut_str().make_ascii_uppercase();
}
} }
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();
let sbytes = self.as_bytes();
for i in 0..self.len() {
let mut c = sbytes[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> Default for Sharedstr<N> {
fn default() -> Self {
Sharedstr {
inner: Rc::new(RefCell::new(fixed(tstr::<N>::default()))),
}
}
}
#[cfg(feature = "flex-str")]
use crate::Flexstr;
#[cfg(feature = "flex-str")]
impl<const N: usize> Sharedstr<N> {
pub fn to_flexstr(self) -> Result<Flexstr<N>, Sharedstr<N>> {
extern crate std;
use crate::shared_structs::Strunion::*;
use std::rc::Rc;
match Rc::try_unwrap(self.inner) {
Ok(x) => {
match x.into_inner() {
fixed(s) => Ok(Flexstr::from_tstr(s)),
owned(s) => Ok(Flexstr::from_string(s)),
} }
Err(r) => Err(Sharedstr { inner: r }),
} } }
impl<const N: usize> core::ops::Deref for Sharedstr<N> {
type Target = str;
fn deref(&self) -> &Self::Target {
self.as_str()
}
}
impl<T: AsRef<str> + ?Sized, const N: usize> core::convert::From<&T> for Sharedstr<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 Sharedstr<N> {
fn from(s: &mut T) -> Self {
Self::make(s.as_mut())
}
}
impl<const N: usize> core::cmp::PartialOrd for Sharedstr<N> {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}
impl<const N: usize> core::cmp::Ord for Sharedstr<N> {
fn cmp(&self, other: &Self) -> Ordering {
self.as_str().cmp(other.as_str())
}
}
impl<const N: usize> core::convert::AsRef<str> for Sharedstr<N> {
fn as_ref(&self) -> &str {
self.as_str()
}
}
impl<const N: usize> core::convert::AsMut<str> for Sharedstr<N> {
fn as_mut(&mut self) -> &mut str {
unsafe {
match self.inner.as_ptr().as_mut().unwrap() {
fixed(f) => f.as_mut(),
owned(s) => s.as_mut(),
} } } }
impl<const N: usize> PartialEq<&str> for Sharedstr<N> {
fn eq(&self, other: &&str) -> bool {
&self.to_str() == other } }
impl<const N: usize> PartialEq<&str> for &Sharedstr<N> {
fn eq(&self, other: &&str) -> bool {
&self.to_str() == other
} }
impl<'t, const N: usize> PartialEq<Sharedstr<N>> for &'t str {
fn eq(&self, other: &Sharedstr<N>) -> bool {
&other.to_str() == self
}
}
impl<'t, const N: usize> PartialEq<&Sharedstr<N>> for &'t str {
fn eq(&self, other: &&Sharedstr<N>) -> bool {
&other.to_str() == self
}
}
impl<const N: usize> core::fmt::Debug for Sharedstr<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 Sharedstr<N> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.pad(self.to_str())
}
}
impl<const N: usize> core::fmt::Write for Sharedstr<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 Sharedstr<N> {
fn from(s: String) -> Self {
if s.len() >= N {
Sharedstr {
inner: Rc::new(RefCell::new(owned(s))),
}
} else {
Sharedstr {
inner: Rc::new(RefCell::new(fixed(tstr::<N>::from(&s[..])))),
}
}
}
}
impl<const M: usize> Sharedstr<M> {
pub fn resize<const N: usize>(&self) -> Sharedstr<N> {
Sharedstr::from(self)
}
}
impl<const N: usize, TA: AsRef<str>> Add<TA> for &Sharedstr<N> {
type Output = Sharedstr<N>;
fn add(self, other: TA) -> Self::Output {
match (&*self.inner.borrow(), other.as_ref()) {
(owned(a), b) => {
let mut a2 = a.clone();
a2.push_str(other.as_ref());
Sharedstr {
inner: Rc::new(RefCell::new(owned(a2))),
}
}
(fixed(a), b) if a.len() + b.len() >= N => {
let mut a2 = a.to_string();
a2.push_str(b);
Sharedstr {
inner: Rc::new(RefCell::new(owned(a2))),
}
}
(fixed(a), b) => {
let mut a2 = *a; a2.push(b);
Sharedstr {
inner: Rc::new(RefCell::new(fixed(a2))),
}
}
} }
}
impl<const N: usize> Add<&Sharedstr<N>> for &str {
type Output = Sharedstr<N>;
fn add(self, other: &Sharedstr<N>) -> Sharedstr<N> {
let mut a2 = Sharedstr::from(self);
a2.push_str(other);
a2
}
}
impl<const N: usize> Add<Sharedstr<N>> for &str {
type Output = Sharedstr<N>;
fn add(self, other: Sharedstr<N>) -> Sharedstr<N> {
let mut a2 = Sharedstr::from(self);
a2.push_str(&other);
a2
}
}
impl<const N: usize> core::hash::Hash for Sharedstr<N> {
fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
self.as_ref().hash(state);
}
}
impl<const N: usize> core::cmp::PartialEq for Sharedstr<N> {
fn eq(&self, other: &Self) -> bool {
self.as_ref() == other.as_ref()
}
}
impl<const N: usize> core::str::FromStr for Sharedstr<N> {
type Err = &'static str;
fn from_str(s: &str) -> Result<Self, Self::Err> {
Ok(Sharedstr::from(s))
}
}
pub type sharedstr8 = Sharedstr<8>;
pub type sharedstr16 = Sharedstr<16>;
pub type sharedstr32 = Sharedstr<32>;
pub type sharedstr64 = Sharedstr<64>;
pub type sharedstr128 = Sharedstr<128>;
pub type sharedstr256 = Sharedstr<256>;