Skip to main content

rustpython_ruff_text_size/
traits.rs

1use std::sync::Arc;
2use {crate::TextRange, crate::TextSize, std::convert::TryInto};
3
4use priv_in_pub::Sealed;
5mod priv_in_pub {
6    pub trait Sealed {}
7}
8
9/// Primitives with a textual length that can be passed to [`TextSize::of`].
10pub trait TextLen: Copy + Sealed {
11    /// The textual length of this primitive.
12    fn text_len(self) -> TextSize;
13}
14
15impl Sealed for &'_ str {}
16impl TextLen for &'_ str {
17    #[inline]
18    fn text_len(self) -> TextSize {
19        self.len().try_into().unwrap()
20    }
21}
22
23impl Sealed for &'_ String {}
24impl TextLen for &'_ String {
25    #[inline]
26    fn text_len(self) -> TextSize {
27        self.as_str().text_len()
28    }
29}
30
31impl Sealed for char {}
32impl TextLen for char {
33    #[inline]
34    #[expect(clippy::cast_possible_truncation)]
35    fn text_len(self) -> TextSize {
36        (self.len_utf8() as u32).into()
37    }
38}
39
40/// A ranged item in the source text.
41pub trait Ranged {
42    /// The range of this item in the source text.
43    fn range(&self) -> TextRange;
44
45    /// The start offset of this item in the source text.
46    fn start(&self) -> TextSize {
47        self.range().start()
48    }
49
50    /// The end offset of this item in the source text.
51    fn end(&self) -> TextSize {
52        self.range().end()
53    }
54}
55
56impl Ranged for TextRange {
57    fn range(&self) -> TextRange {
58        *self
59    }
60}
61
62impl<T> Ranged for &T
63where
64    T: Ranged,
65{
66    fn range(&self) -> TextRange {
67        T::range(self)
68    }
69}
70
71impl<T> Ranged for Arc<T>
72where
73    T: Ranged,
74{
75    fn range(&self) -> TextRange {
76        T::range(self)
77    }
78}
79
80/// A slice of the source text.
81pub trait TextSlice: Sealed {
82    /// Returns the slice of the text within the given `range`.
83    ///
84    /// ## Note
85    ///
86    /// This is the same as `&self[range]` if `self` is a `str` and `range` a `TextRange`.
87    ///
88    /// ## Panics
89    /// If the range is out of bounds.
90    fn slice(&self, range: impl Ranged) -> &str;
91}
92
93impl Sealed for str {}
94
95impl TextSlice for str {
96    fn slice(&self, ranged: impl Ranged) -> &str {
97        &self[ranged.range()]
98    }
99}