use std::borrow::Borrow;
use std::ops::{Deref, DerefMut};
use cpclib_common::smol_str::SmolStr;
use cpclib_common::nom::error::{ErrorKind, ParseError};
use cpclib_common::nom::{
Compare, CompareResult, Err, FindSubstring, IResult, InputIter, InputLength, InputTake, Needed,
Offset, Slice
};
use cpclib_common::nom_locate::LocatedSpan;
use cpclib_tokens::symbols::Source;
use super::context::ParserContext;
use super::ParsingState;
type InnerZ80Span = LocatedSpan<
&'static str,
&'static ParserContext
>;
#[derive(Clone, PartialEq, Eq)]
pub struct Z80Span(pub(crate) InnerZ80Span);
impl AsRef<str> for Z80Span {
#[inline]
fn as_ref(&self) -> &str {
self.fragment()
}
}
impl Z80Span {
#[inline]
pub fn as_str(&self) -> &str {
self.as_ref()
}
}
impl Borrow<str> for Z80Span {
#[inline]
fn borrow(&self) -> &str {
self.as_str()
}
}
impl std::fmt::Display for Z80Span {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "{}", self.as_str())
}
}
impl std::fmt::Debug for Z80Span {
#[inline]
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(
f,
"{}:{}:{} <{}>",
self.context()
.current_filename
.as_ref()
.map(|f| f.to_str().unwrap_or("<invalid filename>"))
.unwrap_or("unknown"),
self.location_line(),
self.get_utf8_column(),
self.as_str()
)
}
}
impl Into<SmolStr> for &Z80Span {
fn into(self) -> SmolStr {
SmolStr::from(self.as_str())
}
}
impl Into<SmolStr> for Z80Span {
fn into(self) -> SmolStr {
SmolStr::from(self.as_str())
}
}
impl Into<Source> for &Z80Span {
#[inline]
fn into(self) -> Source {
Source::new(
self.context()
.current_filename
.as_ref()
.map(|fname| fname.display().to_string())
.unwrap_or_else(|| "<INLINE>".into()),
self.0.location_line() as _,
self.0.get_utf8_column()
)
}
}
impl<'a> Into<LocatedSpan<&'a str>> for Z80Span {
#[inline]
fn into(self) -> LocatedSpan<&'a str> {
unsafe {
LocatedSpan::new_from_raw_offset(
self.location_offset(),
self.location_line(),
self.fragment(),
()
)
}
}
}
impl Deref for Z80Span {
type Target = InnerZ80Span;
#[inline]
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl DerefMut for Z80Span {
#[inline]
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}
impl AsRef<InnerZ80Span> for Z80Span {
#[inline]
fn as_ref(&self) -> &InnerZ80Span {
self.deref()
}
}
impl Compare<&'static str> for Z80Span {
#[inline]
fn compare(&self, t: &'static str) -> CompareResult {
self.deref().compare(t)
}
#[inline]
fn compare_no_case(&self, t: &'static str) -> CompareResult {
self.deref().compare_no_case(t)
}
}
impl cpclib_common::nom::InputIter for Z80Span {
type Item = <InnerZ80Span as cpclib_common::nom::InputIter>::Item;
type Iter = <InnerZ80Span as cpclib_common::nom::InputIter>::Iter;
type IterElem = <InnerZ80Span as cpclib_common::nom::InputIter>::IterElem;
#[inline]
fn iter_indices(&self) -> Self::Iter {
self.deref().iter_indices()
}
#[inline]
fn iter_elements(&self) -> Self::IterElem {
self.deref().iter_elements()
}
#[inline]
fn position<P>(&self, predicate: P) -> Option<usize>
where P: Fn(Self::Item) -> bool {
self.deref().position(predicate)
}
#[inline]
fn slice_index(&self, count: usize) -> Result<usize, Needed> {
self.deref().slice_index(count)
}
}
impl cpclib_common::nom::InputLength for Z80Span {
#[inline]
fn input_len(&self) -> usize {
self.deref().input_len()
}
}
impl Offset for Z80Span {
#[inline]
fn offset(&self, second: &Self) -> usize {
self.deref().offset(second.deref())
}
}
impl cpclib_common::nom::InputTake for Z80Span {
#[inline]
fn take(&self, count: usize) -> Self {
Self(self.deref().take(count))
}
#[inline]
fn take_split(&self, count: usize) -> (Self, Self) {
let res = self.deref().take_split(count);
(Self(res.0), Self(res.1))
}
}
impl cpclib_common::nom::InputTakeAtPosition for Z80Span {
type Item = <InnerZ80Span as cpclib_common::nom::InputIter>::Item;
#[inline]
fn split_at_position<P, E: ParseError<Self>>(&self, predicate: P) -> IResult<Self, Self, E>
where P: Fn(Self::Item) -> bool {
match self.deref().position(predicate) {
Some(n) => Ok(self.take_split(n)),
None => Err(Err::Incomplete(cpclib_common::nom::Needed::new(1)))
}
}
#[inline]
fn split_at_position1<P, E: ParseError<Self>>(
&self,
predicate: P,
e: ErrorKind
) -> IResult<Self, Self, E>
where
P: Fn(Self::Item) -> bool
{
match self.deref().position(predicate) {
Some(0) => Err(Err::Error(E::from_error_kind(self.clone(), e))),
Some(n) => Ok(self.take_split(n)),
None => Err(Err::Incomplete(cpclib_common::nom::Needed::new(1)))
}
}
#[inline]
fn split_at_position_complete<P, E: ParseError<Self>>(
&self,
predicate: P
) -> IResult<Self, Self, E>
where
P: Fn(Self::Item) -> bool
{
match self.split_at_position(predicate) {
Err(Err::Incomplete(_)) => Ok(self.take_split(self.input_len())),
res => res
}
}
#[inline]
fn split_at_position1_complete<P, E: ParseError<Self>>(
&self,
predicate: P,
e: ErrorKind
) -> IResult<Self, Self, E>
where
P: Fn(Self::Item) -> bool
{
match self.fragment().position(predicate) {
Some(0) => Err(Err::Error(E::from_error_kind(self.clone(), e))),
Some(n) => Ok(self.take_split(n)),
None => {
if self.fragment().input_len() == 0 {
Err(Err::Error(E::from_error_kind(self.clone(), e)))
}
else {
Ok(self.take_split(self.input_len()))
}
}
}
}
}
impl<'src, 'ctx, U> FindSubstring<U> for Z80Span
where &'src str: FindSubstring<U>
{
#[inline]
fn find_substring(&self, substr: U) -> Option<usize> {
self.fragment().find_substring(substr)
}
}
impl Slice<std::ops::Range<usize>> for Z80Span {
#[inline]
fn slice(&self, range: std::ops::Range<usize>) -> Self {
Self(self.deref().slice(range))
}
}
impl Slice<std::ops::RangeFrom<usize>> for Z80Span {
#[inline]
fn slice(&self, range: std::ops::RangeFrom<usize>) -> Self {
Self(self.deref().slice(range))
}
}
impl Slice<std::ops::RangeTo<usize>> for Z80Span {
#[inline]
fn slice(&self, range: std::ops::RangeTo<usize>) -> Self {
Self(self.deref().slice(range))
}
}
impl Z80Span {
pub fn new_extra(src: &str, ctx: &ParserContext) -> Self {
Self(LocatedSpan::new_extra(
unsafe { &*(src as *const str) as &'static str },
unsafe { &*(ctx as *const ParserContext) as &'static ParserContext }
))
}
pub fn context(&self) -> &ParserContext {
&self.0.extra
}
}
impl Z80Span {
pub fn state(&self) -> &ParsingState {
&self.context().state
}
}