reifydb_type/fragment/
owned.rs1use std::{
5 cmp::Ordering,
6 fmt::{Display, Formatter},
7};
8
9use serde::{Deserialize, Serialize};
10
11use super::{StatementColumn, StatementLine};
12
13#[derive(Debug, Clone, PartialEq, Hash, Serialize, Deserialize)]
15pub enum OwnedFragment {
16 None,
18
19 Statement {
21 text: String,
22 line: StatementLine,
23 column: StatementColumn,
24 },
25
26 Internal {
28 text: String,
29 },
30}
31
32impl OwnedFragment {
33 pub fn text(&self) -> &str {
35 match self {
36 OwnedFragment::None => "",
37 OwnedFragment::Statement {
38 text,
39 ..
40 }
41 | OwnedFragment::Internal {
42 text,
43 ..
44 } => text,
45 }
46 }
47
48 pub fn line(&self) -> StatementLine {
50 match self {
51 OwnedFragment::Statement {
52 line,
53 ..
54 } => *line,
55 _ => StatementLine(1),
56 }
57 }
58
59 pub fn column(&self) -> StatementColumn {
61 match self {
62 OwnedFragment::Statement {
63 column,
64 ..
65 } => *column,
66 _ => StatementColumn(0),
67 }
68 }
69
70 pub fn into_owned(self) -> OwnedFragment {
72 self
73 }
74
75 pub fn sub_fragment(&self, offset: usize, length: usize) -> OwnedFragment {
78 let text = self.text();
79 let end = std::cmp::min(offset + length, text.len());
80 let sub_text = if offset < text.len() {
81 &text[offset..end]
82 } else {
83 ""
84 };
85
86 match self {
87 OwnedFragment::None => OwnedFragment::None,
88 OwnedFragment::Statement {
89 line,
90 column,
91 ..
92 } => OwnedFragment::Statement {
93 text: sub_text.to_string(),
94 line: *line,
95 column: StatementColumn(column.0 + offset as u32),
96 },
97 OwnedFragment::Internal {
98 ..
99 } => OwnedFragment::Internal {
100 text: sub_text.to_string(),
101 },
102 }
103 }
104}
105
106impl OwnedFragment {
107 pub fn internal(text: impl Into<String>) -> Self {
110 OwnedFragment::Internal {
111 text: text.into(),
112 }
113 }
114
115 pub fn testing(text: impl Into<String>) -> Self {
118 OwnedFragment::Statement {
119 text: text.into(),
120 line: StatementLine(1),
121 column: StatementColumn(0),
122 }
123 }
124
125 pub fn testing_empty() -> Self {
127 Self::testing("")
128 }
129
130 pub fn merge_all(fragments: impl IntoIterator<Item = OwnedFragment>) -> OwnedFragment {
133 let mut fragments: Vec<OwnedFragment> = fragments.into_iter().collect();
134 assert!(!fragments.is_empty());
135
136 fragments.sort();
137
138 let first = fragments.first().unwrap();
139
140 let mut text = String::with_capacity(fragments.iter().map(|f| f.text().len()).sum());
141 for fragment in &fragments {
142 text.push_str(fragment.text());
143 }
144
145 match first {
146 OwnedFragment::None => OwnedFragment::None,
147 OwnedFragment::Statement {
148 line,
149 column,
150 ..
151 } => OwnedFragment::Statement {
152 text,
153 line: *line,
154 column: *column,
155 },
156 OwnedFragment::Internal {
157 ..
158 } => OwnedFragment::Internal {
159 text,
160 },
161 }
162 }
163
164 pub fn fragment(&self) -> &str {
166 self.text()
167 }
168}
169
170impl Default for OwnedFragment {
171 fn default() -> Self {
172 OwnedFragment::None
173 }
174}
175
176impl AsRef<str> for OwnedFragment {
177 fn as_ref(&self) -> &str {
178 self.text()
179 }
180}
181
182impl Display for OwnedFragment {
183 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
184 Display::fmt(self.text(), f)
185 }
186}
187
188impl PartialOrd for OwnedFragment {
189 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
190 Some(self.cmp(other))
191 }
192}
193
194impl Ord for OwnedFragment {
195 fn cmp(&self, other: &Self) -> Ordering {
196 self.column().cmp(&other.column()).then(self.line().cmp(&other.line()))
197 }
198}
199
200impl Eq for OwnedFragment {}