nu_source/
text.rs

1use serde::{Deserialize, Deserializer, Serialize, Serializer};
2use std::cmp::Ordering;
3use std::hash::Hash;
4use std::hash::Hasher;
5use std::ops::Range;
6
7/// A "Text" is like a string except that it can be cheaply cloned.
8/// You can also "extract" subtexts quite cheaply. You can also deref
9/// an `&Text` into a `&str` for interoperability.
10///
11/// Used to represent the value of an input file.
12#[derive(Clone)]
13pub struct Text {
14    pub text: String,
15    pub start: usize,
16    pub end: usize,
17}
18
19impl Text {
20    /// Modifies this restrict to a subset of its current range.
21    pub fn select(&mut self, range: Range<usize>) {
22        let len = range.end - range.start;
23        let new_start = self.start + range.start;
24        let new_end = new_start + len;
25        assert!(new_end <= self.end);
26
27        self.start = new_start;
28        self.end = new_end;
29    }
30
31    /// Extract a new `Text` that is a subset of an old `Text`
32    /// -- `text.extract(1..3)` is similar to `&foo[1..3]` except that
33    /// it gives back an owned value instead of a borrowed value.
34    pub fn slice(&self, range: Range<usize>) -> Self {
35        let mut result = self.clone();
36        result.select(range);
37        result
38    }
39}
40
41impl From<&str> for Text {
42    fn from(text: &str) -> Self {
43        let end = text.len();
44        Self {
45            text: text.to_string(),
46            start: 0,
47            end,
48        }
49    }
50}
51
52impl AsRef<str> for Text {
53    fn as_ref(&self) -> &str {
54        &*self
55    }
56}
57
58impl From<String> for Text {
59    fn from(text: String) -> Self {
60        let end = text.len();
61        Self {
62            text,
63            start: 0,
64            end,
65        }
66    }
67}
68
69impl From<&Text> for Text {
70    fn from(text: &Text) -> Self {
71        text.clone()
72    }
73}
74
75impl std::borrow::Borrow<str> for Text {
76    fn borrow(&self) -> &str {
77        &*self
78    }
79}
80
81impl std::ops::Deref for Text {
82    type Target = str;
83
84    fn deref(&self) -> &str {
85        &self.text[self.start..self.end]
86    }
87}
88
89impl std::fmt::Display for Text {
90    fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
91        <str as std::fmt::Display>::fmt(self, fmt)
92    }
93}
94
95impl std::fmt::Debug for Text {
96    fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
97        <str as std::fmt::Debug>::fmt(self, fmt)
98    }
99}
100
101impl PartialEq<Text> for Text {
102    fn eq(&self, other: &Text) -> bool {
103        let this: &str = self;
104        let other: &str = other;
105        this == other
106    }
107}
108
109impl Eq for Text {}
110
111impl PartialEq<str> for Text {
112    fn eq(&self, other: &str) -> bool {
113        let this: &str = self;
114        this == other
115    }
116}
117
118impl PartialEq<String> for Text {
119    fn eq(&self, other: &String) -> bool {
120        let this: &str = self;
121        let other: &str = other;
122        this == other
123    }
124}
125
126impl PartialEq<Text> for str {
127    fn eq(&self, other: &Text) -> bool {
128        other == self
129    }
130}
131
132impl PartialEq<Text> for String {
133    fn eq(&self, other: &Text) -> bool {
134        other == self
135    }
136}
137
138impl<T: ?Sized> PartialEq<&T> for Text
139where
140    Text: PartialEq<T>,
141{
142    fn eq(&self, other: &&T) -> bool {
143        self == *other
144    }
145}
146
147impl Hash for Text {
148    fn hash<H: Hasher>(&self, state: &mut H) {
149        <str as Hash>::hash(self, state)
150    }
151}
152
153impl PartialOrd<Text> for Text {
154    fn partial_cmp(&self, other: &Text) -> Option<Ordering> {
155        let this: &str = self;
156        let other: &str = other;
157        this.partial_cmp(other)
158    }
159}
160
161impl Ord for Text {
162    fn cmp(&self, other: &Text) -> Ordering {
163        let this: &str = self;
164        let other: &str = other;
165        this.cmp(other)
166    }
167}
168
169impl PartialOrd<str> for Text {
170    fn partial_cmp(&self, other: &str) -> Option<Ordering> {
171        let this: &str = self;
172        this.partial_cmp(other)
173    }
174}
175
176impl PartialOrd<String> for Text {
177    fn partial_cmp(&self, other: &String) -> Option<Ordering> {
178        let this: &str = self;
179        let other: &str = other;
180        this.partial_cmp(other)
181    }
182}
183
184impl PartialOrd<Text> for str {
185    fn partial_cmp(&self, other: &Text) -> Option<Ordering> {
186        other.partial_cmp(self)
187    }
188}
189
190impl PartialOrd<Text> for String {
191    fn partial_cmp(&self, other: &Text) -> Option<Ordering> {
192        other.partial_cmp(self)
193    }
194}
195
196impl<T: ?Sized> PartialOrd<&T> for Text
197where
198    Text: PartialOrd<T>,
199{
200    fn partial_cmp(&self, other: &&T) -> Option<Ordering> {
201        self.partial_cmp(*other)
202    }
203}
204
205impl Serialize for Text {
206    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
207    where
208        S: Serializer,
209    {
210        self.as_ref().serialize(serializer)
211    }
212}
213
214impl<'de> Deserialize<'de> for Text {
215    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
216    where
217        D: Deserializer<'de>,
218    {
219        Ok(Text::from(String::deserialize(deserializer)?))
220    }
221}