use std::cmp;
use std::convert::{TryFrom, TryInto};
use std::fmt;
use std::hash::{Hash, Hasher};
use usize_cast::IntoUsize;
use super::String32;
use super::TryFromStrError;
#[derive(Debug, Eq)]
#[repr(transparent)]
pub struct Str32(str);
impl Str32 {
#[must_use]
pub const fn as_str(&self) -> &str {
&self.0
}
#[must_use]
pub fn as_mut_str(&mut self) -> &mut str {
&mut self.0
}
#[must_use]
pub const fn as_bytes(&self) -> &[u8] {
self.0.as_bytes()
}
#[must_use]
pub unsafe fn as_bytes_mut(&mut self) -> &mut [u8] {
self.0.as_bytes_mut()
}
#[must_use]
pub fn bytes(&self) -> std::str::Bytes<'_> {
self.0.bytes()
}
#[must_use]
pub const fn as_ptr(&self) -> *const u8 {
self.0.as_ptr()
}
#[must_use]
pub fn as_mut_ptr(&mut self) -> *mut u8 {
self.0.as_mut_ptr()
}
#[must_use]
pub fn from_mut_str(s: &mut str) -> &mut Self {
s.try_into().unwrap()
}
#[must_use]
pub fn len(&self) -> u32 {
self.0.len().try_into().unwrap()
}
#[must_use]
pub fn is_empty(&self) -> bool {
self.len() == 0
}
#[must_use]
pub fn chars(&self) -> std::str::Chars {
self.0.chars()
}
#[must_use]
pub fn char_indices(&self) -> impl DoubleEndedIterator<Item = (u32, char)> + '_ {
self.0
.char_indices()
.map(|(i, c)| (i.try_into().unwrap(), c))
}
#[must_use]
pub fn lines(&self) -> impl DoubleEndedIterator<Item = &Self> + '_ {
self.0.lines().map(|line| line.try_into().unwrap())
}
#[must_use]
pub fn split_ascii_whitespace(&self) -> impl DoubleEndedIterator<Item = &Self> + '_ {
self.0
.split_ascii_whitespace()
.map(|line| line.try_into().unwrap())
}
#[must_use]
pub fn split_at(&self, mid: u32) -> (&Self, &Self) {
let (s1, s2) = self.0.split_at(mid.into_usize());
(s1.try_into().unwrap(), s2.try_into().unwrap())
}
#[must_use]
pub fn split_at_mut(&mut self, mid: u32) -> (&mut Self, &mut Self) {
let (s1, s2) = self.0.split_at_mut(mid.into_usize());
(s1.try_into().unwrap(), s2.try_into().unwrap())
}
#[must_use]
pub fn split_whitespace(&self) -> impl DoubleEndedIterator<Item = &Self> + '_ {
self.0
.split_whitespace()
.map(|line| line.try_into().unwrap())
}
#[must_use]
pub fn eq_ignore_ascii_case(&self, other: &Self) -> bool {
self.0.eq_ignore_ascii_case(&other.0)
}
#[must_use]
pub fn escape_debug(&self) -> std::str::EscapeDebug<'_> {
self.0.escape_debug()
}
#[must_use]
pub fn escape_default(&self) -> std::str::EscapeDefault<'_> {
self.0.escape_default()
}
#[must_use]
pub fn escape_unicode(&self) -> std::str::EscapeUnicode<'_> {
self.0.escape_unicode()
}
#[must_use]
pub fn is_char_boundary(&self, index: u32) -> bool {
self.0.is_char_boundary(index.into_usize())
}
pub fn make_ascii_lowercase(&mut self) {
self.0.make_ascii_lowercase()
}
pub fn make_ascii_uppercase(&mut self) {
self.0.make_ascii_uppercase()
}
pub fn parse<F: std::str::FromStr>(&self) -> Result<F, F::Err> {
self.0.parse()
}
#[must_use]
pub fn repeat(&self, n: u32) -> String32 {
self.0.repeat(n.into_usize()).try_into().unwrap()
}
#[must_use]
pub fn to_lowercase(&self) -> String32 {
self.0.to_lowercase().try_into().unwrap()
}
#[must_use]
pub fn to_uppercase(&self) -> String32 {
self.0.to_uppercase().try_into().unwrap()
}
#[must_use]
pub fn to_ascii_lowercase(&self) -> String32 {
self.0.to_ascii_lowercase().try_into().unwrap()
}
#[must_use]
pub fn to_ascii_uppercase(&self) -> String32 {
self.0.to_ascii_uppercase().try_into().unwrap()
}
#[must_use]
pub fn trim(&self) -> &Self {
self.0.trim().try_into().unwrap()
}
#[must_use]
pub fn trim_start(&self) -> &Self {
self.0.trim_start().try_into().unwrap()
}
#[must_use]
pub fn trim_end(&self) -> &Self {
self.0.trim_end().try_into().unwrap()
}
#[must_use]
pub fn into_boxed_str(self: Box<Self>) -> Box<str> {
self.into()
}
#[must_use]
pub fn into_boxed_bytes(self: Box<Self>) -> Box<[u8]> {
self.into()
}
#[must_use]
pub fn into_string(self: Box<Self>) -> String {
self.into()
}
#[must_use]
pub fn into_string32(self: Box<Self>) -> String32 {
self.into()
}
}
impl AsRef<[u8]> for Str32 {
fn as_ref(&self) -> &[u8] {
self.as_bytes()
}
}
impl AsRef<str> for Str32 {
fn as_ref(&self) -> &str {
&self.0
}
}
impl fmt::Display for Str32 {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.0.fmt(f)
}
}
impl<'a> From<&'a Str32> for &'a str {
fn from(s: &'a Str32) -> Self {
&s.0
}
}
impl From<Box<Str32>> for String {
fn from(b: Box<Str32>) -> Self {
b.into()
}
}
impl From<Box<Str32>> for Box<str> {
fn from(b: Box<Str32>) -> Self {
b.into()
}
}
impl From<Box<Str32>> for Box<[u8]> {
fn from(b: Box<Str32>) -> Self {
b.into()
}
}
#[allow(clippy::fallible_impl_from)]
impl From<Box<Str32>> for String32 {
fn from(b: Box<Str32>) -> Self {
String::from(b).try_into().unwrap()
}
}
impl Hash for Str32 {
fn hash<H: Hasher>(&self, state: &mut H) {
self.0.hash(state);
}
}
impl Ord for Str32 {
fn cmp(&self, rhs: &Self) -> cmp::Ordering {
self.0.cmp(&rhs.0)
}
}
impl PartialEq for Str32 {
fn eq(&self, rhs: &Self) -> bool {
self.0 == rhs.0
}
}
impl PartialOrd for Str32 {
fn partial_cmp(&self, rhs: &Self) -> Option<cmp::Ordering> {
self.0.partial_cmp(&rhs.0)
}
}
impl ToOwned for Str32 {
type Owned = String32;
fn to_owned(&self) -> String32 {
self.0.to_owned().try_into().unwrap()
}
}
impl<'a> TryFrom<&'a str> for &'a Str32 {
type Error = TryFromStrError;
fn try_from(s: &str) -> Result<Self, Self::Error> {
u32::try_from(s.len())
.map(|_| {
let ptr = s as *const str as *const Str32;
unsafe {
&*ptr
}
})
.map_err(|_| TryFromStrError(()))
}
}
impl<'a> TryFrom<&'a mut str> for &'a mut Str32 {
type Error = TryFromStrError;
fn try_from(s: &mut str) -> Result<Self, Self::Error> {
u32::try_from(s.len())
.map(|_| {
let ptr = s as *mut str as *mut Str32;
unsafe {
&mut *ptr
}
})
.map_err(|_| TryFromStrError(()))
}
}