flams_utils/sourcerefs/
ranges.rs1use crate::sourcerefs::OffsetPosition;
2
3use super::StringPosition;
4
5#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
7#[derive(Debug, Clone, Copy, PartialEq, Eq, Default, Hash)]
8pub struct StringRange<P: StringPosition> {
9 pub start: P,
10 pub end: P,
11}
12impl<P: StringPosition> std::fmt::Display for StringRange<P> {
13 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
14 write!(f, "{}--{}", self.start, self.end)
15 }
16}
17
18impl<P: StringPosition> std::ops::Sub<P> for StringRange<P> {
19 type Output = Self;
20 fn sub(self, rhs: P) -> Self::Output {
21 Self {
22 start: self.start.sub(rhs),
23 end: self.end.sub(rhs),
24 }
25 }
26}
27
28impl<P: StringPosition> std::ops::SubAssign<P> for StringRange<P> {
29 fn sub_assign(&mut self, rhs: P) {
30 self.start.sub_assign(rhs);
31 self.end.sub_assign(rhs);
32 }
33}
34
35impl<P: StringPosition> StringRange<P> {
36 #[inline]
37 pub fn contains(self, pos: P) -> bool {
38 self.start <= pos && pos <= self.end
39 }
40}
41
42#[allow(clippy::inline_always)]
43impl<P: StringPosition> PartialEq<P> for StringRange<P> {
44 #[inline(always)]
45 fn eq(&self, other: &P) -> bool {
46 self.contains(*other)
47 }
48}
49impl<P: StringPosition> PartialOrd<P> for StringRange<P> {
50 fn partial_cmp(&self, other: &P) -> Option<std::cmp::Ordering> {
51 if self.end <= *other {
52 Some(std::cmp::Ordering::Less)
53 } else if self.start >= *other {
54 Some(std::cmp::Ordering::Greater)
55 } else if self.start == self.end && self.start == *other {
56 Some(std::cmp::Ordering::Equal)
57 } else {
58 None
59 }
60 }
61}
62
63impl<P: StringPosition> std::ops::Index<StringRange<P>> for str {
66 type Output = str;
67 fn index(&self, index: StringRange<P>) -> &Self::Output {
68 let StringRange { start, end } = index.into_other::<crate::sourcerefs::ByteOffset>(self);
69 &self[start.0..end.0]
70 }
71}
72
73impl<P: StringPosition> StringRange<P> {
74 #[allow(clippy::inline_always)]
75 #[inline(always)]
76 #[must_use]
77 pub fn from_other<O: StringPosition>(other: StringRange<O>, source: &str) -> Self {
78 let mut conv = P::from_many(source);
79 Self {
80 start: conv.next(other.start),
81 end: conv.next(other.end),
82 }
83 }
84 #[allow(clippy::inline_always)]
85 #[inline(always)]
86 #[must_use]
87 pub fn into_other<O: StringPosition>(self, source: &str) -> StringRange<O> {
88 StringRange::from_other(self, source)
89 }
90}
91
92impl<P: StringPosition> StringRange<P> {
93 #[must_use]
94 pub const fn until(self, rhs: P) -> Self {
95 Self {
96 start: self.start,
97 end: rhs,
98 }
99 }
100}