use crate ::find::find;
use std::fmt::Debug;
use std::ops::{self , RangeFrom, RangeFull, RangeTo};
#[ derive(Copy, Clone)]
pub struct Range<'a> {
pub doc: &'a [char],
pub offset: usize,
pub len: usize,
}
impl <'a> Range<' a> {
pub fn empty() -> Self {
Range {
doc: &[],
offset: 0 ,
len: 0 ,
}
}
pub fn new(doc: &'a [char], bounds: impl RangeBounds) -> Self {
let (offset, len) = bounds.index(doc.len());
Range { doc, offset, len }
}
pub fn is_empty(&self ) -> bool {
self .len == 0
}
pub fn len_bytes(&self ) -> usize {
self .chars().map(char::len_utf8).sum()
}
pub fn substring(&self , bounds: impl RangeBounds) -> Self {
let (offset, len) = bounds.index(self .len);
Range {
doc: self .doc,
offset: self .offset + offset,
len,
}
}
pub fn get(&self , bounds: impl RangeBounds) -> Option<Self > {
let (offset, len) = bounds.try_index(self .len)?;
Some(Range {
doc: self .doc,
offset: self .offset + offset,
len,
})
}
pub fn split_at(&self , mid: usize) -> (Self , Self ) {
(self .substring(..mid), self .substring(mid..))
}
pub fn chars(
&self ,
) -> impl Iterator<Item = char> + DoubleEndedIterator + ExactSizeIterator + 'a {
slice(*self ).iter().copied()
}
pub fn starts_with(&self , prefix: impl AsRef<[char]>) -> bool {
slice(*self ).starts_with(prefix.as_ref())
}
pub fn ends_with(&self , suffix: impl AsRef<[char]>) -> bool {
slice(*self ).ends_with(suffix.as_ref())
}
pub fn find(&self , needle: impl AsRef<[char]>) -> Option<usize> {
find(slice(*self ), needle.as_ref())
}
}
pub fn slice(range: Range) -> &[char] {
&range.doc[range.offset..range.offset + range.len]
}
impl AsRef<[char]> for Range<'_> {
fn as_ref(&self ) -> &[char] {
slice(*self )
}
}
pub trait RangeBounds: Sized + Clone + Debug {
// Returns (offset, len).
fn try_index(self , len: usize) -> Option<(usize, usize)>;
fn index(self , len: usize) -> (usize, usize) {
match self .clone().try_index(len) {
Some(range) => range,
None => panic!("index out of range, index={self:?}, len={len}" ),
}
}
}
impl RangeBounds for ops::Range<usize> {
fn try_index(self , len: usize) -> Option<(usize, usize)> {
if self .start <= self .end && self .end <= len {
Some((self .start, self .end - self .start))
} else {
None
}
}
}
impl RangeBounds for RangeFrom<usize> {
fn try_index(self , len: usize) -> Option<(usize, usize)> {
if self .start <= len {
Some((self .start, len - self .start))
} else {
None
}
}
}
impl RangeBounds for RangeTo<usize> {
fn try_index(self , len: usize) -> Option<(usize, usize)> {
if self .end <= len {
Some((0 , self .end))
} else {
None
}
}
}
impl RangeBounds for RangeFull {
fn try_index(self , len: usize) -> Option<(usize, usize)> {
Some((0 , len))
}
}
Messung V0.5 in Prozent C=98 H=92 G=94
¤ Dauer der Verarbeitung: 0.3 Sekunden
¤
*© Formatika GbR, Deutschland