use std::{convert::Infallible, ops::Add, str::pattern::Pattern};
use crate::pq_rc::PqRc;
use super::{CharList, CharListTail};
pub type NoTail = ();
pub type FiniteCharList = CharList<NoTail>;
impl CharListTail for NoTail {
type Err = Infallible;
fn next_char_list(&self) -> Result<Option<&CharList<Self>>, Infallible> {
Ok(None)
}
fn len(&self) -> Result<usize, Self::Err> {
Ok(0)
}
}
impl CharList<NoTail> {
pub fn as_str(&self) -> &str {
self.segment_as_str()
}
pub fn as_bytes(&self) -> &[u8] {
self.segment_as_bytes()
}
pub fn split_after_prefix<'a>(&'a self, prefix: impl Pattern<'a>) -> (&'a str, Self) {
let seg_remainder = self.as_str().trim_start_matches(prefix);
self.split_at(self.len().expect("infallible") - seg_remainder.len())
}
pub fn split_after_nonempty_prefix<'a>(
&'a self,
prefix: impl Pattern<'a>,
) -> Option<(&'a str, Self)> {
use std::ops::Not;
let (prefix, suffix) = self.split_after_prefix(prefix);
prefix.is_empty().not().then_some((prefix, suffix))
}
#[track_caller]
pub fn split_at(&self, split_index: usize) -> (&str, Self) {
if split_index > self.len().expect("infallible") {
panic!("given range begins beyond end of the `CharList`");
}
if !self.as_str().is_char_boundary(split_index) {
panic!("given range does not begin on a valid char boundary");
}
let prefix = &self.as_str()[..split_index];
let suffix = Self {
data: PqRc::clone_with_priority(
&self.data,
self.len().expect("infallible") - split_index,
),
};
(prefix, suffix)
}
}
impl Add<CharList<NoTail>> for CharList<NoTail> {
type Output = CharList<NoTail>;
fn add(self, rhs: CharList<()>) -> Self::Output {
rhs.cons_str(self.as_str())
}
}
impl PartialEq for FiniteCharList {
fn eq(&self, other: &Self) -> bool {
self.as_str() == other.as_str()
}
}
impl Eq for FiniteCharList {}