#![allow(unused)]
use std::{mem, str};
#[repr(transparent)]
pub struct StrSuffix([u8]);
impl StrSuffix {
pub fn new(s: &str) -> &Self {
unsafe { mem::transmute(s.as_bytes()) }
}
pub fn len(&self) -> usize {
self.0.len()
}
pub fn is_empty(&self) -> bool {
self.0.is_empty()
}
pub fn first(&self) -> Option<u8> {
self.0.first().cloned()
}
pub fn split_first(&self) -> Option<(u8, &Self)> {
if self.is_empty() {
None
} else {
Some((self.0[0], self.suffix(1)))
}
}
pub fn try_as_str(&self) -> Option<&str> {
self.get(0)
}
fn get(&self, index: usize) -> Option<&str> {
if self.is_char_boundary(index) {
Some(unsafe { str::from_utf8_unchecked(&self.0) })
} else {
None
}
}
#[inline(always)]
fn is_char_boundary_byte(b: u8) -> bool {
(b as i8) >= -0x40
}
fn is_char_boundary(&self, index: usize) -> bool {
if index == 0 || index == self.len() {
return true;
}
match self.as_bytes().get(index) {
None => false,
Some(&b) => Self::is_char_boundary_byte(b),
}
}
fn bytes_prefix(&self) -> &[u8] {
for i in 0..(self.len().min(3)) {
if Self::is_char_boundary_byte(self.0[i]) {
return &self.0[..i];
}
}
&self.0[..0]
}
pub fn restore_char(&self, prefix: &[u8]) -> char {
assert!(prefix.len() <= 4);
let mut buf = [0; 4];
buf[..prefix.len()].copy_from_slice(prefix);
let suffix = self.bytes_prefix();
buf[prefix.len()..(prefix.len() + suffix.len())].copy_from_slice(suffix);
str::from_utf8(&buf)
.expect("UTF-8 string")
.chars()
.next()
.expect("char")
}
fn suffix(&self, index: usize) -> &Self {
unsafe { mem::transmute(&self.0[index..]) }
}
pub fn as_bytes(&self) -> &[u8] {
&self.0
}
pub fn iter(&self) -> Iter {
Iter(self)
}
}
pub struct Iter<'a>(&'a StrSuffix);
impl<'a> Iterator for Iter<'a> {
type Item = u8;
fn next(&mut self) -> Option<u8> {
if let Some((b, rest)) = self.0.split_first() {
self.0 = rest;
Some(b)
} else {
None
}
}
}
impl<'a> Iter<'a> {
pub fn as_str_suffix(&self) -> &'a StrSuffix {
self.0
}
}