makepad_draw/text/
substr.rs1use 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}