1#[derive(Debug, PartialEq, Clone, Copy)]
3pub struct Range {
4 pub start: usize,
6 pub end: usize,
8}
9
10impl Range {
11 pub fn new(start: usize, end: usize) -> Self {
12 Range { start, end }
13 }
14
15 pub fn from_byte_index(pos: usize) -> Self {
16 Range::new(pos, pos)
17 }
18}
19
20impl Ranged for Range {
21 fn range(&self) -> Range {
22 *self
23 }
24}
25
26#[cfg(feature = "serde_json")]
28pub(crate) fn fill_bare_decimal_point(num: &str) -> std::borrow::Cow<'_, str> {
29 let Some(dot) = num.find('.') else {
30 return std::borrow::Cow::Borrowed(num);
31 };
32 let before = num[..dot].ends_with(|c: char| c.is_ascii_digit());
33 let after = num[dot + 1..].starts_with(|c: char| c.is_ascii_digit());
34 if before && after {
35 return std::borrow::Cow::Borrowed(num);
36 }
37 let mut filled = String::with_capacity(num.len() + 1);
38 filled.push_str(&num[..dot]);
39 filled.push_str(if before { ".0" } else { "0." });
40 filled.push_str(&num[dot + 1..]);
41 std::borrow::Cow::Owned(filled)
42}
43
44pub trait Ranged {
46 fn range(&self) -> Range;
48
49 fn start(&self) -> usize {
51 self.range().start
52 }
53
54 fn end(&self) -> usize {
56 self.range().end
57 }
58
59 fn text<'a>(&self, text: &'a str) -> &'a str {
61 let range = self.range();
62 &text[range.start..range.end]
63 }
64
65 fn width(&self) -> usize {
67 let range = self.range();
68 range.end - range.start
69 }
70}