1use crate::value::parse;
7use core::ops::Range;
8use core::str::FromStr;
9use serde::Deserialize;
10use serde::Serialize;
11
12#[derive(Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
13#[derive(Serialize, Deserialize)]
14pub struct Span(pub(crate) usize, pub(crate) usize);
15
16impl core::fmt::Debug for Span {
17 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
18 write!(f, "Span({}, {})", self.0, self.1)
19 }
20}
21
22impl core::fmt::Display for Span {
23 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
24 write!(f, "{}-{}", self.0, self.1)
25 }
26}
27
28impl FromStr for Span {
29 type Err = String;
30
31 fn from_str(value: &str) -> Result<Self, Self::Err> {
32 value
33 .split_once('-')
34 .and_then(|(lo, hi)| parse::usize(lo.as_bytes()).map(|lo| (lo, hi)).ok())
35 .and_then(|(lo, hi)| parse::usize(hi.as_bytes()).map(|hi| (lo, hi)).ok())
36 .map(|(lo, hi)| Span::new(lo, hi))
37 .ok_or_else(|| value.to_string())
38 }
39}
40
41impl From<&[u8]> for Span {
42 fn from(value: &[u8]) -> Self {
43 Self::new(0, value.len())
44 }
45}
46
47impl From<usize> for Span {
48 fn from(value: usize) -> Self {
49 Self::new(0, value)
50 }
51}
52
53impl From<Range<usize>> for Span {
54 fn from(value: Range<usize>) -> Self {
55 Self::new(value.start, value.end)
56 }
57}
58
59impl Span {
60 pub fn new(lo: usize, hi: usize) -> Self {
61 if lo > hi {
62 Self::default()
63 } else {
64 Self(lo, hi)
65 }
66 }
67
68 pub fn lo(&self) -> usize {
69 self.0
70 }
71
72 pub fn hi(&self) -> usize {
73 self.1
74 }
75
76 pub fn len(&self) -> usize {
77 self.1.saturating_sub(self.0)
78 }
79
80 pub fn is_empty(&self) -> bool {
81 self.0 == self.1
82 }
83
84 pub fn with_lo(self, lo: usize) -> Self {
85 Self(lo, self.1)
86 }
87
88 pub fn with_hi(self, hi: usize) -> Self {
89 Self(self.0, hi)
90 }
91
92 pub fn into_lo(self) -> Self {
93 Self(self.0, self.0)
94 }
95
96 pub fn into_hi(self) -> Self {
97 Self(self.1, self.1)
98 }
99
100 pub fn read<'a, T: Default>(&self, list: &'a [T]) -> &'a [T] {
101 list.get(self.range()).unwrap_or_default()
102 }
103
104 pub fn range(self) -> Range<usize> {
105 self.0..self.1
106 }
107
108 pub fn lo_range(self) -> Range<usize> {
109 self.0..self.0
110 }
111
112 pub fn hi_range(self) -> Range<usize> {
113 self.1..self.1
114 }
115
116 pub fn contains(self, other: Span) -> bool {
117 self.0 <= other.0 && self.1 >= other.1
118 }
119
120 #[doc(hidden)]
121 pub fn diff(self, diff: isize) -> Self {
122 Span::new(self.0, self.1.saturating_add_signed(diff))
123 }
124
125 #[doc(hidden)]
126 pub fn expand(self, left: usize, right: usize) -> Self {
127 Span::new(self.0.saturating_sub(left), self.1.saturating_add(right))
128 }
129
130 #[doc(hidden)]
131 pub fn contract(self, left: usize, right: usize) -> Self {
132 Span::new(self.0.saturating_add(left), self.1.saturating_sub(right))
133 }
134
135 #[doc(hidden)]
136 pub(crate) fn zoom(self, span: Span) -> Self {
137 Span::new(
138 self.0.saturating_add(span.lo()),
139 self.0.saturating_add(span.hi()),
140 )
141 }
142
143 #[doc(hidden)]
144 pub fn left(self, span: Span) -> Self {
145 Span::new(
146 self.0.saturating_sub(span.lo()),
147 self.1.saturating_sub(span.lo()),
148 )
149 }
150
151 #[doc(hidden)]
152 pub fn right(self, span: Span) -> Self {
153 Span::new(
154 self.0.saturating_add(span.lo()),
155 self.1.saturating_add(span.lo()),
156 )
157 }
158}