1use crate::{LinearPosition, LinearSpan};
2
3#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
5#[derive(Clone, Debug)]
6pub struct SourceText {
7 source_text: Vec<u16>,
8}
9
10impl SourceText {
11 #[must_use]
13 pub fn with_capacity(capacity: usize) -> Self {
14 Self {
15 source_text: Vec::with_capacity(capacity),
16 }
17 }
18
19 #[must_use]
21 pub fn cur_linear_position(&self) -> LinearPosition {
22 LinearPosition::new(self.source_text.len())
23 }
24
25 #[must_use]
27 pub fn get_code_points_from_pos(&self, pos: LinearPosition) -> &[u16] {
28 &self.source_text[pos.pos()..]
29 }
30
31 #[must_use]
33 pub fn get_code_points_from_span(&self, span: LinearSpan) -> &[u16] {
34 &self.source_text[span.start().pos()..span.end().pos()]
35 }
36
37 #[inline]
39 pub fn remove_last_code_point(&mut self) {
40 self.source_text.pop();
41 }
42
43 #[inline]
49 pub fn collect_code_point(&mut self, cp: u32) {
50 if let Ok(cu) = cp.try_into() {
51 self.push(cu);
52 return;
53 }
54 let cp = cp - 0x10000;
55 let cu1 = (cp / 0x400 + 0xD800)
56 .try_into()
57 .expect("Invalid code point");
58 let cu2 = (cp % 0x400 + 0xDC00)
59 .try_into()
60 .expect("Invalid code point");
61 self.push(cu1);
62 self.push(cu2);
63 }
64
65 #[inline]
66 fn push(&mut self, cp: u16) {
67 self.source_text.push(cp);
68 }
69}
70
71const DEFAULT_CAPACITY: usize = 4 * 1024;
72
73impl Default for SourceText {
74 fn default() -> Self {
75 Self::with_capacity(DEFAULT_CAPACITY)
76 }
77}