nushell/src/data/meta.rs

373 lines
7.8 KiB
Rust
Raw Normal View History

2019-08-10 22:18:14 +02:00
use crate::context::{SourceMap, SpanSource};
2019-07-24 00:22:11 +02:00
use crate::prelude::*;
2019-06-22 22:46:16 +02:00
use crate::Text;
2019-06-11 07:53:04 +02:00
use derive_new::new;
2019-06-22 03:36:57 +02:00
use getset::Getters;
2019-08-02 21:15:07 +02:00
use serde::Deserialize;
use serde::Serialize;
use std::path::{Path, PathBuf};
use uuid::Uuid;
2019-06-11 07:53:04 +02:00
#[derive(new, Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Serialize, Deserialize, Hash)]
pub struct Tagged<T> {
pub tag: Tag,
2019-06-27 06:56:48 +02:00
pub item: T,
2019-06-11 07:53:04 +02:00
}
impl<T> HasTag for Tagged<T> {
fn tag(&self) -> Tag {
self.tag
}
}
impl AsRef<Path> for Tagged<PathBuf> {
fn as_ref(&self) -> &Path {
self.item.as_ref()
2019-07-24 00:22:11 +02:00
}
}
pub trait TaggedItem: Sized {
fn tagged(self, tag: impl Into<Tag>) -> Tagged<Self> {
Tagged::from_item(self, tag.into())
2019-07-09 06:31:26 +02:00
}
2019-07-08 18:44:53 +02:00
// 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<Self> {
Tagged::from_item(
self,
Tag {
span: Span::unknown(),
origin: uuid::Uuid::nil(),
},
)
2019-07-08 18:44:53 +02:00
}
}
impl<T> TaggedItem for T {}
impl<T> std::ops::Deref for Tagged<T> {
2019-06-11 07:53:04 +02:00
type Target = T;
fn deref(&self) -> &T {
&self.item
}
}
impl<T> Tagged<T> {
pub fn with_tag(self, tag: impl Into<Tag>) -> Tagged<T> {
Tagged::from_item(self.item, tag)
}
pub fn from_item(item: T, tag: impl Into<Tag>) -> Tagged<T> {
Tagged {
2019-06-11 07:53:04 +02:00
item,
tag: tag.into(),
2019-06-11 07:53:04 +02:00
}
}
pub fn map<U>(self, input: impl FnOnce(T) -> U) -> Tagged<U> {
let tag = self.tag();
2019-06-11 07:53:04 +02:00
let mapped = input(self.item);
Tagged::from_item(mapped, tag)
2019-06-11 07:53:04 +02:00
}
2019-06-22 03:36:57 +02:00
pub(crate) fn copy_tag<U>(&self, output: U) -> Tagged<U> {
Tagged::from_item(output, self.tag())
2019-06-22 03:36:57 +02:00
}
2019-06-22 22:46:16 +02:00
pub fn source(&self, source: &Text) -> Text {
Text::from(self.tag().slice(source))
}
2019-06-11 07:53:04 +02:00
pub fn tag(&self) -> Tag {
self.tag
}
2019-09-18 08:37:04 +02:00
pub fn span(&self) -> Span {
self.tag.span
}
pub fn origin(&self) -> uuid::Uuid {
self.tag.origin
}
2019-08-10 22:18:14 +02:00
pub fn origin_name(&self, source_map: &SourceMap) -> Option<String> {
match source_map.get(&self.tag.origin) {
Some(SpanSource::File(file)) => Some(file.clone()),
Some(SpanSource::Url(url)) => Some(url.clone()),
2019-08-10 22:18:14 +02:00
_ => None,
}
}
pub fn item(&self) -> &T {
&self.item
2019-07-08 18:44:53 +02:00
}
pub fn into_parts(self) -> (T, Tag) {
(self.item, self.tag)
}
2019-07-08 18:44:53 +02:00
}
impl From<&Tag> for Tag {
fn from(input: &Tag) -> Tag {
2019-06-22 03:36:57 +02:00
*input
}
}
impl From<nom_locate::LocatedSpanEx<&str, Uuid>> for Span {
fn from(input: nom_locate::LocatedSpanEx<&str, Uuid>) -> Span {
2019-06-22 03:36:57 +02:00
Span {
start: input.offset,
end: input.offset + input.fragment.len(),
}
}
}
impl<T>
From<(
nom_locate::LocatedSpanEx<T, Uuid>,
nom_locate::LocatedSpanEx<T, Uuid>,
)> for Span
{
fn from(
input: (
nom_locate::LocatedSpanEx<T, Uuid>,
nom_locate::LocatedSpanEx<T, Uuid>,
),
) -> Span {
2019-06-11 07:53:04 +02:00
Span {
start: input.0.offset,
end: input.1.offset,
}
}
}
impl From<(usize, usize)> for Span {
fn from(input: (usize, usize)) -> Span {
Span {
start: input.0,
end: input.1,
}
}
}
impl From<&std::ops::Range<usize>> for Span {
fn from(input: &std::ops::Range<usize>) -> Span {
Span {
start: input.start,
end: input.end,
}
}
}
#[derive(
Debug, Clone, Copy, PartialEq, Eq, Ord, PartialOrd, Serialize, Deserialize, Hash, Getters,
)]
pub struct Tag {
pub origin: Uuid,
pub span: Span,
}
impl From<Span> for Tag {
fn from(span: Span) -> Self {
Tag {
origin: uuid::Uuid::nil(),
span,
}
}
}
impl From<&Span> for Tag {
fn from(span: &Span) -> Self {
Tag {
origin: uuid::Uuid::nil(),
span: *span,
}
}
}
impl From<(usize, usize, Uuid)> for Tag {
fn from((start, end, origin): (usize, usize, Uuid)) -> Self {
Tag {
origin,
span: Span { start, end },
}
}
}
impl From<(usize, usize, Option<Uuid>)> for Tag {
fn from((start, end, origin): (usize, usize, Option<Uuid>)) -> Self {
Tag {
origin: if let Some(uuid) = origin {
uuid
} else {
uuid::Uuid::nil()
},
span: Span { start, end },
}
}
}
impl From<nom_locate::LocatedSpanEx<&str, Uuid>> for Tag {
fn from(input: nom_locate::LocatedSpanEx<&str, Uuid>) -> Tag {
Tag {
origin: input.extra,
span: Span {
start: input.offset,
end: input.offset + input.fragment.len(),
},
}
}
}
impl From<Tag> for Span {
fn from(tag: Tag) -> Self {
tag.span
}
}
impl From<&Tag> for Span {
fn from(tag: &Tag) -> Self {
tag.span
}
}
impl Tag {
pub fn unknown_origin(span: Span) -> Tag {
Tag {
origin: uuid::Uuid::nil(),
span,
}
}
pub fn unknown_span(origin: Uuid) -> Tag {
Tag {
origin,
span: Span::unknown(),
}
}
pub fn unknown() -> Tag {
Tag {
origin: uuid::Uuid::nil(),
span: Span::unknown(),
}
}
pub fn until(&self, other: impl Into<Tag>) -> Tag {
let other = other.into();
2019-09-14 19:16:52 +02:00
debug_assert!(
self.origin == other.origin,
"Can only merge two tags with the same origin"
);
Tag {
span: Span {
start: self.span.start,
2019-09-14 19:16:52 +02:00
end: other.span.end,
},
2019-09-14 19:16:52 +02:00
origin: self.origin,
}
}
pub fn slice<'a>(&self, source: &'a str) -> &'a str {
self.span.slice(source)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Ord, PartialOrd, Serialize, Deserialize, Hash)]
pub struct Span {
pub(crate) start: usize,
pub(crate) end: usize,
}
impl From<Option<Span>> for Span {
fn from(input: Option<Span>) -> Span {
match input {
None => Span { start: 0, end: 0 },
Some(span) => span,
2019-06-11 07:53:04 +02:00
}
}
}
impl Span {
2019-07-08 18:44:53 +02:00
pub fn unknown() -> Span {
Span { start: 0, end: 0 }
}
/*
pub fn unknown_with_uuid(uuid: Uuid) -> Span {
Span {
start: 0,
end: 0,
source: Some(uuid),
}
2019-07-08 18:44:53 +02:00
}
*/
2019-07-08 18:44:53 +02:00
pub fn is_unknown(&self) -> bool {
self.start == 0 && self.end == 0
}
pub fn slice<'a>(&self, source: &'a str) -> &'a str {
2019-06-22 03:36:57 +02:00
&source[self.start..self.end]
2019-06-11 07:53:04 +02:00
}
}
impl language_reporting::ReportingSpan for Span {
fn with_start(&self, start: usize) -> Self {
Span {
start,
end: self.end,
}
}
fn with_end(&self, end: usize) -> Self {
Span {
start: self.start,
end,
}
}
fn start(&self) -> usize {
self.start
}
fn end(&self) -> usize {
self.end
}
}
impl language_reporting::ReportingSpan for Tag {
fn with_start(&self, start: usize) -> Self {
Tag {
span: Span {
start,
end: self.span.end,
},
origin: self.origin,
}
}
fn with_end(&self, end: usize) -> Self {
Tag {
span: Span {
start: self.span.start,
end,
},
origin: self.origin,
}
}
fn start(&self) -> usize {
self.span.start
}
fn end(&self) -> usize {
self.span.end
}
}