bms_rs/bms/command/
mixin.rs1use std::ops::Range;
7
8#[derive(Debug, Clone, PartialEq, Eq, Hash)]
10#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
11pub struct SourceRangeMixin<T> {
12 content: T,
14 range: Range<usize>,
16}
17
18impl<T> SourceRangeMixin<T> {
19 pub const fn new(content: T, range: Range<usize>) -> Self {
21 Self { content, range }
22 }
23
24 pub const fn new_with_start_end(content: T, start: usize, end: usize) -> Self {
26 Self::new(content, start..end)
27 }
28
29 pub const fn content(&self) -> &T {
31 &self.content
32 }
33
34 pub const fn content_mut(&mut self) -> &mut T {
36 &mut self.content
37 }
38
39 pub fn into_content(self) -> T {
41 self.content
42 }
43
44 pub const fn start(&self) -> usize {
46 self.range.start
47 }
48
49 pub const fn end(&self) -> usize {
51 self.range.end
52 }
53
54 pub const fn range(&self) -> &Range<usize> {
56 &self.range
57 }
58
59 pub const fn as_span(&self) -> (usize, usize) {
61 (self.range.start, self.range.end)
62 }
63
64 pub const fn len(&self) -> usize {
66 self.range.end.saturating_sub(self.range.start)
67 }
68
69 pub const fn is_empty(&self) -> bool {
71 self.len() == 0
72 }
73}
74
75impl<'a, T> SourceRangeMixin<T> {
76 pub fn inner_ref(&'a self) -> SourceRangeMixin<&'a T> {
78 let content = &self.content;
79 SourceRangeMixin::new(content, self.range.clone())
80 }
81}
82
83impl<T> SourceRangeMixin<T> {
84 pub fn map<U, F>(self, f: F) -> SourceRangeMixin<U>
86 where
87 F: FnOnce(T) -> U,
88 {
89 SourceRangeMixin::new(f(self.content), self.range)
90 }
91}
92
93impl<T: std::fmt::Display> std::fmt::Display for SourceRangeMixin<T> {
94 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
95 write!(
96 f,
97 "{} at indices [{}, {})",
98 self.content, self.range.start, self.range.end
99 )
100 }
101}
102
103impl<T> From<(T, Range<usize>)> for SourceRangeMixin<T> {
104 fn from(value: (T, Range<usize>)) -> Self {
105 Self::new(value.0, value.1)
106 }
107}
108
109impl<T> From<(T, usize, usize)> for SourceRangeMixin<T> {
110 fn from(value: (T, usize, usize)) -> Self {
111 Self::new_with_start_end(value.0, value.1, value.2)
112 }
113}
114
115impl<T> From<SourceRangeMixin<T>> for (T, Range<usize>) {
116 fn from(value: SourceRangeMixin<T>) -> Self {
117 (value.content, value.range)
118 }
119}
120
121impl<T> From<SourceRangeMixin<T>> for (T, usize, usize) {
122 fn from(value: SourceRangeMixin<T>) -> Self {
123 (value.content, value.range.start, value.range.end)
124 }
125}
126
127impl From<Range<usize>> for SourceRangeMixin<()> {
129 fn from(value: Range<usize>) -> Self {
130 Self::new((), value)
131 }
132}
133
134impl From<(usize, usize)> for SourceRangeMixin<()> {
135 fn from(value: (usize, usize)) -> Self {
136 Self::new_with_start_end((), value.0, value.1)
137 }
138}
139
140impl<T: std::error::Error + 'static> std::error::Error for SourceRangeMixin<T> {
141 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
142 Some(&self.content)
143 }
144}
145
146pub trait SourceRangeMixinExt {
148 fn into_wrapper<W>(self, wrapper: &SourceRangeMixin<W>) -> SourceRangeMixin<Self>
150 where
151 Self: Sized,
152 {
153 SourceRangeMixin::new(self, wrapper.range.clone())
154 }
155
156 fn into_wrapper_range(self, range: Range<usize>) -> SourceRangeMixin<Self>
158 where
159 Self: Sized,
160 {
161 SourceRangeMixin::new(self, range)
162 }
163
164 fn into_wrapper_span(self, span: (usize, usize)) -> SourceRangeMixin<Self>
166 where
167 Self: Sized,
168 {
169 SourceRangeMixin::new_with_start_end(self, span.0, span.1)
170 }
171}
172
173impl<T> SourceRangeMixinExt for T {}