Skip to content

Commit 4b68ff2

Browse files
bors[bot]CAD97
andauthored
Merge #18
18: minor improvements everywhere r=matklad a=CAD97 Because none of this was quite specific enough to break into its own PR - Update translation docs - Officially `compiler_error!`-forbid `cfg(target_pointer_width = "16")` - `TextRange::before` (alt options: `TextRange::to`, `TextRange::up_to`, `TextRangeTo`, `TextSize::prefix`) - `TextRange::after` (alt options: `TextSize::suffix`) - `TextRange::offset` (alt options: `TextRange::add`, `Add::add`, `TextRange::reanchor`) - `TextSize::one` (alt options: ) - `TextSize::ONE` (alt options: `TextSize::ASCII` - `#[inline]` capability for a bunch of things This PR is mainly just to get opinions on all of these little things, then I'll re-force-push with a commit just with those. Co-authored-by: CAD97 <[email protected]>
2 parents e523b86 + a55a2f5 commit 4b68ff2

File tree

4 files changed

+65
-32
lines changed

4 files changed

+65
-32
lines changed

src/lib.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,6 @@ mod traits;
1313
mod serde_impls;
1414

1515
pub use crate::{range::TextRange, size::TextSize, traits::TextSized};
16+
17+
#[cfg(target_pointer_width = "16")]
18+
compile_error!("text-size assumes usize >= u32 and does not work on 16-bit targets");

src/range.rs

Lines changed: 31 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -8,24 +8,19 @@ use {
88

99
/// A range in text, represented as a pair of [`TextSize`][struct@TextSize].
1010
///
11-
/// It is a logical error to have `end() < start()`, but
12-
/// code must not assume this is true for `unsafe` guarantees.
13-
///
1411
/// # Translation from `text_unit`
1512
///
16-
/// - `TextRange::from_to(from, to)` ⟹ `TextRange::from(from..to)`
17-
/// - `TextRange::offset_len(offset, size)` ⟹ `TextRange::from(offset..offset + size)`
13+
/// - `TextRange::from_to(from, to)` ⟹ `TextRange(from, to)`
14+
/// - `TextRange::offset_len(offset, size)` ⟹ `TextRange::up_to(size).offset(offset)`
1815
/// - `range.start()` ⟹ `range.start()`
1916
/// - `range.end()` ⟹ `range.end()`
20-
/// - `range.len()` ⟹ `range.len()`<sup>†</sup>
17+
/// - `range.len()` ⟹ `range.len()`
2118
/// - `range.is_empty()` ⟹ `range.is_empty()`
22-
/// - `a.is_subrange(b)` ⟹ `b.contains(a)`
19+
/// - `a.is_subrange(b)` ⟹ `b.contains_range(a)`
2320
/// - `a.intersection(b)` ⟹ `TextRange::intersection(a, b)`
2421
/// - `a.extend_to(b)` ⟹ `TextRange::covering(a, b)`
25-
/// - `range.contains(offset)` ⟹ `range.contains_exclusive(point)`
22+
/// - `range.contains(offset)` ⟹ `range.contains(point)`
2623
/// - `range.contains_inclusive(offset)` ⟹ `range.contains_inclusive(point)`
27-
///
28-
/// † See the note on [`TextRange::len`] for differing behavior for incorrect reverse ranges.
2924
#[derive(Copy, Clone, Eq, PartialEq, Hash)]
3025
pub struct TextRange {
3126
// Invariant: start <= end
@@ -39,47 +34,61 @@ impl fmt::Debug for TextRange {
3934
}
4035
}
4136

42-
/// Creates a new `TextRange` with given `start` and `end.
37+
/// Creates a new `TextRange` with the given `start` and `end` (`start..end`).
4338
///
4439
/// # Panics
4540
///
4641
/// Panics if `end < start`.
4742
#[allow(non_snake_case)]
43+
#[inline]
4844
pub fn TextRange(start: TextSize, end: TextSize) -> TextRange {
4945
assert!(start <= end);
5046
TextRange { start, end }
5147
}
5248

53-
/// Identity methods.
5449
impl TextRange {
55-
/// Creates a zero-length range at the specified offset.
56-
pub const fn empty(self, offset: TextSize) -> TextRange {
50+
/// Create a zero-length range at the specified offset (`offset..offset`).
51+
#[inline]
52+
pub const fn empty(offset: TextSize) -> TextRange {
5753
TextRange {
5854
start: offset,
5955
end: offset,
6056
}
6157
}
6258

59+
/// Create a range up to the given end (`..end`).
60+
#[inline]
61+
pub const fn up_to(end: TextSize) -> TextRange {
62+
TextRange {
63+
start: TextSize::zero(),
64+
end,
65+
}
66+
}
67+
}
68+
69+
/// Identity methods.
70+
impl TextRange {
6371
/// The start point of this range.
72+
#[inline]
6473
pub const fn start(self) -> TextSize {
6574
self.start
6675
}
6776

6877
/// The end point of this range.
78+
#[inline]
6979
pub const fn end(self) -> TextSize {
7080
self.end
7181
}
7282

7383
/// The size of this range.
84+
#[inline]
7485
pub const fn len(self) -> TextSize {
7586
// HACK for const fn: math on primitives only
7687
TextSize(self.end().raw - self.start().raw)
7788
}
7889

79-
/// Check if this range empty or reversed.
80-
///
81-
/// When `end() < start()`, this returns false.
82-
/// Code should prefer `is_empty()` to `len() == 0`.
90+
/// Check if this range is empty.
91+
#[inline]
8392
pub const fn is_empty(self) -> bool {
8493
// HACK for const fn: math on primitives only
8594
self.start().raw == self.end().raw
@@ -99,8 +108,7 @@ impl TextRange {
99108
///
100109
/// The end index is considered included.
101110
pub fn contains_inclusive(self, offset: TextSize) -> bool {
102-
let point = offset.into();
103-
self.start() <= point && point <= self.end()
111+
self.start() <= offset && offset <= self.end()
104112
}
105113

106114
/// Check if this range completely contains another range.
@@ -129,12 +137,14 @@ impl TextRange {
129137

130138
impl Index<TextRange> for str {
131139
type Output = str;
140+
#[inline]
132141
fn index(&self, index: TextRange) -> &Self::Output {
133142
&self[Range::<usize>::from(index)]
134143
}
135144
}
136145

137146
impl IndexMut<TextRange> for str {
147+
#[inline]
138148
fn index_mut(&mut self, index: TextRange) -> &mut Self::Output {
139149
&mut self[Range::<usize>::from(index)]
140150
}
@@ -154,6 +164,7 @@ impl<T> From<TextRange> for Range<T>
154164
where
155165
T: From<TextSize>,
156166
{
167+
#[inline]
157168
fn from(r: TextRange) -> Self {
158169
r.start().into()..r.end().into()
159170
}

src/size.rs

Lines changed: 29 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,23 @@ use {
1111

1212
/// A measure of text length. Also, equivalently, an index into text.
1313
///
14-
/// This is a utf8-bytes-offset stored as `u32`, but
14+
/// This is a UTF-8 bytes offset stored as `u32`, but
1515
/// most clients should treat it as an opaque measure.
1616
///
17+
/// For cases that need to escape `TextSize` and return to working directly
18+
/// with primitive integers, `TextSize` can be converted losslessly to/from
19+
/// `u32` via [`From`] conversions as well as losslessly be converted [`Into`]
20+
/// `usize`. The `usize -> TextSize` direction can be done via [`TryFrom`].
21+
///
22+
/// These escape hatches are primarily required for unit testing and when
23+
/// converting from UTF-8 size to another coordinate space, such as UTF-16.
24+
///
1725
/// # Translation from `text_unit`
1826
///
1927
/// - `TextUnit::of_char(c)` ⟹ `TextSize::of(c)`
20-
/// - `TextUnit::of_str(s)` ⟹ `TextSize:of(s)`
28+
/// - `TextUnit::of_str(s)` ⟹ `TextSize::of(s)`
2129
/// - `TextUnit::from_usize(size)` ⟹ `TextSize::try_from(size).unwrap_or_else(|| panic!(_))`
22-
/// - `unit.to_usize()` ⟹ `usize::try_from(size).unwrap_or_else(|| panic!(_))`
30+
/// - `unit.to_usize()` ⟹ `usize::from(size)`
2331
#[derive(Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
2432
pub struct TextSize {
2533
pub(crate) raw: u32,
@@ -38,6 +46,7 @@ impl fmt::Debug for TextSize {
3846

3947
impl TextSize {
4048
/// The text size of some text-like object.
49+
#[inline]
4150
pub fn of(text: impl TextSized) -> TextSize {
4251
text.text_size()
4352
}
@@ -46,6 +55,7 @@ impl TextSize {
4655
///
4756
/// This is equivalent to `TextSize::default()` or [`TextSize::MIN`],
4857
/// but is more explicit on intent.
58+
#[inline]
4959
pub const fn zero() -> TextSize {
5060
TextSize(0)
5161
}
@@ -59,57 +69,60 @@ impl TextSize {
5969
/// The largest representable text size. (`u32::MAX`)
6070
pub const MAX: TextSize = TextSize(u32::MAX);
6171

62-
#[allow(missing_docs)]
72+
/// Checked addition. Returns `None` if overflow occurred.
73+
#[inline]
6374
pub fn checked_add(self, rhs: TextSize) -> Option<TextSize> {
6475
self.raw.checked_add(rhs.raw).map(TextSize)
6576
}
6677

67-
#[allow(missing_docs)]
78+
/// Checked subtraction. Returns `None` if overflow occurred.
79+
#[inline]
6880
pub fn checked_sub(self, rhs: TextSize) -> Option<TextSize> {
6981
self.raw.checked_sub(rhs.raw).map(TextSize)
7082
}
7183
}
7284

7385
impl From<u32> for TextSize {
86+
#[inline]
7487
fn from(raw: u32) -> Self {
75-
TextSize { raw }
88+
TextSize(raw)
7689
}
7790
}
7891

7992
impl From<TextSize> for u32 {
93+
#[inline]
8094
fn from(value: TextSize) -> Self {
8195
value.raw
8296
}
8397
}
8498

8599
impl TryFrom<usize> for TextSize {
86100
type Error = TryFromIntError;
101+
#[inline]
87102
fn try_from(value: usize) -> Result<Self, TryFromIntError> {
88103
Ok(u32::try_from(value)?.into())
89104
}
90105
}
91106

92107
impl From<TextSize> for usize {
108+
#[inline]
93109
fn from(value: TextSize) -> Self {
94-
assert_lossless_conversion();
95-
return value.raw as usize;
96-
97-
const fn assert_lossless_conversion() {
98-
[()][(std::mem::size_of::<usize>() < std::mem::size_of::<u32>()) as usize]
99-
}
110+
value.raw as usize
100111
}
101112
}
102113

103114
macro_rules! ops {
104115
(impl $Op:ident for TextSize by fn $f:ident = $op:tt) => {
105116
impl $Op<TextSize> for TextSize {
106117
type Output = TextSize;
118+
#[inline]
107119
fn $f(self, other: TextSize) -> TextSize {
108120
TextSize(self.raw $op other.raw)
109121
}
110122
}
111123
impl $Op<&TextSize> for TextSize {
112124
type Output = TextSize;
125+
#[inline]
113126
fn $f(self, other: &TextSize) -> TextSize {
114127
self $op *other
115128
}
@@ -119,6 +132,7 @@ macro_rules! ops {
119132
TextSize: $Op<T, Output=TextSize>,
120133
{
121134
type Output = TextSize;
135+
#[inline]
122136
fn $f(self, other: T) -> TextSize {
123137
*self $op other
124138
}
@@ -133,6 +147,7 @@ impl<A> AddAssign<A> for TextSize
133147
where
134148
TextSize: Add<A, Output = TextSize>,
135149
{
150+
#[inline]
136151
fn add_assign(&mut self, rhs: A) {
137152
*self = *self + rhs
138153
}
@@ -142,6 +157,7 @@ impl<S> SubAssign<S> for TextSize
142157
where
143158
TextSize: Sub<S, Output = TextSize>,
144159
{
160+
#[inline]
145161
fn sub_assign(&mut self, rhs: S) {
146162
*self = *self - rhs
147163
}
@@ -151,6 +167,7 @@ impl<A> iter::Sum<A> for TextSize
151167
where
152168
TextSize: Add<A, Output = TextSize>,
153169
{
170+
#[inline]
154171
fn sum<I: Iterator<Item = A>>(iter: I) -> TextSize {
155172
iter.fold(TextSize::zero(), Add::add)
156173
}

src/traits.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ pub trait TextSized: Copy {
77
}
88

99
impl TextSized for &'_ str {
10+
#[inline]
1011
fn text_size(self) -> TextSize {
1112
self.len()
1213
.try_into()
@@ -15,6 +16,7 @@ impl TextSized for &'_ str {
1516
}
1617

1718
impl TextSized for char {
19+
#[inline]
1820
fn text_size(self) -> TextSize {
1921
TextSize(self.len_utf8() as u32)
2022
}

0 commit comments

Comments
 (0)