use core::option::Option::None;
use std::{fmt, ops::Deref};
use detached_str::{Str, StrSlice};
use nom::{InputLength, InputTake};
#[derive(Copy, Clone, Debug)]
pub(crate) struct Input<'a> {
str: &'a Str,
offset: usize,
}
impl Deref for Input<'_> {
type Target = str;
fn deref(&self) -> &Self::Target {
&self.str[self.offset..]
}
}
impl AsRef<str> for Input<'_> {
fn as_ref(&self) -> &str {
&self.str[self.offset..]
}
}
impl<'a> Input<'a> {
pub fn new(str: &'a Str) -> Self {
Input { str, offset: 0 }
}
#[inline]
pub fn is_empty(self) -> bool {
self.offset == self.str.len()
}
#[inline]
pub fn as_original_str(self) -> &'a str {
self.str
}
#[inline]
pub fn as_str_slice(self) -> StrSlice {
self.str.get(self.offset..)
}
#[inline]
pub fn split_at(self, n: usize) -> (Self, StrSlice) {
let start = self.offset;
let offset = start + n;
let new_input = Input { offset, ..self };
let slice = self.str.get(start..offset);
(new_input, slice)
}
#[inline]
pub fn split_until(self, other: Input<'_>) -> (Self, StrSlice) {
assert!(std::ptr::eq(self.str, other.str));
let diff = self.len() - other.len();
self.split_at(diff)
}
#[inline]
pub fn strip_prefix(self, prefix: &str) -> Option<(Self, StrSlice)> {
if self.starts_with(prefix) {
Some(self.split_at(prefix.len()))
} else {
None
}
}
}
impl nom::InputLength for Input<'_> {
fn input_len(&self) -> usize {
self.len()
}
}
#[derive(Copy, Clone, PartialEq, Eq)]
pub struct Token {
pub kind: TokenKind,
pub range: StrSlice,
pub open_len: u8, pub close_len: u8, }
impl Token {
#[inline]
pub fn new(kind: TokenKind, range: StrSlice) -> Self {
Token {
kind,
range,
open_len: 0,
close_len: 0,
}
}
#[inline]
pub fn new_quoted(kind: TokenKind, range: StrSlice, open_len: u8, close_len: u8) -> Self {
Token {
kind,
range,
open_len,
close_len,
}
}
#[inline]
pub fn text(self, tokens: Tokens<'_>) -> &str {
self.range.to_str(tokens.str)
}
#[inline]
pub fn text_inner<'b>(&self, tokens: Tokens<'b>) -> &'b str {
let start = self.range.start() + self.open_len as usize;
let end = self.range.end() - self.close_len as usize;
&tokens.str[start..end]
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum TokenKind {
Punctuation,
Operator,
Keyword,
StringLiteral,
StringRaw,
StringTemplate,
StringSafe,
Bytes,
IntegerLiteral,
Radix2,
Radix8,
Radix16,
FloatLiteral,
ValueSymbol,
Symbol,
Whitespace,
LineBreak, OperatorInfix,
OperatorPrefix,
OperatorPostfix,
Comment,
ModeTip,
Regex,
Time,
}
impl fmt::Debug for Token {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"{:?}({}..{})",
self.kind,
self.range.start(),
self.range.end(),
)
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub struct Tokens<'a> {
pub str: &'a Str,
pub slice: &'a [Token],
}
impl std::ops::Deref for Tokens<'_> {
type Target = [Token];
fn deref(&self) -> &Self::Target {
self.slice
}
}
impl InputLength for Tokens<'_> {
fn input_len(&self) -> usize {
self.slice.len()
}
}
impl InputTake for Tokens<'_> {
fn take(&self, count: usize) -> Self {
Tokens {
slice: &self.slice[count..],
..*self
}
}
fn take_split(&self, count: usize) -> (Self, Self) {
let (a, b) = self.slice.split_at(count);
(Tokens { slice: a, ..*self }, Tokens { slice: b, ..*self })
}
}
impl Tokens<'_> {
#[inline]
pub fn skip_n(self, count: usize) -> Self {
let slice = &self.slice[count..];
Tokens { slice, ..self }
}
#[inline]
pub fn get_str_slice(self) -> StrSlice {
match self.slice.first() {
Some(t) => t.range,
None => {
let len = self.str.len();
self.str.get(len..len)
}
}
}
}