pub mod contains_str;
pub mod find_str;
pub mod replace_str;
pub mod extend_string;
pub mod remove_matches;
use core::{
ops::{ Index, Range, RangeFrom, RangeTo, RangeFull, RangeInclusive, RangeToInclusive, Deref },
slice,
convert::From,
str,
hint
};
#[derive(Debug)]
pub struct Str<'a> {
inner: &'a str
}
impl<'a> Str<'a> {
pub fn len(&self) -> usize {
self.inner.len()
}
pub fn inner(&self) -> &'a str {
self.inner
}
pub fn inner_slice(&self, index: Range<usize>) -> &'a str {
unsafe {
let start = self.inner.as_ptr().add(index.start);
let len = index.end - index.start;
str::from_utf8_unchecked(
slice::from_raw_parts(start, len)
)
}
}
pub fn inner_slice_from(&self, index: RangeFrom<usize>) -> &'a str {
unsafe {
let start = self.inner.as_ptr().add(index.start);
let len = self.inner.len() - index.start;
str::from_utf8_unchecked(
slice::from_raw_parts(start, len)
)
}
}
pub fn inner_slice_to(&self, index: RangeTo<usize>) -> &'a str {
unsafe {
let start = self.inner.as_ptr();
let len = index.end;
str::from_utf8_unchecked(
slice::from_raw_parts(start, len)
)
}
}
pub fn find(&self, pat: &str) -> usize {
for i in 0..self.len() {
if self[i..i + pat.len()] == *pat {
return i
}
}
unsafe { hint::unreachable_unchecked() }
}
pub fn find_checked(&self, pat: &str) -> Option<usize> {
for i in 0..self.len() - (pat.len() - 1) {
if self[i..i + pat.len()] == *pat {
return Some(i)
}
}
None
}
pub fn find_and_then<F>(&self, pat: &str, mut f: F) where F: FnMut(usize) {
for i in 0..self.len() - (pat.len() - 1) {
if self[i..i + pat.len()] == *pat {
return f(i)
}
}
}
pub fn find_end(&self, pat: &str) -> usize {
for i in 0..self.len() {
if self[i..i + pat.len()] == *pat {
return i + pat.len() - 1
}
}
unsafe { hint::unreachable_unchecked() }
}
pub fn find_end_checked(&self, pat: &str) -> Option<usize> {
for i in 0..self.len() - (pat.len() - 1) {
if self[i..i + pat.len()] == *pat {
return Some(i + pat.len() - 1)
}
}
None
}
}
impl<'a> From<&'a str> for Str<'a> {
fn from(slice: &'a str) -> Self {
Self { inner: slice }
}
}
impl<'a> From<&'a [u8]> for Str<'a> {
fn from(slice: &'a [u8]) -> Self {
Self {
inner: unsafe {
str::from_utf8_unchecked(slice)
}
}
}
}
impl<'a> PartialEq<str> for Str<'a> {
fn eq(&self, other: &str) -> bool {
self.inner == other
}
}
impl<'a> Deref for Str<'a> {
type Target = str;
fn deref(&self) -> &Self::Target {
&self.inner
}
}
impl<'a> Index<usize> for Str<'a>
{
type Output = u8;
fn index(&self, index: usize) -> &Self::Output {
unsafe {
let ptr = self.inner.as_ptr().add(index);
&*ptr
}
}
}
impl<'a> Index<Range<usize>> for Str<'a>
{
type Output = str;
fn index(&self, index: Range<usize>) -> &Self::Output {
unsafe {
let start = self.inner.as_ptr().add(index.start);
let len = index.end - index.start;
str::from_utf8_unchecked(
slice::from_raw_parts(start, len)
)
}
}
}
impl<'a> Index<RangeInclusive<usize>> for Str<'a>
{
type Output = str;
fn index(&self, index: RangeInclusive<usize>) -> &Self::Output {
unsafe {
let (index_start, index_end) = index.into_inner();
let start = self.inner.as_ptr().add(index_start);
let len = index_end + 1 - index_start;
str::from_utf8_unchecked(
slice::from_raw_parts(start, len)
)
}
}
}
impl<'a> Index<RangeFrom<usize>> for Str<'a>
{
type Output = str;
fn index(&self, index: RangeFrom<usize>) -> &Self::Output {
unsafe {
let start = self.inner.as_ptr().add(index.start);
let len = self.inner.len() - index.start;
str::from_utf8_unchecked(
slice::from_raw_parts(start, len)
)
}
}
}
impl<'a> Index<RangeTo<usize>> for Str<'a>
{
type Output = str;
fn index(&self, index: RangeTo<usize>) -> &Self::Output {
unsafe {
let start = self.inner.as_ptr();
let len = index.end;
str::from_utf8_unchecked(
slice::from_raw_parts(start, len)
)
}
}
}
impl<'a> Index<RangeToInclusive<usize>> for Str<'a>
{
type Output = str;
fn index(&self, index: RangeToInclusive<usize>) -> &Self::Output {
unsafe {
let start = self.inner.as_ptr();
let len = index.end + 1;
str::from_utf8_unchecked(
slice::from_raw_parts(start, len)
)
}
}
}
impl<'a> Index<RangeFull> for Str<'a>
{
type Output = str;
fn index(&self, _index: RangeFull) -> &Self::Output {
unsafe {
let start = self.inner.as_ptr();
let len = self.inner.len();
str::from_utf8_unchecked(
slice::from_raw_parts(start, len)
)
}
}
}