makepad_draw/text/
substr.rs

1use std::{
2    fmt,
3    hash::{Hash, Hasher},
4    ops::{Deref, RangeBounds},
5    rc::Rc,
6};
7
8#[derive(Clone)]
9pub struct Substr {
10    parent: Rc<str>,
11    start: usize,
12    end: usize,
13}
14
15impl Substr {
16    pub fn split_at(self, index: usize) -> (Substr, Substr) {
17        (
18            Self {
19                parent: self.parent.clone(),
20                start: self.start,
21                end: index,
22            },
23            Self {
24                parent: self.parent,
25                start: index,
26                end: self.end,
27            },
28        )
29    }
30
31    pub fn parent(&self) -> &Rc<str> {
32        &self.parent
33    }
34
35    pub fn start_in_parent(&self) -> usize {
36        self.start
37    }
38
39    pub fn end_in_parent(&self) -> usize {
40        self.end
41    }
42
43    pub fn as_str(&self) -> &str {
44        &self.parent[self.start..self.end]
45    }
46
47    pub fn shallow_eq(&self, other: &Self) -> bool {
48        if !Rc::ptr_eq(&self.parent, &other.parent) {
49            return false;
50        }
51        if self.start != other.start {
52            return false;
53        }
54        if self.end != other.end {
55            return false;
56        }
57        true
58    }
59
60    pub fn substr(&self, range: impl RangeBounds<usize>) -> Substr {
61        use std::ops::Bound;
62
63        let start = match range.start_bound() {
64            Bound::Included(&start) => start,
65            Bound::Excluded(&start) => start + 1,
66            Bound::Unbounded => 0,
67        };
68        let end = match range.end_bound() {
69            Bound::Included(&end) => end + 1,
70            Bound::Excluded(&end) => end,
71            Bound::Unbounded => self.len(),
72        };
73        assert!(start <= end);
74        assert!(end <= self.len());
75        Substr {
76            parent: self.parent.clone(),
77            start: self.start + start,
78            end: self.start + end,
79        }
80    }
81}
82
83impl fmt::Debug for Substr {
84    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
85        write!(f, "{:?}", self.as_str())
86    }
87}
88
89impl Deref for Substr {
90    type Target = str;
91
92    fn deref(&self) -> &Self::Target {
93        self.as_str()
94    }
95}
96
97impl From<String> for Substr {
98    fn from(string: String) -> Self {
99        string.as_str().into()
100    }
101}
102
103impl From<&String> for Substr {
104    fn from(string: &String) -> Self {
105        string.as_str().into()
106    }
107}
108
109impl From<&str> for Substr {
110    fn from(string: &str) -> Self {
111        Rc::<str>::from(string).into()
112    }
113}
114
115impl From<Rc<str>> for Substr {
116    fn from(string: Rc<str>) -> Self {
117        let len = string.len();
118        Self {
119            parent: string,
120            start: 0,
121            end: len,
122        }
123    }
124}
125
126impl Eq for Substr {}
127
128impl Hash for Substr {
129    fn hash<H>(&self, hasher: &mut H)
130    where
131        H: Hasher,
132    {
133        self.as_str().hash(hasher)
134    }
135}
136
137impl Ord for Substr {
138    fn cmp(&self, other: &Self) -> std::cmp::Ordering {
139        self.as_str().cmp(other.as_str())
140    }
141}
142
143impl PartialEq for Substr {
144    fn eq(&self, other: &Self) -> bool {
145        self.shallow_eq(other) || self.as_str().eq(other.as_str())
146    }
147}
148
149impl PartialOrd for Substr {
150    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
151        self.as_str().partial_cmp(other.as_str())
152    }
153}