use serde::{Deserialize, Deserializer, Serialize, Serializer}; use std::cmp::Ordering; use std::hash::Hash; use std::hash::Hasher; use std::ops::Range; /// A "Text" is like a string except that it can be cheaply cloned. /// You can also "extract" subtexts quite cheaply. You can also deref /// an `&Text` into a `&str` for interoperability. /// /// Used to represent the value of an input file. #[derive(Clone)] pub struct Text { pub text: String, pub start: usize, pub end: usize, } impl Text { /// Modifies this restrict to a subset of its current range. pub fn select(&mut self, range: Range) { let len = range.end - range.start; let new_start = self.start + range.start; let new_end = new_start + len; assert!(new_end <= self.end); self.start = new_start; self.end = new_end; } /// Extract a new `Text` that is a subset of an old `Text` /// -- `text.extract(1..3)` is similar to `&foo[1..3]` except that /// it gives back an owned value instead of a borrowed value. pub fn slice(&self, range: Range) -> Self { let mut result = self.clone(); result.select(range); result } } impl From<&str> for Text { fn from(text: &str) -> Self { let end = text.len(); Self { text: text.to_string(), start: 0, end, } } } impl AsRef for Text { fn as_ref(&self) -> &str { &*self } } impl From for Text { fn from(text: String) -> Self { let end = text.len(); Self { text, start: 0, end, } } } impl From<&Text> for Text { fn from(text: &Text) -> Self { text.clone() } } impl std::borrow::Borrow for Text { fn borrow(&self) -> &str { &*self } } impl std::ops::Deref for Text { type Target = str; fn deref(&self) -> &str { &self.text[self.start..self.end] } } impl std::fmt::Display for Text { fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { ::fmt(self, fmt) } } impl std::fmt::Debug for Text { fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { ::fmt(self, fmt) } } impl PartialEq for Text { fn eq(&self, other: &Text) -> bool { let this: &str = self; let other: &str = other; this == other } } impl Eq for Text {} impl PartialEq for Text { fn eq(&self, other: &str) -> bool { let this: &str = self; this == other } } impl PartialEq for Text { fn eq(&self, other: &String) -> bool { let this: &str = self; let other: &str = other; this == other } } impl PartialEq for str { fn eq(&self, other: &Text) -> bool { other == self } } impl PartialEq for String { fn eq(&self, other: &Text) -> bool { other == self } } impl PartialEq<&T> for Text where Text: PartialEq, { fn eq(&self, other: &&T) -> bool { self == *other } } impl Hash for Text { fn hash(&self, state: &mut H) { ::hash(self, state) } } impl PartialOrd for Text { fn partial_cmp(&self, other: &Text) -> Option { let this: &str = self; let other: &str = other; this.partial_cmp(other) } } impl Ord for Text { fn cmp(&self, other: &Text) -> Ordering { let this: &str = self; let other: &str = other; this.cmp(other) } } impl PartialOrd for Text { fn partial_cmp(&self, other: &str) -> Option { let this: &str = self; this.partial_cmp(other) } } impl PartialOrd for Text { fn partial_cmp(&self, other: &String) -> Option { let this: &str = self; let other: &str = other; this.partial_cmp(other) } } impl PartialOrd for str { fn partial_cmp(&self, other: &Text) -> Option { other.partial_cmp(self) } } impl PartialOrd for String { fn partial_cmp(&self, other: &Text) -> Option { other.partial_cmp(self) } } impl PartialOrd<&T> for Text where Text: PartialOrd, { fn partial_cmp(&self, other: &&T) -> Option { self.partial_cmp(*other) } } impl Serialize for Text { fn serialize(&self, serializer: S) -> Result where S: Serializer, { self.as_ref().serialize(serializer) } } impl<'de> Deserialize<'de> for Text { fn deserialize(deserializer: D) -> Result where D: Deserializer<'de>, { Ok(Text::from(String::deserialize(deserializer)?)) } }