Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'lib/text-size/src/size.rs')
| -rw-r--r-- | lib/text-size/src/size.rs | 41 |
1 files changed, 29 insertions, 12 deletions
diff --git a/lib/text-size/src/size.rs b/lib/text-size/src/size.rs index 454327a015..5239ea6691 100644 --- a/lib/text-size/src/size.rs +++ b/lib/text-size/src/size.rs @@ -11,15 +11,23 @@ use { /// A measure of text length. Also, equivalently, an index into text. /// -/// This is a utf8-bytes-offset stored as `u32`, but +/// This is a UTF-8 bytes offset stored as `u32`, but /// most clients should treat it as an opaque measure. /// +/// For cases that need to escape `TextSize` and return to working directly +/// with primitive integers, `TextSize` can be converted losslessly to/from +/// `u32` via [`From`] conversions as well as losslessly be converted [`Into`] +/// `usize`. The `usize -> TextSize` direction can be done via [`TryFrom`]. +/// +/// These escape hatches are primarily required for unit testing and when +/// converting from UTF-8 size to another coordinate space, such as UTF-16. +/// /// # Translation from `text_unit` /// /// - `TextUnit::of_char(c)` ⟹ `TextSize::of(c)` -/// - `TextUnit::of_str(s)` ⟹ `TextSize:of(s)` +/// - `TextUnit::of_str(s)` ⟹ `TextSize::of(s)` /// - `TextUnit::from_usize(size)` ⟹ `TextSize::try_from(size).unwrap_or_else(|| panic!(_))` -/// - `unit.to_usize()` ⟹ `usize::try_from(size).unwrap_or_else(|| panic!(_))` +/// - `unit.to_usize()` ⟹ `usize::from(size)` #[derive(Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct TextSize { pub(crate) raw: u32, @@ -38,6 +46,7 @@ impl fmt::Debug for TextSize { impl TextSize { /// The text size of some text-like object. + #[inline] pub fn of(text: impl TextSized) -> TextSize { text.text_size() } @@ -46,6 +55,7 @@ impl TextSize { /// /// This is equivalent to `TextSize::default()` or [`TextSize::MIN`], /// but is more explicit on intent. + #[inline] pub const fn zero() -> TextSize { TextSize(0) } @@ -59,24 +69,28 @@ impl TextSize { /// The largest representable text size. (`u32::MAX`) pub const MAX: TextSize = TextSize(u32::MAX); - #[allow(missing_docs)] + /// Checked addition. Returns `None` if overflow occurred. + #[inline] pub fn checked_add(self, rhs: TextSize) -> Option<TextSize> { self.raw.checked_add(rhs.raw).map(TextSize) } - #[allow(missing_docs)] + /// Checked subtraction. Returns `None` if overflow occurred. + #[inline] pub fn checked_sub(self, rhs: TextSize) -> Option<TextSize> { self.raw.checked_sub(rhs.raw).map(TextSize) } } impl From<u32> for TextSize { + #[inline] fn from(raw: u32) -> Self { - TextSize { raw } + TextSize(raw) } } impl From<TextSize> for u32 { + #[inline] fn from(value: TextSize) -> Self { value.raw } @@ -84,19 +98,16 @@ impl From<TextSize> for u32 { impl TryFrom<usize> for TextSize { type Error = TryFromIntError; + #[inline] fn try_from(value: usize) -> Result<Self, TryFromIntError> { Ok(u32::try_from(value)?.into()) } } impl From<TextSize> for usize { + #[inline] fn from(value: TextSize) -> Self { - assert_lossless_conversion(); - return value.raw as usize; - - const fn assert_lossless_conversion() { - [()][(std::mem::size_of::<usize>() < std::mem::size_of::<u32>()) as usize] - } + value.raw as usize } } @@ -104,12 +115,14 @@ macro_rules! ops { (impl $Op:ident for TextSize by fn $f:ident = $op:tt) => { impl $Op<TextSize> for TextSize { type Output = TextSize; + #[inline] fn $f(self, other: TextSize) -> TextSize { TextSize(self.raw $op other.raw) } } impl $Op<&TextSize> for TextSize { type Output = TextSize; + #[inline] fn $f(self, other: &TextSize) -> TextSize { self $op *other } @@ -119,6 +132,7 @@ macro_rules! ops { TextSize: $Op<T, Output=TextSize>, { type Output = TextSize; + #[inline] fn $f(self, other: T) -> TextSize { *self $op other } @@ -133,6 +147,7 @@ impl<A> AddAssign<A> for TextSize where TextSize: Add<A, Output = TextSize>, { + #[inline] fn add_assign(&mut self, rhs: A) { *self = *self + rhs } @@ -142,6 +157,7 @@ impl<S> SubAssign<S> for TextSize where TextSize: Sub<S, Output = TextSize>, { + #[inline] fn sub_assign(&mut self, rhs: S) { *self = *self - rhs } @@ -151,6 +167,7 @@ impl<A> iter::Sum<A> for TextSize where TextSize: Add<A, Output = TextSize>, { + #[inline] fn sum<I: Iterator<Item = A>>(iter: I) -> TextSize { iter.fold(TextSize::zero(), Add::add) } |