use crate::Text; use derive_new::new; use getset::Getters; use serde::Serialize; use serde_derive::Deserialize; use uuid::Uuid; #[derive( new, Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Serialize, Deserialize, Hash, Getters, )] #[get = "crate"] pub struct Tagged { pub tag: Tag, pub item: T, } pub trait TaggedItem: Sized { fn tagged(self, span: impl Into) -> Tagged { Tagged::from_item(self, span.into()) } // For now, this is a temporary facility. In many cases, there are other useful spans that we // could be using, such as the original source spans of JSON or Toml files, but we don't yet // have the infrastructure to make that work. fn tagged_unknown(self) -> Tagged { Tagged::from_item(self, (0, 0)) } } impl TaggedItem for T {} impl std::ops::Deref for Tagged { type Target = T; fn deref(&self) -> &T { &self.item } } impl Tagged { pub fn tagged(self, span: impl Into) -> Tagged { Tagged::from_item(self.item, span.into()) } pub fn from_item(item: T, span: impl Into) -> Tagged { Tagged { item, tag: Tag { span: span.into() }, } } pub fn map(self, input: impl FnOnce(T) -> U) -> Tagged { let span = self.span(); let mapped = input(self.item); Tagged::from_item(mapped, span) } crate fn copy_span(&self, output: U) -> Tagged { let span = self.span(); Tagged::from_item(output, span) } pub fn source(&self, source: &Text) -> Text { Text::from(self.span().slice(source)) } pub fn span(&self) -> Span { self.tag.span } } impl From<&Tagged> for Span { fn from(input: &Tagged) -> Span { input.span() } } impl From<&Span> for Span { fn from(input: &Span) -> Span { *input } } impl From> for Span { fn from(input: nom5_locate::LocatedSpan<&str>) -> Span { Span { start: input.offset, end: input.offset + input.fragment.len(), source: None, } } } impl From<(nom5_locate::LocatedSpan, nom5_locate::LocatedSpan)> for Span { fn from(input: (nom5_locate::LocatedSpan, nom5_locate::LocatedSpan)) -> Span { Span { start: input.0.offset, end: input.1.offset, source: None, } } } impl From<(usize, usize)> for Span { fn from(input: (usize, usize)) -> Span { Span { start: input.0, end: input.1, source: None, } } } impl From<&std::ops::Range> for Span { fn from(input: &std::ops::Range) -> Span { Span { start: input.start, end: input.end, source: None, } } } #[derive( Debug, Clone, Copy, PartialEq, Eq, Ord, PartialOrd, Serialize, Deserialize, Hash, Getters, )] pub struct Tag { pub span: Span, } #[derive(Debug, Clone, Copy, PartialEq, Eq, Ord, PartialOrd, Serialize, Deserialize, Hash)] pub struct Span { crate start: usize, crate end: usize, pub source: Option, } impl From> for Span { fn from(input: Option) -> Span { match input { None => Span { start: 0, end: 0, source: None, }, Some(span) => span, } } } impl Span { pub fn unknown() -> Span { Span { start: 0, end: 0, source: None, } } pub fn unknown_with_uuid(uuid: Uuid) -> Span { Span { start: 0, end: 0, source: Some(uuid), } } pub fn is_unknown(&self) -> bool { self.start == 0 && self.end == 0 } pub fn slice(&self, source: &'a str) -> &'a str { &source[self.start..self.end] } } impl language_reporting::ReportingSpan for Span { fn with_start(&self, start: usize) -> Self { Span { start, end: self.end, source: None, } } fn with_end(&self, end: usize) -> Self { Span { start: self.start, end, source: None, } } fn start(&self) -> usize { self.start } fn end(&self) -> usize { self.end } }