diff --git a/src/traits.rs b/src/traits.rs index 65f6445..3944030 100644 --- a/src/traits.rs +++ b/src/traits.rs @@ -1,6 +1,6 @@ use { crate::TextSize, - std::{convert::TryInto, ops::Deref}, + std::{borrow::Cow, convert::TryInto, rc::Rc, sync::Arc}, }; /// Text-like structures that have a text size. @@ -16,19 +16,44 @@ impl LenTextSize for &'_ str { } } -impl LenTextSize for &'_ D -where - D: Deref, -{ +impl LenTextSize for char { #[inline] fn len_text_size(self) -> TextSize { - self.deref().len_text_size() + (self.len_utf8() as u32).into() } } -impl LenTextSize for char { - #[inline] +impl LenTextSize for &'_ D +where + D: LenTextSize + Copy, +{ fn len_text_size(self) -> TextSize { - (self.len_utf8() as u32).into() + D::len_text_size(*self) } } + +// Because we could not find a smart blanket impl to do this automatically and +// cleanly (rust-analyzer/text-size#36), just provide a bunch of manual impls. +// If a type fits in this macro and you need it to impl LenTextSize, just open +// a PR and we are likely to accept it. Or use `TextSize::of::<&str>` for now. +macro_rules! impl_lentextsize_for_string { + ($($ty:ty),+ $(,)?) => {$( + impl LenTextSize for $ty { + #[inline] + fn len_text_size(self) -> TextSize { + <&str>::len_text_size(self) + } + } + )+}; +} + +impl_lentextsize_for_string! { + &Box, + &'_ String, + &Cow<'_, str>, + &Cow<'_, String>, + &Arc, + &Arc, + &Rc, + &Rc, +} diff --git a/tests/constructors.rs b/tests/constructors.rs index eba587b..1022a41 100644 --- a/tests/constructors.rs +++ b/tests/constructors.rs @@ -1,31 +1,34 @@ use { - std::{borrow::Cow, ops::Deref}, + std::{borrow::Cow, sync::Arc}, text_size::*, }; -struct StringLike<'a>(&'a str); +#[derive(Copy, Clone)] +struct BadRope<'a>(&'a [&'a str]); -impl Deref for StringLike<'_> { - type Target = str; - fn deref(&self) -> &Self::Target { - &self.0 +impl LenTextSize for BadRope<'_> { + fn len_text_size(self) -> TextSize { + self.0.iter().map(TextSize::of).sum() } } #[test] fn main() { - let s = ""; - let _ = TextSize::of(&s); - - let s = String::new(); - let _ = TextSize::of(&s); - - let s = Cow::Borrowed(""); - let _ = TextSize::of(&s); - - let s = Cow::Owned(String::new()); - let _ = TextSize::of(&s); + macro_rules! test { + ($($expr:expr),+ $(,)?) => { + $(let _ = TextSize::of($expr);)+ + }; + } - let s = StringLike(""); - let _ = TextSize::of(&s); + test! { + "", + &"", + 'a', + &'a', + &String::new(), + &String::new().into_boxed_str(), + &Arc::new(String::new()), + &Cow::Borrowed(""), + BadRope(&[""]), + } }