endbasic_std/console/
linebuffer.rs1use std::fmt::Display;
20use std::iter;
21use std::str::Chars;
22
23#[derive(Default, Debug)]
24pub struct LineBuffer {
32 line: String,
33}
34
35impl LineBuffer {
36 pub fn with_capacity(capacity: usize) -> Self {
38 Self { line: String::with_capacity(capacity) }
39 }
40
41 pub fn len(&self) -> usize {
43 self.line.chars().count()
44 }
45
46 pub fn chars(&self) -> Chars {
48 self.line.chars()
49 }
50
51 pub fn end(&self, start_pos: usize) -> String {
54 self.chars().skip(start_pos).collect()
55 }
56
57 pub fn start(&self, end_pos: usize) -> String {
62 self.chars().take(end_pos).collect()
63 }
64
65 pub fn range(&self, start_pos: usize, end_pos: usize) -> String {
67 let count = if start_pos > end_pos { 0 } else { end_pos - start_pos };
68 self.chars().skip(start_pos).take(count).collect()
69 }
70
71 pub fn is_empty(&self) -> bool {
73 self.line.is_empty()
74 }
75
76 pub fn as_bytes(&self) -> &[u8] {
80 self.line.as_bytes()
81 }
82
83 pub fn remove(&mut self, pos: usize) {
87 self.line = self.line.chars().take(pos).chain(self.line.chars().skip(pos + 1)).collect();
88 }
89
90 pub fn insert(&mut self, pos: usize, ch: char) {
95 self.line = self
96 .line
97 .chars()
98 .take(pos)
99 .chain(iter::once(ch))
100 .chain(self.line.chars().skip(pos))
101 .collect();
102 }
103
104 pub fn into_inner(self) -> String {
106 self.line
107 }
108
109 pub fn insert_str(&mut self, pos: usize, s: &str) {
113 self.line = self
114 .line
115 .chars()
116 .take(pos)
117 .chain(s.chars())
118 .chain(self.line.chars().skip(pos))
119 .collect();
120 }
121
122 pub fn push_str(&mut self, s: &LineBuffer) {
124 self.line.push_str(&s.line);
125 }
126
127 pub fn split_off(&mut self, at: usize) -> LineBuffer {
131 let ret = LineBuffer::from(self.line.chars().skip(at).collect::<String>());
132 self.line = self.line.chars().take(at).collect();
133 ret
134 }
135}
136
137impl From<&str> for LineBuffer {
138 fn from(s: &str) -> Self {
139 Self { line: String::from(s) }
140 }
141}
142
143impl From<&String> for LineBuffer {
144 fn from(s: &String) -> Self {
145 Self::from(s.as_str())
146 }
147}
148impl From<String> for LineBuffer {
149 fn from(line: String) -> Self {
150 Self { line }
151 }
152}
153
154impl Display for LineBuffer {
155 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
156 self.line.fmt(f)
157 }
158}
159
160#[cfg(test)]
161mod tests {
162 use super::LineBuffer;
163
164 #[test]
165 fn test_end() {
166 let empty = LineBuffer::default();
167 assert_eq!(empty.end(0), "");
168 assert_eq!(empty.end(1), ""); let hw = LineBuffer::from("Hello, World");
170
171 assert_eq!(hw.end(0), "Hello, World");
172 assert_eq!(hw.end(7), "World");
173 assert_eq!(hw.end(100), "");
174 }
175
176 #[test]
177 fn test_start() {
178 let empty = LineBuffer::default();
179 assert_eq!(empty.start(0), "");
180 assert_eq!(empty.start(1), ""); let hw = LineBuffer::from("Hello, World");
182
183 assert_eq!(hw.start(0), "");
184 assert_eq!(hw.start(7), "Hello, ");
185 assert_eq!(hw.start(100), "Hello, World");
186 }
187
188 #[test]
189 fn test_insert() {
190 let mut buffer = LineBuffer::default();
191 buffer.insert(0, 'c'); buffer.insert(0, 'é'); buffer.insert(1, 'à'); buffer.insert(100, 'd'); assert_eq!(buffer.into_inner(), "éàcd");
199 }
200
201 #[test]
202 fn test_remove() {
203 let mut empty = LineBuffer::default();
204 empty.remove(0);
205 empty.remove(5);
206 assert_eq!(empty.into_inner(), "");
207
208 let mut hello = LineBuffer::from("Hello");
209 hello.remove(100); hello.remove(1); assert_eq!(hello.into_inner(), "Hllo");
212 }
213
214 #[test]
215 fn test_insert_str() {
216 let mut buffer = LineBuffer::default();
217 buffer.insert_str(0, "Hello");
218 assert_eq!(buffer.end(0), "Hello");
219 buffer.insert_str(100, "World"); assert_eq!(buffer.end(0), "HelloWorld");
221 buffer.insert_str(5, ", ");
222 assert_eq!(buffer.end(0), "Hello, World");
223 }
224
225 #[test]
226 fn test_range() {
227 let mut buffer = LineBuffer::default();
228
229 assert_eq!(buffer.range(0, 0), "");
230 assert_eq!(buffer.range(0, 10), "");
231 assert_eq!(buffer.range(0, 10), "");
232 assert_eq!(buffer.range(10, 0), ""); buffer.insert_str(0, "Hello, World");
235 assert_eq!(buffer.range(0, 5), "Hello");
236 assert_eq!(buffer.range(7, 10), "Wor");
237 assert_eq!(buffer.range(7, 100), "World");
238 assert_eq!(buffer.range(10, 0), ""); }
240
241 #[test]
242 fn test_is_empty() {
243 assert!(LineBuffer::default().is_empty());
244 assert!(LineBuffer::from("").is_empty());
245 assert!(!LineBuffer::from("This is not empty").is_empty());
246 }
247
248 #[test]
249 fn test_split_off() {
250 let mut buffer = LineBuffer::from("Hello, World");
251 let world = buffer.split_off(7);
252 assert_eq!(buffer.into_inner(), "Hello, ");
253 assert_eq!(world.into_inner(), "World");
254 }
255}