Vendor things
This commit is contained in:
parent
5deceec006
commit
977e3c17e5
19434 changed files with 10682014 additions and 0 deletions
1
third-party/vendor/text_lines/.cargo-checksum.json
vendored
Normal file
1
third-party/vendor/text_lines/.cargo-checksum.json
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
{"files":{"Cargo.toml":"2863d70e91d11fb3170fd59e931ddf5f3a3f9e97c7f40ed9438adb433cd70aed","LICENSE":"44535889267702111e0156318d664b454dacab11ca486856e80ac0df28635cce","README.md":"ab1e3843cdf62eb9966927d2f9ffb1e65110d7b30222b677748cede0628ba847","src/lib.rs":"82bd5e4707b1c4ed0693b839ca97e07c1d252e79a4af4d471f659ea1a3d0c7ad"},"package":"7fd5828de7deaa782e1dd713006ae96b3bee32d3279b79eb67ecf8072c059bcf"}
|
||||
25
third-party/vendor/text_lines/Cargo.toml
vendored
Normal file
25
third-party/vendor/text_lines/Cargo.toml
vendored
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
|
||||
#
|
||||
# When uploading crates to the registry Cargo will automatically
|
||||
# "normalize" Cargo.toml files for maximal compatibility
|
||||
# with all versions of Cargo and also rewrite `path` dependencies
|
||||
# to registry (e.g., crates.io) dependencies.
|
||||
#
|
||||
# If you are reading this file be aware that the original Cargo.toml
|
||||
# will likely look very different (and much more reasonable).
|
||||
# See Cargo.toml.orig for the original contents.
|
||||
|
||||
[package]
|
||||
edition = "2018"
|
||||
name = "text_lines"
|
||||
version = "0.6.0"
|
||||
authors = ["David Sherret <dsherret@gmail.com>"]
|
||||
description = "Information about lines of text in a string."
|
||||
license = "MIT"
|
||||
[dependencies.serde]
|
||||
version = "1"
|
||||
features = ["derive"]
|
||||
optional = true
|
||||
|
||||
[features]
|
||||
serialization = ["serde"]
|
||||
21
third-party/vendor/text_lines/LICENSE
vendored
Normal file
21
third-party/vendor/text_lines/LICENSE
vendored
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2021 David Sherret
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
20
third-party/vendor/text_lines/README.md
vendored
Normal file
20
third-party/vendor/text_lines/README.md
vendored
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
# text_lines
|
||||
|
||||
[](https://crates.io/crates/text_lines)
|
||||
|
||||
Information about lines of text in a string.
|
||||
|
||||
```rust
|
||||
use text_lines::TextLines;
|
||||
|
||||
let text = "Line 1\n\tLine 2";
|
||||
let info = TextLines::new(&text); // defaults to an indent width of 4
|
||||
|
||||
let line_index = info.line_index(9); // 1
|
||||
let line_and_column = info.line_and_column_index(9); // 1, 2
|
||||
let byte_index = info.byte_index(&line_and_column); // 9
|
||||
let line_and_column_display = info.line_and_column_display(9); // 2, 6
|
||||
|
||||
let info = TextLines::with_indent_width(&text, 2);
|
||||
let line_and_column_display = info.line_and_column_display(9); // 2, 4
|
||||
```
|
||||
708
third-party/vendor/text_lines/src/lib.rs
vendored
Normal file
708
third-party/vendor/text_lines/src/lib.rs
vendored
Normal file
|
|
@ -0,0 +1,708 @@
|
|||
const BOM_CHAR: char = '\u{FEFF}';
|
||||
|
||||
#[cfg_attr(
|
||||
feature = "serialization",
|
||||
derive(serde::Serialize, serde::Deserialize)
|
||||
)]
|
||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||
pub struct LineAndColumnIndex {
|
||||
/// The zero-indexed line index.
|
||||
pub line_index: usize,
|
||||
/// The character index relative to the start of the line.
|
||||
pub column_index: usize,
|
||||
}
|
||||
|
||||
#[cfg_attr(
|
||||
feature = "serialization",
|
||||
derive(serde::Serialize, serde::Deserialize)
|
||||
)]
|
||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||
pub struct LineAndColumnDisplay {
|
||||
/// The 1-indexed line number for display purposes.
|
||||
pub line_number: usize,
|
||||
/// The 1-indexed column number based on the indent width.
|
||||
pub column_number: usize,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct MultiByteCharInfo {
|
||||
/// The byte index in the entire file.
|
||||
byte_index: usize,
|
||||
/// The character index on the current line.
|
||||
line_char_index: usize,
|
||||
length: usize,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct TextLine {
|
||||
start_index: usize,
|
||||
end_index: usize,
|
||||
multi_byte_chars: Vec<MultiByteCharInfo>,
|
||||
tab_chars: Vec<usize>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct TextLines {
|
||||
lines: Vec<TextLine>,
|
||||
indent_width: usize,
|
||||
}
|
||||
|
||||
impl TextLines {
|
||||
/// Creates a new `TextLines` with the specified text and default
|
||||
/// indent width of 4.
|
||||
pub fn new(text: &str) -> Self {
|
||||
TextLines::with_indent_width(text, 4)
|
||||
}
|
||||
|
||||
/// Creates a new `TextLines` with the specified text and indent width.
|
||||
/// The indent width sets the width of a tab character when getting
|
||||
/// the display column.
|
||||
pub fn with_indent_width(text: &str, indent_width: usize) -> Self {
|
||||
let mut last_line_start = if text.starts_with(BOM_CHAR) {
|
||||
BOM_CHAR.len_utf8()
|
||||
} else {
|
||||
0
|
||||
};
|
||||
let mut multi_byte_chars = Vec::new();
|
||||
let mut tab_chars = Vec::new();
|
||||
let mut lines = Vec::new();
|
||||
let mut was_last_slash_r = false;
|
||||
let mut line_char_index = 0;
|
||||
for (char_index, (byte_index, c)) in text.char_indices().enumerate() {
|
||||
if byte_index == 0 && c == BOM_CHAR {
|
||||
continue;
|
||||
}
|
||||
|
||||
if c == '\n' {
|
||||
lines.push(TextLine {
|
||||
start_index: last_line_start,
|
||||
end_index: if was_last_slash_r {
|
||||
byte_index - 1
|
||||
} else {
|
||||
byte_index
|
||||
},
|
||||
multi_byte_chars: std::mem::take(&mut multi_byte_chars),
|
||||
tab_chars: std::mem::take(&mut tab_chars),
|
||||
});
|
||||
last_line_start = byte_index + 1;
|
||||
line_char_index = char_index + 1;
|
||||
} else if c == '\t' {
|
||||
tab_chars.push(byte_index);
|
||||
} else if c.len_utf8() > 1 {
|
||||
multi_byte_chars.push(MultiByteCharInfo {
|
||||
line_char_index: char_index - line_char_index,
|
||||
byte_index,
|
||||
length: c.len_utf8(),
|
||||
});
|
||||
}
|
||||
was_last_slash_r = c == '\r';
|
||||
}
|
||||
|
||||
lines.push(TextLine {
|
||||
start_index: last_line_start,
|
||||
end_index: text.len(),
|
||||
multi_byte_chars,
|
||||
tab_chars,
|
||||
});
|
||||
|
||||
Self {
|
||||
lines,
|
||||
indent_width,
|
||||
}
|
||||
}
|
||||
|
||||
/// Gets the number of lines in the text.
|
||||
pub fn lines_count(&self) -> usize {
|
||||
self.lines.len()
|
||||
}
|
||||
|
||||
/// Gets the text length in bytes.
|
||||
pub fn text_length(&self) -> usize {
|
||||
self.lines.last().unwrap().end_index
|
||||
}
|
||||
|
||||
/// Gets the line index from a byte index.
|
||||
/// Note that if you provide the middle byte index of a \r\n newline
|
||||
/// then it will return the index of the preceding line.
|
||||
pub fn line_index(&self, byte_index: usize) -> usize {
|
||||
self.assert_valid_byte_index(byte_index);
|
||||
|
||||
match self
|
||||
.lines
|
||||
.binary_search_by_key(&byte_index, |line| line.start_index)
|
||||
{
|
||||
Ok(index) => index,
|
||||
Err(insert_index) => {
|
||||
if insert_index == 0 {
|
||||
0 // may happen when there's a BOM
|
||||
} else {
|
||||
insert_index - 1
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Gets the line start byte index.
|
||||
pub fn line_start(&self, line_index: usize) -> usize {
|
||||
self.assert_valid_line_index(line_index);
|
||||
self.lines[line_index].start_index
|
||||
}
|
||||
|
||||
/// Gets the line end byte index (before/at the newline character).
|
||||
pub fn line_end(&self, line_index: usize) -> usize {
|
||||
self.assert_valid_line_index(line_index);
|
||||
self.lines[line_index].end_index
|
||||
}
|
||||
|
||||
/// Gets the line range.
|
||||
pub fn line_range(&self, line_index: usize) -> (usize, usize) {
|
||||
self.assert_valid_line_index(line_index);
|
||||
let line = &self.lines[line_index];
|
||||
(line.start_index, line.end_index)
|
||||
}
|
||||
|
||||
/// Gets the byte position from the provided line and column index.
|
||||
pub fn byte_index(&self, line_and_column: LineAndColumnIndex) -> usize {
|
||||
let line = &self.lines[line_and_column.line_index];
|
||||
let mut byte_index = line.start_index + line_and_column.column_index;
|
||||
|
||||
for char_info in line.multi_byte_chars.iter() {
|
||||
if char_info.line_char_index < line_and_column.column_index {
|
||||
// - 1 because the 1 was already added above when adding the column index
|
||||
byte_index += char_info.length - 1;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// fallback gracefully to the end index of the line when the column goes off
|
||||
if byte_index > line.end_index {
|
||||
line.end_index
|
||||
} else {
|
||||
byte_index
|
||||
}
|
||||
}
|
||||
|
||||
/// Gets a byte index from the provided character index.
|
||||
pub fn byte_index_from_char_index(&self, char_index: usize) -> usize {
|
||||
let mut last_char_index = 0;
|
||||
let mut last_byte_index = 0;
|
||||
|
||||
let mut lines = self.lines.iter().peekable();
|
||||
while let Some(line) = lines.next() {
|
||||
for char_info in &line.multi_byte_chars {
|
||||
let char_length = char_info.byte_index - last_byte_index;
|
||||
if last_char_index + char_length >= char_index {
|
||||
let byte_diff = char_index - last_char_index;
|
||||
return last_byte_index + byte_diff;
|
||||
} else {
|
||||
// move to the position past the character
|
||||
last_byte_index = char_info.byte_index + char_info.length;
|
||||
last_char_index += char_length + 1;
|
||||
}
|
||||
}
|
||||
|
||||
// check the end of the line
|
||||
let line_end = if let Some(next_line) = lines.peek() {
|
||||
next_line.start_index
|
||||
} else {
|
||||
line.end_index
|
||||
};
|
||||
let char_length = line_end - last_byte_index;
|
||||
if last_char_index + char_length >= char_index {
|
||||
let byte_diff = char_index - last_char_index;
|
||||
return last_byte_index + byte_diff;
|
||||
} else {
|
||||
last_byte_index = line_end;
|
||||
last_char_index += char_length;
|
||||
}
|
||||
}
|
||||
|
||||
last_byte_index
|
||||
}
|
||||
|
||||
/// Gets a character index from the provided byte index.
|
||||
pub fn char_index(&self, byte_index: usize) -> usize {
|
||||
let mut lines = self.lines.iter().peekable();
|
||||
let mut last_char_index = 0;
|
||||
let mut last_byte_index = 0;
|
||||
while let Some(line) = lines.next() {
|
||||
for char_info in &line.multi_byte_chars {
|
||||
if char_info.byte_index >= byte_index {
|
||||
let char_length = byte_index - last_byte_index;
|
||||
return last_char_index + char_length;
|
||||
} else {
|
||||
// move to the position past the character
|
||||
let char_length = char_info.byte_index - last_byte_index;
|
||||
last_byte_index = char_info.byte_index + char_info.length;
|
||||
last_char_index += char_length + 1;
|
||||
}
|
||||
}
|
||||
|
||||
// check the end of the line
|
||||
let line_end = if let Some(next_line) = lines.peek() {
|
||||
next_line.start_index
|
||||
} else {
|
||||
line.end_index
|
||||
};
|
||||
if line_end >= byte_index {
|
||||
let char_length = byte_index - last_byte_index;
|
||||
return last_char_index + char_length;
|
||||
} else {
|
||||
let char_length = line_end - last_byte_index;
|
||||
last_byte_index = line_end;
|
||||
last_char_index += char_length;
|
||||
}
|
||||
}
|
||||
|
||||
last_char_index
|
||||
}
|
||||
|
||||
/// Gets the line and column index of the provided byte index.
|
||||
pub fn line_and_column_index(&self, byte_index: usize) -> LineAndColumnIndex {
|
||||
// ensure no panics will happen here in case someone is specifying a byte position in the middle of a char
|
||||
let line_index = self.line_index(byte_index);
|
||||
let line = &self.lines[line_index];
|
||||
|
||||
let relative_byte_index = if byte_index < line.start_index {
|
||||
0 // could happen when at the BOM position
|
||||
} else {
|
||||
byte_index - line.start_index
|
||||
};
|
||||
let multi_byte_char_offset = line
|
||||
.multi_byte_chars
|
||||
.iter()
|
||||
.take_while(|char_info| char_info.byte_index < byte_index)
|
||||
.map(|char_info| {
|
||||
if char_info.byte_index + char_info.length > byte_index {
|
||||
byte_index - char_info.byte_index
|
||||
} else {
|
||||
char_info.length - 1
|
||||
}
|
||||
})
|
||||
.sum::<usize>();
|
||||
|
||||
LineAndColumnIndex {
|
||||
line_index,
|
||||
column_index: relative_byte_index - multi_byte_char_offset,
|
||||
}
|
||||
}
|
||||
|
||||
/// Gets the line and column display based on the indentation width and the provided byte index.
|
||||
pub fn line_and_column_display(&self, byte_index: usize) -> LineAndColumnDisplay {
|
||||
self.line_and_column_display_with_indent_width(byte_index, self.indent_width)
|
||||
}
|
||||
|
||||
/// Gets the line and column display based on the provided byte index and indentation width.
|
||||
pub fn line_and_column_display_with_indent_width(
|
||||
&self,
|
||||
byte_index: usize,
|
||||
indent_width: usize,
|
||||
) -> LineAndColumnDisplay {
|
||||
let line_and_column_index = self.line_and_column_index(byte_index);
|
||||
let line = &self.lines[line_and_column_index.line_index];
|
||||
let tab_char_count = line
|
||||
.tab_chars
|
||||
.iter()
|
||||
.take_while(|tab_index| **tab_index < byte_index)
|
||||
.count();
|
||||
|
||||
LineAndColumnDisplay {
|
||||
line_number: line_and_column_index.line_index + 1,
|
||||
column_number: line_and_column_index.column_index - tab_char_count
|
||||
+ tab_char_count * indent_width
|
||||
+ 1,
|
||||
}
|
||||
}
|
||||
|
||||
fn assert_valid_byte_index(&self, byte_index: usize) {
|
||||
if byte_index > self.text_length() {
|
||||
panic!(
|
||||
"The specified byte index {} was greater than the text length of {}.",
|
||||
byte_index,
|
||||
self.text_length()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fn assert_valid_line_index(&self, line_index: usize) {
|
||||
if line_index >= self.lines.len() {
|
||||
panic!(
|
||||
"The specified line index {} was greater or equal to the number of lines of {}.",
|
||||
line_index,
|
||||
self.lines.len()
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn line_and_column_index() {
|
||||
let text = "12\n3\r\n4\n5";
|
||||
let info = TextLines::new(text);
|
||||
assert_line_and_col_index(&info, 0, 0, 0); // 1
|
||||
assert_line_and_col_index(&info, 1, 0, 1); // 2
|
||||
assert_line_and_col_index(&info, 2, 0, 2); // \n
|
||||
assert_line_and_col_index(&info, 3, 1, 0); // 3
|
||||
assert_line_and_col_index(&info, 4, 1, 1); // \r
|
||||
assert_line_and_col_index(&info, 5, 1, 2); // \n
|
||||
assert_line_and_col_index(&info, 6, 2, 0); // 4
|
||||
assert_line_and_col_index(&info, 7, 2, 1); // \n
|
||||
assert_line_and_col_index(&info, 8, 3, 0); // 5
|
||||
assert_line_and_col_index(&info, 9, 3, 1); // <EOF>
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn line_and_column_index_bom() {
|
||||
let text = "\u{FEFF}12\n3";
|
||||
let info = TextLines::new(text);
|
||||
assert_line_and_col_index(&info, 0, 0, 0); // first BOM index
|
||||
assert_line_and_col_index(&info, 1, 0, 0); // second BOM index
|
||||
assert_line_and_col_index(&info, 2, 0, 0); // third BOM index
|
||||
assert_line_and_col_index(&info, 3, 0, 0); // 1
|
||||
assert_line_and_col_index(&info, 4, 0, 1); // 2
|
||||
assert_line_and_col_index(&info, 5, 0, 2); // \n
|
||||
assert_line_and_col_index(&info, 6, 1, 0); // 3
|
||||
assert_line_and_col_index(&info, 7, 1, 1); // <EOF>
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn line_and_column_index_multi_byte_chars() {
|
||||
let text = "β1β\nΔβ1";
|
||||
let info = TextLines::new(text);
|
||||
assert_line_and_col_index(&info, 0, 0, 0); // first β index
|
||||
assert_line_and_col_index(&info, 1, 0, 0); // second β index
|
||||
assert_line_and_col_index(&info, 2, 0, 1); // 1
|
||||
assert_line_and_col_index(&info, 3, 0, 2); // first β index
|
||||
assert_line_and_col_index(&info, 4, 0, 2); // second β index
|
||||
assert_line_and_col_index(&info, 5, 0, 3); // \n
|
||||
assert_line_and_col_index(&info, 6, 1, 0); // first Δ index
|
||||
assert_line_and_col_index(&info, 7, 1, 0); // second Δ index
|
||||
assert_line_and_col_index(&info, 8, 1, 1); // first β index
|
||||
assert_line_and_col_index(&info, 9, 1, 1); // second β index
|
||||
assert_line_and_col_index(&info, 10, 1, 2); // 1
|
||||
assert_line_and_col_index(&info, 11, 1, 3); // <EOF>
|
||||
}
|
||||
|
||||
fn assert_line_and_col_index(
|
||||
info: &TextLines,
|
||||
byte_index: usize,
|
||||
line_index: usize,
|
||||
column_index: usize,
|
||||
) {
|
||||
assert_eq!(
|
||||
info.line_and_column_index(byte_index),
|
||||
LineAndColumnIndex {
|
||||
line_index,
|
||||
column_index,
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn line_and_column_display() {
|
||||
let text = "\t1\n\t 3\t4";
|
||||
let info = TextLines::new(text);
|
||||
assert_line_and_col_display(&info, 0, 1, 1); // \t
|
||||
assert_line_and_col_display(&info, 1, 1, 5); // 1
|
||||
assert_line_and_col_display(&info, 2, 1, 6); // \n
|
||||
assert_line_and_col_display(&info, 3, 2, 1); // \t
|
||||
assert_line_and_col_display(&info, 4, 2, 5); // <space>
|
||||
assert_line_and_col_display(&info, 5, 2, 6); // 3
|
||||
assert_line_and_col_display(&info, 6, 2, 7); // \t
|
||||
assert_line_and_col_display(&info, 7, 2, 11); // \t
|
||||
assert_line_and_col_display(&info, 8, 2, 12); // <EOF>
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn line_and_column_display_bom() {
|
||||
let text = "\u{FEFF}\t1";
|
||||
let info = TextLines::new(text);
|
||||
assert_line_and_col_display(&info, 0, 1, 1); // first BOM index
|
||||
assert_line_and_col_display(&info, 1, 1, 1); // second BOM index
|
||||
assert_line_and_col_display(&info, 2, 1, 1); // third BOM index
|
||||
assert_line_and_col_display(&info, 3, 1, 1); // \t
|
||||
assert_line_and_col_display(&info, 4, 1, 5); // 1
|
||||
assert_line_and_col_display(&info, 5, 1, 6); // <EOF>
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn line_and_column_display_indent_width() {
|
||||
let text = "\t1";
|
||||
let info = TextLines::with_indent_width(text, 2);
|
||||
assert_line_and_col_display(&info, 0, 1, 1); // \t
|
||||
assert_line_and_col_display(&info, 1, 1, 3); // 1
|
||||
assert_line_and_col_display(&info, 2, 1, 4); // <EOF>
|
||||
}
|
||||
|
||||
fn assert_line_and_col_display(
|
||||
info: &TextLines,
|
||||
byte_index: usize,
|
||||
line_number: usize,
|
||||
column_number: usize,
|
||||
) {
|
||||
assert_eq!(
|
||||
info.line_and_column_display(byte_index),
|
||||
LineAndColumnDisplay {
|
||||
line_number,
|
||||
column_number,
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn line_and_column_display_with_indent_width() {
|
||||
let text = "\t1\n\t 3\t4";
|
||||
let info = TextLines::new(text);
|
||||
assert_eq!(
|
||||
info.line_and_column_display_with_indent_width(1, 2),
|
||||
LineAndColumnDisplay {
|
||||
line_number: 1,
|
||||
column_number: 3,
|
||||
}
|
||||
);
|
||||
assert_eq!(
|
||||
info.line_and_column_display_with_indent_width(1, 4),
|
||||
LineAndColumnDisplay {
|
||||
line_number: 1,
|
||||
column_number: 5,
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic(expected = "The specified byte index 5 was greater than the text length of 4.")]
|
||||
fn line_and_column_index_panic_greater_than() {
|
||||
let info = TextLines::new("test");
|
||||
info.line_and_column_index(5);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn line_start() {
|
||||
let text = "12\n3\r\n4\n5";
|
||||
let info = TextLines::new(text);
|
||||
assert_line_start(&info, 0, 0);
|
||||
assert_line_start(&info, 1, 3);
|
||||
assert_line_start(&info, 2, 6);
|
||||
assert_line_start(&info, 3, 8);
|
||||
}
|
||||
|
||||
fn assert_line_start(info: &TextLines, line_index: usize, line_start: usize) {
|
||||
assert_eq!(info.line_start(line_index), line_start);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic(
|
||||
expected = "The specified line index 1 was greater or equal to the number of lines of 1."
|
||||
)]
|
||||
fn line_start_equal_number_lines() {
|
||||
let info = TextLines::new("test");
|
||||
info.line_start(1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn line_end() {
|
||||
let text = "12\n3\r\n4\n5";
|
||||
let info = TextLines::new(text);
|
||||
assert_line_end(&info, 0, 2);
|
||||
assert_line_end(&info, 1, 4);
|
||||
assert_line_end(&info, 2, 7);
|
||||
assert_line_end(&info, 3, 9);
|
||||
}
|
||||
|
||||
fn assert_line_end(info: &TextLines, line_index: usize, line_end: usize) {
|
||||
assert_eq!(info.line_end(line_index), line_end);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic(
|
||||
expected = "The specified line index 1 was greater or equal to the number of lines of 1."
|
||||
)]
|
||||
fn line_end_equal_number_lines() {
|
||||
let info = TextLines::new("test");
|
||||
info.line_end(1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn byte_index() {
|
||||
let text = "12\n3\r\n4\n5";
|
||||
let info = TextLines::new(text);
|
||||
assert_byte_index(&info, 0, 0, 0); // 1
|
||||
assert_byte_index(&info, 0, 1, 1); // 2
|
||||
assert_byte_index(&info, 0, 2, 2); // \n
|
||||
assert_byte_index(&info, 0, 3, 2); // passed the \n
|
||||
assert_byte_index(&info, 0, 4, 2); // passed the \n
|
||||
assert_byte_index(&info, 1, 0, 3); // 3
|
||||
assert_byte_index(&info, 1, 1, 4); // \r
|
||||
assert_byte_index(&info, 1, 2, 4); // \n
|
||||
assert_byte_index(&info, 1, 3, 4); // passed the \r\n
|
||||
assert_byte_index(&info, 2, 0, 6); // 4
|
||||
assert_byte_index(&info, 2, 1, 7); // \n
|
||||
assert_byte_index(&info, 3, 0, 8); // 5
|
||||
assert_byte_index(&info, 3, 1, 9); // <EOF>
|
||||
assert_byte_index(&info, 3, 2, 9); // passed the<EOF>
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn byte_index_bom() {
|
||||
let text = "\u{FEFF}12\n3";
|
||||
let info = TextLines::new(text);
|
||||
assert_byte_index(&info, 0, 0, 3); // 1
|
||||
assert_byte_index(&info, 0, 1, 4); // 2
|
||||
assert_byte_index(&info, 0, 2, 5); // \n
|
||||
assert_byte_index(&info, 1, 0, 6); // 3
|
||||
assert_byte_index(&info, 1, 1, 7); // <EOF>
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn byte_index_multi_byte_chars() {
|
||||
let text = "β1β\nΔβ1";
|
||||
let info = TextLines::new(text);
|
||||
assert_byte_index(&info, 0, 0, 0); // first β index
|
||||
assert_byte_index(&info, 0, 1, 2); // 1
|
||||
assert_byte_index(&info, 0, 2, 3); // first β index
|
||||
assert_byte_index(&info, 0, 3, 5); // \n
|
||||
assert_byte_index(&info, 1, 0, 6); // first Δ index
|
||||
assert_byte_index(&info, 1, 1, 8); // first β index
|
||||
assert_byte_index(&info, 1, 2, 10); // 1
|
||||
assert_byte_index(&info, 1, 3, 11); // <EOF>
|
||||
}
|
||||
|
||||
fn assert_byte_index(
|
||||
info: &TextLines,
|
||||
line_index: usize,
|
||||
column_index: usize,
|
||||
byte_index: usize,
|
||||
) {
|
||||
assert_eq!(
|
||||
info.byte_index(LineAndColumnIndex {
|
||||
line_index,
|
||||
column_index,
|
||||
}),
|
||||
byte_index,
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn byte_index_from_char_index() {
|
||||
let text = "1234\n567\r\n8\n";
|
||||
let info = TextLines::new(text);
|
||||
assert_byte_index_from_char_index(&info, 0, 0); // 1
|
||||
assert_byte_index_from_char_index(&info, 1, 1); // 2
|
||||
assert_byte_index_from_char_index(&info, 2, 2); // 3
|
||||
assert_byte_index_from_char_index(&info, 3, 3); // 4
|
||||
assert_byte_index_from_char_index(&info, 4, 4); // \n
|
||||
assert_byte_index_from_char_index(&info, 5, 5); // 5
|
||||
assert_byte_index_from_char_index(&info, 6, 6); // 6
|
||||
assert_byte_index_from_char_index(&info, 7, 7); // 7
|
||||
assert_byte_index_from_char_index(&info, 8, 8); // \r
|
||||
assert_byte_index_from_char_index(&info, 9, 9); // \n
|
||||
assert_byte_index_from_char_index(&info, 10, 10); // 8
|
||||
assert_byte_index_from_char_index(&info, 11, 11); // \n
|
||||
assert_byte_index_from_char_index(&info, 12, 12); // <EOF>
|
||||
assert_byte_index_from_char_index(&info, 13, 12); // <EOF> + 1
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn byte_index_from_char_index_multi_byte_chars() {
|
||||
let text = "β1β\nΔβ1\r\nt\nu";
|
||||
let info = TextLines::new(text);
|
||||
assert_byte_index_from_char_index(&info, 0, 0); // β
|
||||
assert_byte_index_from_char_index(&info, 1, 2); // 1
|
||||
assert_byte_index_from_char_index(&info, 2, 3); // β
|
||||
assert_byte_index_from_char_index(&info, 3, 5); // \n
|
||||
assert_byte_index_from_char_index(&info, 4, 6); // Δ
|
||||
assert_byte_index_from_char_index(&info, 5, 8); // β
|
||||
assert_byte_index_from_char_index(&info, 6, 10); // 1
|
||||
assert_byte_index_from_char_index(&info, 7, 11); // \r
|
||||
assert_byte_index_from_char_index(&info, 8, 12); // \n
|
||||
assert_byte_index_from_char_index(&info, 9, 13); // t
|
||||
assert_byte_index_from_char_index(&info, 10, 14); // \n
|
||||
assert_byte_index_from_char_index(&info, 11, 15); // u
|
||||
assert_byte_index_from_char_index(&info, 12, 16); // <EOF>
|
||||
assert_byte_index_from_char_index(&info, 13, 16); // <EOF> + 1
|
||||
}
|
||||
|
||||
fn assert_byte_index_from_char_index(info: &TextLines, char_index: usize, byte_index: usize) {
|
||||
assert_eq!(info.byte_index_from_char_index(char_index), byte_index,);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn char_index() {
|
||||
let text = "1234\n567\r\n8\n";
|
||||
let info = TextLines::new(text);
|
||||
assert_char_index(&info, 0, 0); // 1
|
||||
assert_char_index(&info, 1, 1); // 2
|
||||
assert_char_index(&info, 2, 2); // 3
|
||||
assert_char_index(&info, 3, 3); // 4
|
||||
assert_char_index(&info, 4, 4); // \n
|
||||
assert_char_index(&info, 5, 5); // 5
|
||||
assert_char_index(&info, 6, 6); // 6
|
||||
assert_char_index(&info, 7, 7); // 7
|
||||
assert_char_index(&info, 8, 8); // \r
|
||||
assert_char_index(&info, 9, 9); // \n
|
||||
assert_char_index(&info, 10, 10); // 8
|
||||
assert_char_index(&info, 11, 11); // \n
|
||||
assert_char_index(&info, 12, 12); // <EOF>
|
||||
assert_char_index(&info, 13, 12); // <EOF> + 1
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn char_index_multi_byte_chars() {
|
||||
let text = "β1β\nΔβ1\r\nt\nu";
|
||||
let info = TextLines::new(text);
|
||||
assert_char_index(&info, 0, 0); // β
|
||||
assert_char_index(&info, 2, 1); // 1
|
||||
assert_char_index(&info, 3, 2); // β
|
||||
assert_char_index(&info, 5, 3); // \n
|
||||
assert_char_index(&info, 6, 4); // Δ
|
||||
assert_char_index(&info, 8, 5); // β
|
||||
assert_char_index(&info, 10, 6); // 1
|
||||
assert_char_index(&info, 11, 7); // \r
|
||||
assert_char_index(&info, 12, 8); // \n
|
||||
assert_char_index(&info, 13, 9); // t
|
||||
assert_char_index(&info, 14, 10); // \n
|
||||
assert_char_index(&info, 15, 11); // u
|
||||
assert_char_index(&info, 16, 12); // <EOF>
|
||||
assert_char_index(&info, 17, 12); // <EOF> + 1
|
||||
}
|
||||
|
||||
fn assert_char_index(info: &TextLines, char_index: usize, byte_index: usize) {
|
||||
assert_eq!(info.char_index(char_index), byte_index,);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn readme_example() {
|
||||
let text = "Line 1\n\tLine 2";
|
||||
let info = TextLines::new(&text);
|
||||
|
||||
assert_eq!(info.line_index(9), 1);
|
||||
assert_eq!(
|
||||
info.line_and_column_index(9),
|
||||
LineAndColumnIndex {
|
||||
line_index: 1,
|
||||
column_index: 2,
|
||||
}
|
||||
);
|
||||
assert_eq!(
|
||||
info.line_and_column_display(9),
|
||||
LineAndColumnDisplay {
|
||||
line_number: 2,
|
||||
column_number: 6,
|
||||
}
|
||||
);
|
||||
|
||||
let info = TextLines::with_indent_width(&text, 2);
|
||||
assert_eq!(
|
||||
info.line_and_column_display(9),
|
||||
LineAndColumnDisplay {
|
||||
line_number: 2,
|
||||
column_number: 4,
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue