#![warn(missing_docs)]
#![doc = include_str!("../docs.md")]
mod parser;
pub use parser::*;
pub mod combinators;
#[cfg(feature = "builtins")]
pub mod builtins;
pub use nevermore::FromNever;
#[cfg(test)]
mod tests;
use std::{cell::Cell, fmt::{Debug, Display}};
pub struct ParserString {
full: Box<str>,
ptr: Cell<usize>,
}
fn update<T: Copy, F: Fn(T) -> T>(cell: &Cell<T>, f: F) {
let a = cell.get();
cell.set(f(a));
}
impl ParserString {
pub fn take(&mut self, n: usize) -> &str {
let offs = self.get().chars()
.take(n).map(char::len_utf8).sum();
let (front, _) = self.get().split_at(offs);
update(&self.ptr, |ptr| ptr + offs);
assert!(self.ptr.get() <= self.full.len());
front
}
pub fn try_take(&mut self, n: usize) -> Option<&str> {
if self.ptr.get() + n > self.full.len() {
return None;
}
let offs = self.get().chars()
.take(n).map(char::len_utf8).sum();
let (front, _) = self.get().split_at(offs);
update(&self.ptr, |ptr| ptr + offs);
Some(front)
}
pub unsafe fn give(&mut self, n: usize) {
*self.ptr.get_mut() -= n;
}
pub unsafe fn set_ptr(&mut self, ptr: usize) {
self.ptr.set(ptr);
}
pub fn get(&self) -> &str {
&self.full[self.ptr.get()..]
}
pub fn len(&self) -> usize {
self.full.len() - self.ptr.get()
}
pub fn start(&self) -> usize {
self.ptr.get()
}
}
impl From<&str> for ParserString {
fn from(value: &str) -> Self {
Self {
full: Box::from(value),
ptr: Cell::new(0),
}
}
}
impl From<String> for ParserString {
fn from(value: String) -> Self {
Self {
full: value.into_boxed_str(),
ptr: Cell::new(0),
}
}
}
impl Debug for ParserString {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{:?}", self.get())
}
}
impl Display for ParserString {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.get())
}
}