Mountain/Environment/Utility/
TextEdit.rs1#![allow(unused_variables, dead_code, unused_imports)]
2
3pub(crate) fn ComputeLineOffsets(Source:&str) -> Vec<usize> {
12 let mut Offsets = Vec::with_capacity(Source.len() / 40 + 1);
13
14 Offsets.push(0);
15
16 for (Index, Byte) in Source.bytes().enumerate() {
17 if Byte == b'\n' {
18 Offsets.push(Index + 1);
19 }
20 }
21
22 Offsets
23}
24
25pub(crate) fn LinePosToOffset(LineOffsets:&[usize], Source:&str, Line:usize, Character:usize) -> usize {
30 if Line >= LineOffsets.len() {
31 return Source.len();
32 }
33
34 let LineStart = LineOffsets[Line];
35
36 let LineEnd = if Line + 1 < LineOffsets.len() {
37 LineOffsets[Line + 1].saturating_sub(1)
38 } else {
39 Source.len()
40 };
41
42 let LineText = &Source[LineStart..LineEnd.min(Source.len())];
43
44 let mut Utf16Count:usize = 0;
45
46 for (ByteOffset, Char) in LineText.char_indices() {
47 if Utf16Count >= Character {
48 return LineStart + ByteOffset;
49 }
50
51 Utf16Count += Char.len_utf16();
52 }
53
54 LineStart + LineText.len()
55}
56
57pub(crate) fn percent_decode(Input:&str) -> String {
60 let mut Out = String::with_capacity(Input.len());
61
62 let mut Bytes = Input.as_bytes().iter().peekable();
63
64 while let Some(&Byte) = Bytes.next() {
65 if Byte == b'%' {
66 let H = Bytes.next().copied();
67
68 let L = Bytes.next().copied();
69
70 if let (Some(H), Some(L)) = (H, L) {
71 if let (Some(Hi), Some(Lo)) = (hex_digit(H), hex_digit(L)) {
72 Out.push((Hi * 16 + Lo) as char);
73
74 continue;
75 }
76
77 Out.push('%');
78
79 Out.push(H as char);
80
81 Out.push(L as char);
82
83 continue;
84 }
85
86 Out.push('%');
87 } else {
88 Out.push(Byte as char);
89 }
90 }
91
92 Out
93}
94
95fn hex_digit(Byte:u8) -> Option<u8> {
96 match Byte {
97 b'0'..=b'9' => Some(Byte - b'0'),
98
99 b'a'..=b'f' => Some(Byte - b'a' + 10),
100
101 b'A'..=b'F' => Some(Byte - b'A' + 10),
102
103 _ => None,
104 }
105}