use crate::{MaybeSpanned, Span, Spanned};
#[derive(Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, Debug)]
pub struct Location<F> {
pub file: F,
pub span: Span,
}
impl<F> Location<F> {
#[inline(always)]
pub fn new(file: F, span: Span) -> Self {
Self { file, span }
}
#[inline(always)]
pub fn into_parts(self) -> (F, Span) {
(self.file, self.span)
}
#[inline(always)]
pub fn into_file(self) -> F {
self.file
}
#[inline(always)]
pub fn into_span(self) -> Span {
self.span
}
#[inline(always)]
pub fn map<G>(self, f: impl FnOnce(F) -> G) -> Location<G> {
Location {
file: f(self.file),
span: self.span,
}
}
#[inline(always)]
pub fn as_ref(&self) -> Location<&F> {
Location::new(&self.file, self.span)
}
#[inline(always)]
pub fn cast<G>(self) -> Location<G>
where
F: Into<G>,
{
Location::new(self.file.into(), self.span)
}
}
impl<F> Location<F> {
#[inline(always)]
pub fn until(mut self, end: usize) -> Self {
self.span.end = end;
self
}
#[inline(always)]
pub fn with(mut self, span: Span) -> Self {
self.span.append(span);
self
}
}
impl<F: Clone> Location<&F> {
#[inline(always)]
pub fn cloned(&self) -> Location<F> {
Location::new(self.file.clone(), self.span)
}
}
pub trait Located {
type File;
fn location(&self) -> Location<&Self::File>;
}
impl<F> Located for Location<F> {
type File = F;
fn location(&self) -> Location<&Self::File> {
self.as_ref()
}
}
impl<T: Located> Spanned for T {
fn span(&self) -> Span {
self.location().span
}
}
pub trait MaybeLocated {
type File;
fn optional_location(&self) -> Option<Location<&Self::File>>;
}
impl<T: MaybeLocated> MaybeSpanned for T {
fn optional_span(&self) -> Option<Span> {
self.optional_location().map(Location::into_span)
}
}
impl<T: Located> MaybeLocated for T {
type File = T::File;
fn optional_location(&self) -> Option<Location<&Self::File>> {
Some(self.location())
}
}