cooklang/
located.rs

1//! Utility to add location information to any type
2
3use std::{
4    fmt::{Debug, Display},
5    ops::{Deref, DerefMut, Range},
6};
7
8use serde::Serialize;
9
10use crate::{error::Recover, span::Span};
11
12/// Wrapper type that adds location information to another
13#[derive(PartialEq, Serialize)]
14pub struct Located<T> {
15    inner: T,
16    span: Span,
17}
18
19impl<T> Located<T> {
20    /// Creata a new instance of [`Located`]
21    pub fn new(inner: T, span: impl Into<Span>) -> Self {
22        Self {
23            inner,
24            span: span.into(),
25        }
26    }
27
28    /// Map the inner value while keeping the same location
29    pub fn map<F, O>(self, f: F) -> Located<O>
30    where
31        F: FnOnce(T) -> O,
32    {
33        Located {
34            inner: f(self.inner),
35            span: self.span,
36        }
37    }
38
39    /// Discard the location and consume the inner value
40    pub fn into_inner(self) -> T {
41        self.inner
42    }
43
44    /// Consume and get the inner value and it's location
45    pub fn take_pair(self) -> (T, Span) {
46        (self.inner, self.span)
47    }
48
49    /// Get a reference to the inner value
50    pub fn value(&self) -> &T {
51        &self.inner
52    }
53
54    /// Get the location
55    pub fn span(&self) -> Span {
56        self.span
57    }
58}
59
60impl<T: Clone + Copy> Copy for Located<T> {}
61
62impl<T: Copy> Located<T> {
63    /// Get the inner value by copy
64    pub fn get(&self) -> T {
65        self.inner
66    }
67}
68
69impl<T> Clone for Located<T>
70where
71    T: Clone,
72{
73    fn clone(&self) -> Self {
74        Self {
75            inner: self.inner.clone(),
76            span: self.span,
77        }
78    }
79}
80
81impl<T> Debug for Located<T>
82where
83    T: Debug,
84{
85    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
86        self.inner.fmt(f)?;
87        f.write_str(" @ ")?;
88        self.span.fmt(f)
89    }
90}
91
92impl<T> Display for Located<T>
93where
94    T: Display,
95{
96    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
97        self.inner.fmt(f)
98    }
99}
100
101impl<T> Deref for Located<T> {
102    type Target = T;
103
104    fn deref(&self) -> &Self::Target {
105        &self.inner
106    }
107}
108
109impl<T> DerefMut for Located<T> {
110    fn deref_mut(&mut self) -> &mut Self::Target {
111        &mut self.inner
112    }
113}
114
115impl<T> From<Located<T>> for Range<usize> {
116    fn from(value: Located<T>) -> Self {
117        value.span.range()
118    }
119}
120
121impl<T> Recover for Located<T>
122where
123    T: Recover,
124{
125    fn recover() -> Self {
126        Self {
127            inner: T::recover(),
128            span: Recover::recover(),
129        }
130    }
131}