pub struct CharList<Tail: CharListTail> { /* private fields */ }
Expand description
An efficient string type with the same API as a linked-list of characters.
§Notable Methods
cons
which immutably prepends a character (cons_str
is also available), andcar_cdr
which immutably splitsself
into its first character and everything except the first character.
§Note: CharList: !Deref<Target=str>
This type specifically does not implement Deref<Target=str>
. It cannot
because it’s too generic, and might have a tail with more text. For a
version that does implement this trait, see [FiniteCharList
].
Implementations§
source§impl CharList<NoTail>
impl CharList<NoTail>
sourcepub fn as_str(&self) -> &str
pub fn as_str(&self) -> &str
Extracts a string slice which references self
’s entire view of the
underlying text.
Same as <CharList as AsRef<str>>::as_ref
.
sourcepub fn as_bytes(&self) -> &[u8] ⓘ
pub fn as_bytes(&self) -> &[u8] ⓘ
Extracts a byte slice which references self
’s entire view of the
underlying text.
Same as <CharList as AsRef<[u8]>>::as_ref
.
sourcepub fn split_after_prefix<'a>(
&'a self,
prefix: impl Pattern<'a>
) -> (&'a str, Self)
pub fn split_after_prefix<'a>( &'a self, prefix: impl Pattern<'a> ) -> (&'a str, Self)
Separates self
into a prefix (described by the Pattern
prefix
) and
a suffix made of the remainder of the string.
The Pattern
prefix
could be:
- a
&str
giving an exact prefix to match, - a
char
giving an exact character prefix to match, - a predicate of type
FnMut(char) -> bool
which returns true for all characters in the prefix.
Notice that this function returns a pair containing two different
string types: a &str
for the found prefix, and a CharList
for the
suffix. The assumption is that the prefix (and the CharList
which
holds onto that section of the string) will be dropped before the suffix
is dropped. This means, if possible, don’t immediately create a new
CharList
from the prefix as this will allocate a copy of the text
referenced by the prefix.
let creepy_book = FiniteCharList::from("necronomicon");
let pair = creepy_book.split_after_prefix("necro");
assert!(pair == ("necro", FiniteCharList::from("nomicon")));
let words = FiniteCharList::from("hello world");
let (hello, rest) = words.split_after_prefix(char::is_alphabetic);
assert!(hello == "hello");
assert!(rest == " world");
let numbers = FiniteCharList::from("1253 39271 4542");
let (first_word, rest) = numbers.split_after_prefix(char::is_alphabetic);
assert!(first_word.is_empty());
assert!(rest == numbers);
sourcepub fn split_after_nonempty_prefix<'a>(
&'a self,
prefix: impl Pattern<'a>
) -> Option<(&'a str, Self)>
pub fn split_after_nonempty_prefix<'a>( &'a self, prefix: impl Pattern<'a> ) -> Option<(&'a str, Self)>
Just like split_after_prefix
except it will never return an empty prefix, instead returning None
in
that case.
sourcepub fn split_at(&self, split_index: usize) -> (&str, Self)
pub fn split_at(&self, split_index: usize) -> (&str, Self)
For the argument idx
, returns the pair (prefix, suffix)
where
prefix
ends just before byte-index idx
, and suffix
begins at
byte-index idx
.
The String
created from format!("{prefix}{suffix}")
will always be
equal to self
.
Guarunteed not to allocate a new underlying FrontString
.
§Panics
A panic will occur if:
start_idx
is greater thanself.len()
, orstart_idx
indexes to an invalidchar
boundary.
§Examples
let rustonomicon = FiniteCharList::from("rustonomicon");
let ptr_before = rustonomicon.backing_string().as_ptr();
let idx = "rusto".len();
let (rusto, nomicon) = rustonomicon.split_at(idx);
assert!(rusto == "rusto" && nomicon == "nomicon");
// The underlying buffer has NOT been reallocated!
let ptr_after = nomicon.backing_string().as_ptr();
assert!(ptr_before == ptr_after);
let word = FiniteCharList::from("word");
let (empty, suffix) = word.split_at(0);
assert!(empty.is_empty());
assert!(suffix == word);
let word = FiniteCharList::from("kitty");
let _ = word.split_at(1000); // Panic!
let pride_bytes: Vec<u8> = [
0xF0, 0x9F, 0x8F, 0xB3, // 1st char: 🏳
// ^^^^ We're gonna try to begin the suffix here 😈
0xEF, 0xB8, 0x8F, // 2nd char: ◌️
0xE2, 0x80, 0x8D, // 3rd char: <Zero Width Joiner>
0xF0, 0x9F, 0x8C, 0x88, // 4th char: 🌈
].to_vec();
let pride = FiniteCharList::from_utf8(pride_bytes).expect("bytes are valid utf8");
assert!(pride == "🏳️🌈");
let _ = pride.split_at(2); // Panic!
source§impl<Tail: CharListTail> CharList<Tail>
impl<Tail: CharListTail> CharList<Tail>
pub fn partial_segments(&self) -> SegmentWalker<'_, Tail> ⓘ
source§impl<Tail: CharListTail> CharList<Tail>
impl<Tail: CharListTail> CharList<Tail>
sourcepub fn new() -> Self
pub fn new() -> Self
Creates an empty CharList
.
§Example
let empty = FiniteCharList::new();
assert!(empty.len().unwrap() == 0);
sourcepub fn with_capacity(capacity: usize) -> Self
pub fn with_capacity(capacity: usize) -> Self
Creates a CharList
whose backing FrontString
begins with the capacity specified.
pub fn from_utf8(vec: Vec<u8>) -> Result<Self, FromUtf8Error>
pub fn from_utf8_lossy(bytes: &[u8]) -> Self
pub fn new_with_tail(tail: Tail) -> Self
sourcepub fn with_capacity_and_tail(capacity: usize, tail: Tail) -> Self
pub fn with_capacity_and_tail(capacity: usize, tail: Tail) -> Self
Creates a CharList
whose backing FrontString
begins with the capacity specified.
sourcepub fn segment_as_str(&self) -> &str
pub fn segment_as_str(&self) -> &str
Returns a string slice of this segment’s portion of the string. Ignores any tail that may be present.
Note: for CharList<()>
(()
is the default type parameter for
CharList
) this is the same as as_str
.
sourcepub fn segment_as_bytes(&self) -> &[u8] ⓘ
pub fn segment_as_bytes(&self) -> &[u8] ⓘ
Returns a byte slice of this segment’s portion of the string. Ignores any tail that may be present.
Note: for CharList<()>
(()
is the default type parameter for
CharList
) this is the same as as_bytes
.
sourcepub fn len(&self) -> Result<usize, Tail::Err>
pub fn len(&self) -> Result<usize, Tail::Err>
Returns the length of self
.
This length is in bytes, not char
s or graphemes. In other words,
it might not be what a human considers the length of the string.
§Examples
Basic usage:
let foo = FiniteCharList::from("foo");
assert!(foo.len() == Ok(3));
let fancy_foo = FiniteCharList::from("ƒoo"); // fancy f!
assert!(fancy_foo.len() == Ok(4));
assert!(fancy_foo.as_str().chars().count() == 3);
sourcepub fn partial_len(&self) -> usize
pub fn partial_len(&self) -> usize
Returns as much of the length of the string as is possible to know right now.
sourcepub fn segment_len(&self) -> usize
pub fn segment_len(&self) -> usize
Returns the length of this segment, ignoring any tail.
§Example
If the underlying buffers looked like this:
[?, ?, ?, 'a', 'b', 'c'] --> [?, ?, 'd', 'e', 'f']
Then a CharList
representing the string “cdef” would have a
segment_len
of one (1). A CharList
for “abcdef” would have
segment_len
three (3).
pub fn is_empty(&self) -> Result<bool, Tail::Err>
pub fn cons_char_list(&self, prefix: &Self) -> Self
sourcepub fn car_cdr(&self) -> Result<Option<(char, Self)>, Tail::Err>
pub fn car_cdr(&self) -> Result<Option<(char, Self)>, Tail::Err>
Returns a pair containing the first character of self
and a
CharList
made up of everything after the first character of self
.
Returns None
if self
is empty.
§Example
let (g, oats) = FiniteCharList::from("goats").car_cdr().unwrap().unwrap();
assert!((g, oats) == ('g', FiniteCharList::from("oats")));
let empty = FiniteCharList::new();
assert!(empty.car_cdr().unwrap().is_none());
sourcepub unsafe fn from_utf8_unchecked(bytes: &[u8]) -> Self
pub unsafe fn from_utf8_unchecked(bytes: &[u8]) -> Self
§Safety
See str::from_utf8_unchecked
for
safety requirements.
sourcepub fn backing_string(&self) -> &FrontString
pub fn backing_string(&self) -> &FrontString
Get an immutable reference to the backing FrontString
.
pub fn from_string_and_tail(s: impl Into<String>, tail: Tail) -> Self
pub fn from_utf8_and_tail(bytes: &[u8], tail: Tail) -> Result<Self, Utf8Error>
pub fn from_utf8_lossy_and_tail(bytes: &[u8], tail: Tail) -> Self
pub fn from_io_readable(readable: &mut impl Read) -> Result<Self>
pub fn prepend_from_bytes_iter( &self, it: impl ExactSizeIterator<Item = u8> ) -> Result<Self, FromUtf8Error>
Trait Implementations§
source§impl<Tail: CharListTail> Clone for CharList<Tail>
impl<Tail: CharListTail> Clone for CharList<Tail>
source§impl<Tail: CharListTail> Debug for CharList<Tail>
impl<Tail: CharListTail> Debug for CharList<Tail>
source§impl<Tail: CharListTail> Default for CharList<Tail>
impl<Tail: CharListTail> Default for CharList<Tail>
source§impl<Tail: CharListTail> Display for CharList<Tail>
impl<Tail: CharListTail> Display for CharList<Tail>
source§impl<Tail: CharListTail> Drop for CharList<Tail>
impl<Tail: CharListTail> Drop for CharList<Tail>
source§impl<Tail: CharListTail> FromIterator<char> for CharList<Tail>
impl<Tail: CharListTail> FromIterator<char> for CharList<Tail>
source§fn from_iter<I: IntoIterator<Item = char>>(iter: I) -> Self
fn from_iter<I: IntoIterator<Item = char>>(iter: I) -> Self
Given an iterator over the &str
"abc"
, the CharList
"abc"
will be created.
source§impl<Tail> Hash for CharList<Tail>where
Tail: CharListTail,
impl<Tail> Hash for CharList<Tail>where
Tail: CharListTail,
source§impl<S, Tail> PartialOrd<S> for CharList<Tail>
impl<S, Tail> PartialOrd<S> for CharList<Tail>
In general, a CharList
does not have reflexive equality.
§Example
In Prolog, a partial string looks like this:
-? Partial = [a, b, c | Tail].
If later Tail
is instantiated, then we have two times at which Partial
is not symbolically equal to itself i.e.
?- [a, b, c | Tail] \== [a, b, c, d, e, f].
1.0.0 · source§fn le(&self, other: &Rhs) -> bool
fn le(&self, other: &Rhs) -> bool
self
and other
) and is used by the <=
operator. Read more