facet_deserialize/
span.rs1use alloc::vec::Vec;
2use core::fmt;
3use core::marker::PhantomData;
4
5#[derive(Debug, PartialEq)]
7pub enum Cooked {}
8
9#[derive(Debug, PartialEq)]
11pub enum Raw {}
12
13pub type Pos = usize;
15
16#[derive(Debug, PartialEq, Eq)]
18pub struct Span<C = Cooked> {
19 pub start: Pos,
21 pub len: usize,
23 _p: PhantomData<C>,
25}
26
27pub trait Spannable<C = Cooked>: Sized {
29 fn with_span(self, span: Span<C>) -> Spanned<Self, C>;
31}
32
33impl<T, C> Spannable<C> for T {
34 fn with_span(self, span: Span<C>) -> Spanned<Self, C> {
35 Spanned { node: self, span }
36 }
37}
38
39impl<C> Span<C> {
40 pub fn new(start: Pos, len: usize) -> Self {
42 Span {
43 start,
44 len,
45 _p: PhantomData,
46 }
47 }
48 pub fn start(&self) -> Pos {
50 self.start
51 }
52 pub fn len(&self) -> usize {
54 self.len
55 }
56 pub fn is_empty(&self) -> bool {
58 self.len == 0
59 }
60 pub fn end(&self) -> Pos {
62 self.start + self.len
63 }
64}
65
66impl<C> Default for Span<C> {
67 fn default() -> Self {
68 Span {
69 start: 0,
70 len: 0,
71 _p: PhantomData,
72 }
73 }
74}
75
76#[derive(Debug, Clone, PartialEq, Eq)]
78pub struct Spanned<T, C = Cooked> {
79 pub node: T,
81 pub span: Span<C>,
83}
84
85impl<T: fmt::Display, C> fmt::Display for Spanned<T, C> {
86 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
87 write!(
88 f,
89 "{} at {}-{}",
90 self.node,
91 self.span.start(),
92 self.span.end()
93 )
94 }
95}
96
97impl<C> Clone for Span<C> {
101 fn clone(&self) -> Self {
102 *self
103 }
104}
105
106impl<C> Copy for Span<C> {}
107
108#[derive(Clone, Debug, PartialEq)]
110pub struct Subspan {
111 pub offset: usize,
113 pub len: usize,
115 pub meta: Option<SubspanMeta>,
117}
118
119#[derive(Debug, Copy, Clone, PartialEq)]
122pub enum SubspanMeta {
123 Delimiter(char),
126
127 KeyValue,
130 }
132
133pub struct Substack<C> {
135 spans: Option<Vec<Subspan>>,
136 _marker: PhantomData<C>,
137}
138
139impl<C> Substack<C> {
140 pub fn new() -> Self {
142 Substack {
143 spans: None,
144 _marker: PhantomData,
145 }
146 }
147
148 pub fn get(&self) -> &[Subspan] {
150 match &self.spans {
151 Some(spans) => spans,
152 None => &[], }
154 }
155
156 pub fn pop(&mut self) -> Option<Subspan> {
158 if let Some(spans) = &mut self.spans {
159 spans.pop()
160 } else {
161 None
162 }
163 }
164
165 pub fn clear(&mut self) {
167 if let Some(spans) = &mut self.spans {
168 spans.clear();
169 }
170 }
171}
172
173impl<C> Default for Substack<C> {
174 fn default() -> Self {
175 Self::new()
176 }
177}
178
179impl<C> From<Vec<Subspan>> for Substack<C> {
180 fn from(subspans: Vec<Subspan>) -> Self {
181 Substack {
182 spans: Some(subspans),
183 _marker: PhantomData,
184 }
185 }
186}
187
188impl Substack<Raw> {
189 pub fn add(&mut self, offset: usize, len: usize, meta: Option<SubspanMeta>) {
191 if self.spans.is_none() {
192 self.spans = Some(Vec::new());
193 }
194
195 if let Some(spans) = &mut self.spans {
196 spans.push(Subspan { offset, len, meta });
197 }
198 }
199
200 pub fn add_simple(&mut self, offset: usize, len: usize) {
202 self.add(offset, len, None);
203 }
204
205 pub fn add_delimiter(&mut self, offset: usize, len: usize, delimiter: char) {
207 self.add(offset, len, Some(SubspanMeta::Delimiter(delimiter)));
208 }
209
210 pub fn add_key_value(&mut self, offset: usize, len: usize) {
212 self.add(offset, len, Some(SubspanMeta::KeyValue));
213 }
214}
215
216impl Substack<Cooked> {
217 pub fn add(&mut self, _offset: usize, _len: usize, _meta: Option<SubspanMeta>) {}
219
220 pub fn add_simple(&mut self, _offset: usize, _len: usize) {}
222
223 pub fn add_delimiter(&mut self, _offset: usize, _len: usize, _delimiter: char) {}
225
226 pub fn add_key_value(&mut self, _offset: usize, _len: usize) {}
228}
229
230pub trait SubstackBehavior {
233 const USES_SUBSTACK: bool;
235}
236
237impl SubstackBehavior for Raw {
238 const USES_SUBSTACK: bool = true;
239}
240
241impl SubstackBehavior for Cooked {
242 const USES_SUBSTACK: bool = false;
243}