1use crate::pretty::{DbgDocBldr, DebugDocBuilder, PrettyDebugWithSource};
2use crate::text::Text;
3
4use derive_new::new;
5use getset::Getters;
6use serde::Deserialize;
7use serde::Serialize;
8use std::cmp::Ordering;
9use std::path::{Path, PathBuf};
10
11#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord, Hash)]
13pub enum AnchorLocation {
14 Url(String),
16 File(String),
18 Source(Text),
20}
21
22pub trait HasTag {
23 fn tag(&self) -> Tag;
25}
26
27#[derive(new, Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Serialize, Deserialize, Hash)]
29pub struct Spanned<T> {
30 pub span: Span,
31 pub item: T,
32}
33
34impl<T> Spanned<T> {
35 pub fn map<U>(self, input: impl FnOnce(T) -> U) -> Spanned<U> {
37 let span = self.span;
38
39 let mapped = input(self.item);
40 mapped.spanned(span)
41 }
42}
43
44impl Spanned<String> {
45 pub fn items<'a, U>(
47 items: impl Iterator<Item = &'a Spanned<String>>,
48 ) -> impl Iterator<Item = &'a str> {
49 items.map(|item| &item.item[..])
50 }
51
52 pub fn borrow_spanned(&self) -> Spanned<&str> {
54 let span = self.span;
55 self.item[..].spanned(span)
56 }
57
58 pub fn slice_spanned(&self, span: impl Into<Span>) -> Spanned<&str> {
59 let span = span.into();
60 let item = &self.item[span.start()..span.end()];
61 item.spanned(span)
62 }
63}
64
65pub trait SpannedItem: Sized {
66 fn spanned(self, span: impl Into<Span>) -> Spanned<Self> {
68 Spanned {
69 item: self,
70 span: span.into(),
71 }
72 }
73
74 fn spanned_unknown(self) -> Spanned<Self> {
76 Spanned {
77 item: self,
78 span: Span::unknown(),
79 }
80 }
81}
82impl<T> SpannedItem for T {}
83
84impl<T> std::ops::Deref for Spanned<T> {
85 type Target = T;
86
87 fn deref(&self) -> &T {
89 &self.item
90 }
91}
92
93#[derive(new, Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Serialize, Deserialize, Hash)]
95pub struct Tagged<T> {
96 pub tag: Tag,
97 pub item: T,
98}
99
100impl Tagged<String> {
101 pub fn borrow_spanned(&self) -> Spanned<&str> {
103 let span = self.tag.span;
104 self.item[..].spanned(span)
105 }
106
107 pub fn borrow_tagged(&self) -> Tagged<&str> {
109 self.item[..].tagged(self.tag.clone())
110 }
111}
112
113impl<T> Tagged<Vec<T>> {
114 pub fn items(&self) -> impl Iterator<Item = &T> {
116 self.item.iter()
117 }
118}
119
120impl<T> HasTag for Tagged<T> {
121 fn tag(&self) -> Tag {
123 self.tag.clone()
124 }
125}
126
127impl AsRef<Path> for Tagged<PathBuf> {
128 fn as_ref(&self) -> &Path {
130 self.item.as_ref()
131 }
132}
133
134pub trait TaggedItem: Sized {
135 fn tagged(self, tag: impl Into<Tag>) -> Tagged<Self> {
136 Tagged {
137 item: self,
138 tag: tag.into(),
139 }
140 }
141
142 fn tagged_unknown(self) -> Tagged<Self> {
146 Tagged {
147 item: self,
148 tag: Tag {
149 span: Span::unknown(),
150 anchor: None,
151 },
152 }
153 }
154}
155
156impl<T> TaggedItem for T {}
157
158impl<T> std::ops::Deref for Tagged<T> {
159 type Target = T;
160
161 fn deref(&self) -> &T {
162 &self.item
163 }
164}
165
166impl<T> Tagged<T> {
167 pub fn map<U>(self, input: impl FnOnce(T) -> U) -> Tagged<U> {
168 let tag = self.tag();
169
170 let mapped = input(self.item);
171 mapped.tagged(tag)
172 }
173
174 pub fn map_anchored(self, anchor: &Option<AnchorLocation>) -> Tagged<T> {
175 let mut tag = self.tag;
176
177 tag.anchor = anchor.clone();
178
179 Tagged {
180 item: self.item,
181 tag,
182 }
183 }
184
185 pub fn transpose(&self) -> Tagged<&T> {
186 Tagged {
187 item: &self.item,
188 tag: self.tag.clone(),
189 }
190 }
191
192 pub fn tag(&self) -> Tag {
194 self.tag.clone()
195 }
196
197 pub fn span(&self) -> Span {
199 self.tag.span
200 }
201
202 pub fn anchor(&self) -> Option<AnchorLocation> {
204 self.tag.anchor.clone()
205 }
206
207 pub fn anchor_name(&self) -> Option<String> {
209 match self.tag.anchor {
210 Some(AnchorLocation::File(ref file)) => Some(file.clone()),
211 Some(AnchorLocation::Url(ref url)) => Some(url.clone()),
212 _ => None,
213 }
214 }
215
216 pub fn item(&self) -> &T {
218 &self.item
219 }
220
221 pub fn into_parts(self) -> (T, Tag) {
223 (self.item, self.tag)
224 }
225}
226
227impl From<&Tag> for Tag {
228 fn from(input: &Tag) -> Tag {
229 input.clone()
230 }
231}
232
233impl From<(usize, usize)> for Span {
234 fn from(input: (usize, usize)) -> Span {
235 Span::new(input.0, input.1)
236 }
237}
238
239impl From<&std::ops::Range<usize>> for Span {
240 fn from(input: &std::ops::Range<usize>) -> Span {
241 Span::new(input.start, input.end)
242 }
243}
244
245#[derive(
247 Debug,
248 Default,
249 Clone,
250 PartialEq,
251 Eq,
252 Ord,
253 PartialOrd,
254 Serialize,
255 Deserialize,
256 Hash,
257 Getters,
258 new,
259)]
260pub struct Tag {
261 pub anchor: Option<AnchorLocation>,
263 pub span: Span,
265}
266
267impl From<Span> for Tag {
268 fn from(span: Span) -> Self {
269 Tag { anchor: None, span }
270 }
271}
272
273impl From<&Span> for Tag {
274 fn from(span: &Span) -> Self {
275 Tag {
276 anchor: None,
277 span: *span,
278 }
279 }
280}
281
282impl From<(usize, usize, AnchorLocation)> for Tag {
283 fn from((start, end, anchor): (usize, usize, AnchorLocation)) -> Self {
284 Tag {
285 anchor: Some(anchor),
286 span: Span::new(start, end),
287 }
288 }
289}
290
291impl From<(usize, usize, Option<AnchorLocation>)> for Tag {
292 fn from((start, end, anchor): (usize, usize, Option<AnchorLocation>)) -> Self {
293 Tag {
294 anchor,
295 span: Span::new(start, end),
296 }
297 }
298}
299
300impl From<Tag> for Span {
301 fn from(tag: Tag) -> Self {
302 tag.span
303 }
304}
305
306impl From<&Tag> for Span {
307 fn from(tag: &Tag) -> Self {
308 tag.span
309 }
310}
311
312impl Tag {
313 pub fn default() -> Self {
315 Tag {
316 anchor: None,
317 span: Span::unknown(),
318 }
319 }
320
321 pub fn anchored(self, anchor: Option<AnchorLocation>) -> Tag {
322 Tag {
323 anchor,
324 span: self.span,
325 }
326 }
327
328 pub fn unknown_anchor(span: Span) -> Tag {
330 Tag { anchor: None, span }
331 }
332
333 pub fn for_char(pos: usize, anchor: AnchorLocation) -> Tag {
335 Tag {
336 anchor: Some(anchor),
337 span: Span::new(pos, pos + 1),
338 }
339 }
340
341 pub fn unknown_span(anchor: AnchorLocation) -> Tag {
343 Tag {
344 anchor: Some(anchor),
345 span: Span::unknown(),
346 }
347 }
348
349 pub fn unknown() -> Tag {
351 Tag {
352 anchor: None,
353 span: Span::unknown(),
354 }
355 }
356
357 pub fn anchor(&self) -> Option<AnchorLocation> {
359 self.anchor.clone()
360 }
361
362 pub fn until(&self, other: impl Into<Tag>) -> Tag {
367 let other = other.into();
368 debug_assert!(
369 self.anchor == other.anchor,
370 "Can only merge two tags with the same anchor"
371 );
372
373 Tag {
374 span: Span::new(self.span.start, other.span.end),
375 anchor: self.anchor.clone(),
376 }
377 }
378
379 pub fn until_option(&self, other: Option<impl Into<Tag>>) -> Tag {
385 match other {
386 Some(other) => {
387 let other = other.into();
388 debug_assert!(
389 self.anchor == other.anchor,
390 "Can only merge two tags with the same anchor"
391 );
392
393 Tag {
394 span: Span::new(self.span.start, other.span.end),
395 anchor: self.anchor.clone(),
396 }
397 }
398 None => self.clone(),
399 }
400 }
401
402 pub fn slice<'a>(&self, source: &'a str) -> &'a str {
403 self.span.slice(source)
404 }
405
406 pub fn string(&self, source: &str) -> String {
407 self.span.slice(source).to_string()
408 }
409
410 pub fn tagged_slice<'a>(&self, source: &'a str) -> Tagged<&'a str> {
411 self.span.slice(source).tagged(self)
412 }
413
414 pub fn tagged_string(&self, source: &str) -> Tagged<String> {
415 self.span.slice(source).to_string().tagged(self)
416 }
417
418 pub fn anchor_name(&self) -> Option<String> {
419 match self.anchor {
420 Some(AnchorLocation::File(ref file)) => Some(file.clone()),
421 Some(AnchorLocation::Url(ref url)) => Some(url.clone()),
422 _ => None,
423 }
424 }
425}
426
427pub fn tag_for_tagged_list(mut iter: impl Iterator<Item = Tag>) -> Tag {
428 let first = iter.next();
429
430 let first = match first {
431 None => return Tag::unknown(),
432 Some(first) => first,
433 };
434
435 let last = iter.last();
436
437 match last {
438 None => first,
439 Some(last) => first.until(last),
440 }
441}
442
443pub fn span_for_spanned_list(mut iter: impl Iterator<Item = Span>) -> Span {
444 let first = iter.next();
445
446 let first = match first {
447 None => return Span::unknown(),
448 Some(first) => first,
449 };
450
451 let last = iter.last();
452
453 match last {
454 None => first,
455 Some(last) => first.until(last),
456 }
457}
458
459#[derive(
464 Debug, Default, Clone, Copy, PartialEq, Eq, Ord, PartialOrd, Serialize, Deserialize, Hash,
465)]
466pub struct Span {
467 start: usize,
468 end: usize,
469}
470
471impl From<&Span> for Span {
472 fn from(span: &Span) -> Span {
473 *span
474 }
475}
476
477impl From<Option<Span>> for Span {
478 fn from(input: Option<Span>) -> Span {
479 input.unwrap_or_else(|| Span::new(0, 0))
480 }
481}
482
483impl From<Span> for std::ops::Range<usize> {
484 fn from(input: Span) -> std::ops::Range<usize> {
485 std::ops::Range {
486 start: input.start,
487 end: input.end,
488 }
489 }
490}
491
492impl Span {
493 pub fn default() -> Self {
495 Span::unknown()
496 }
497
498 pub fn unknown() -> Span {
500 Span::new(0, 0)
501 }
502
503 pub fn from_list(list: &[impl HasSpan]) -> Span {
504 let mut iterator = list.iter();
505
506 match iterator.next() {
507 None => Span::new(0, 0),
508 Some(first) => {
509 let last = iterator.last().unwrap_or(first);
510
511 Span::new(first.span().start, last.span().end)
512 }
513 }
514 }
515
516 pub fn new(start: usize, end: usize) -> Span {
518 assert!(
519 end >= start,
520 "Can't create a Span whose end < start, start={}, end={}",
521 start,
522 end
523 );
524
525 Span { start, end }
526 }
527
528 pub fn new_option(start: usize, end: usize) -> Option<Span> {
529 if end >= start {
530 None
531 } else {
532 Some(Span { start, end })
533 }
534 }
535
536 pub fn for_char(pos: usize) -> Span {
547 Span {
548 start: pos,
549 end: pos + 1,
550 }
551 }
552
553 pub fn contains(&self, pos: usize) -> bool {
565 self.start <= pos && pos < self.end
566 }
567
568 pub fn since(&self, other: impl Into<Span>) -> Span {
583 let other = other.into();
584
585 Span::new(other.start, self.end)
586 }
587
588 pub fn until(&self, other: impl Into<Span>) -> Span {
603 let other = other.into();
604
605 Span::new(self.start, other.end)
606 }
607
608 pub fn merge(&self, other: impl Into<Span>) -> Span {
609 let other = other.into();
610
611 if other.end < self.start {
612 other.until(self)
613 } else {
614 self.until(other)
615 }
616 }
617
618 pub fn until_option(&self, other: Option<impl Into<Span>>) -> Span {
623 match other {
624 Some(other) => {
625 let other = other.into();
626
627 Span::new(self.start, other.end)
628 }
629 None => *self,
630 }
631 }
632
633 pub fn string(&self, source: &str) -> String {
634 self.slice(source).to_string()
635 }
636
637 pub fn spanned_slice<'a>(&self, source: &'a str) -> Spanned<&'a str> {
638 self.slice(source).spanned(*self)
639 }
640
641 pub fn spanned_string(&self, source: &str) -> Spanned<String> {
642 self.slice(source).to_string().spanned(*self)
643 }
644
645 pub fn start(&self) -> usize {
647 self.start
648 }
649
650 pub fn end(&self) -> usize {
652 self.end
653 }
654
655 pub fn is_unknown(&self) -> bool {
667 self.start == 0 && self.end == 0
668 }
669
670 pub fn is_closed(&self) -> bool {
688 self.start == self.end
689 }
690
691 pub fn slice<'a>(&self, source: &'a str) -> &'a str {
693 &source[self.start..self.end]
694 }
695}
696
697impl PartialOrd<usize> for Span {
698 fn partial_cmp(&self, other: &usize) -> Option<Ordering> {
699 (self.end - self.start).partial_cmp(other)
700 }
701}
702
703impl PartialEq<usize> for Span {
704 fn eq(&self, other: &usize) -> bool {
705 (self.end - self.start) == *other
706 }
707}
708
709pub trait IntoSpanned {
710 type Output: HasFallibleSpan;
711
712 fn into_spanned(self, span: impl Into<Span>) -> Self::Output;
713}
714
715impl<T: HasFallibleSpan> IntoSpanned for T {
716 type Output = T;
717 fn into_spanned(self, _span: impl Into<Span>) -> Self::Output {
718 self
719 }
720}
721
722pub trait HasSpan {
723 fn span(&self) -> Span;
724}
725
726impl<T, E> HasSpan for Result<T, E>
727where
728 T: HasSpan,
729{
730 fn span(&self) -> Span {
731 match self {
732 Result::Ok(val) => val.span(),
733 Result::Err(_) => Span::unknown(),
734 }
735 }
736}
737
738impl<T> HasSpan for Spanned<T> {
739 fn span(&self) -> Span {
740 self.span
741 }
742}
743
744pub trait HasFallibleSpan {
745 fn maybe_span(&self) -> Option<Span>;
746}
747
748impl HasFallibleSpan for bool {
749 fn maybe_span(&self) -> Option<Span> {
750 None
751 }
752}
753
754impl HasFallibleSpan for () {
755 fn maybe_span(&self) -> Option<Span> {
756 None
757 }
758}
759
760impl<T> HasFallibleSpan for T
761where
762 T: HasSpan,
763{
764 fn maybe_span(&self) -> Option<Span> {
765 Some(HasSpan::span(self))
766 }
767}
768
769impl PrettyDebugWithSource for Option<Span> {
770 fn pretty_debug(&self, source: &str) -> DebugDocBuilder {
771 match self {
772 None => DbgDocBldr::description("no span"),
773 Some(span) => span.pretty_debug(source),
774 }
775 }
776}
777
778impl HasFallibleSpan for Option<Span> {
779 fn maybe_span(&self) -> Option<Span> {
780 *self
781 }
782}
783
784impl PrettyDebugWithSource for Span {
785 fn pretty_debug(&self, source: &str) -> DebugDocBuilder {
786 DbgDocBldr::typed(
787 "span",
788 DbgDocBldr::keyword("for")
789 + DbgDocBldr::space()
790 + DbgDocBldr::description(format!("{:?}", self.slice(source))),
791 )
792 }
793}
794
795impl HasSpan for Span {
796 fn span(&self) -> Span {
797 *self
798 }
799}
800
801impl<T> PrettyDebugWithSource for Option<Spanned<T>>
802where
803 Spanned<T>: PrettyDebugWithSource,
804{
805 fn pretty_debug(&self, source: &str) -> DebugDocBuilder {
806 match self {
807 None => DbgDocBldr::description("nothing"),
808 Some(v) => v.pretty_debug(v.span.slice(source)),
809 }
810 }
811}
812
813impl<T> HasFallibleSpan for Option<Spanned<T>> {
814 fn maybe_span(&self) -> Option<Span> {
815 self.as_ref().map(|value| value.span)
816 }
817}
818
819impl<T> PrettyDebugWithSource for Option<Tagged<T>>
820where
821 Tagged<T>: PrettyDebugWithSource,
822{
823 fn pretty_debug(&self, source: &str) -> DebugDocBuilder {
824 match self {
825 None => DbgDocBldr::description("nothing"),
826 Some(d) => d.pretty_debug(source),
827 }
828 }
829}
830
831impl<T> HasFallibleSpan for Option<Tagged<T>> {
832 fn maybe_span(&self) -> Option<Span> {
833 self.as_ref().map(|value| value.tag.span)
834 }
835}
836
837impl<T> HasSpan for Tagged<T> {
838 fn span(&self) -> Span {
839 self.tag.span
840 }
841}