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