From 679495c3ec01d545103accc11b998fcc30b87bdf Mon Sep 17 00:00:00 2001 From: Don Isaac Date: Sun, 26 May 2024 21:05:33 -0400 Subject: [PATCH] feat(atom): get &str from Atom<'a> with lifetime of 'a (#3420) Change `Atom<'a>::as_str(&self) -> &str` to `Atom<'a>::as_str(&self) -> &'a str`. This API is more ergonomic for external `oxc` consumers relying on `&str` data collected while traversing an AST. I also enhanced some nearby doc comments and implemented some `From<...>` traits while I was at it. --- crates/oxc_span/src/atom.rs | 67 +++++++++++++++++++++++++++---------- 1 file changed, 50 insertions(+), 17 deletions(-) diff --git a/crates/oxc_span/src/atom.rs b/crates/oxc_span/src/atom.rs index 9c28b5cfc..d35ae03af 100644 --- a/crates/oxc_span/src/atom.rs +++ b/crates/oxc_span/src/atom.rs @@ -17,8 +17,8 @@ pub const MAX_INLINE_LEN: usize = 16; /// An inlinable string for oxc_allocator. /// -/// Use [CompactStr] with [Atom::to_compact_str] or [Atom::into_compact_str] for the -/// lifetimeless form. +/// Use [CompactStr] with [Atom::to_compact_str] or [Atom::into_compact_str] for +/// the lifetimeless form. #[derive(Clone, Eq)] #[cfg_attr(feature = "serialize", derive(Serialize))] #[cfg_attr(feature = "serialize", serde(transparent))] @@ -26,7 +26,7 @@ pub struct Atom<'a>(&'a str); impl<'a> Atom<'a> { #[inline] - pub fn as_str(&self) -> &str { + pub fn as_str(&self) -> &'a str { self.0 } @@ -52,6 +52,20 @@ impl<'a> From<&'a str> for Atom<'a> { } } +impl<'a> From> for CompactStr { + #[inline] + fn from(val: Atom<'a>) -> Self { + val.into_compact_str() + } +} + +impl<'a> From> for String { + #[inline] + fn from(val: Atom<'a>) -> Self { + val.into_string() + } +} + impl<'a> Deref for Atom<'a> { type Target = str; @@ -108,20 +122,22 @@ impl<'a> fmt::Display for Atom<'a> { } } -/// Lifetimeless version of `Atom<'_>` which owns its own string data allocation. +/// Lifetimeless version of [`Atom<'_>`] which owns its own string data allocation. /// -/// `CompactStr` is immutable. Use `CompactStr::into_string` for a mutable `String`. +/// [`CompactStr`] is immutable. Use [`CompactStr::into_string`] for a mutable +/// [`String`]. /// -/// Currently implemented as just a wrapper around `compact_str::CompactString`, +/// Currently implemented as just a wrapper around [`compact_str::CompactString`], /// but will be reduced in size with a custom implementation later. #[derive(Clone, Eq)] pub struct CompactStr(CompactString); impl CompactStr { - /// Create a new `CompactStr`. + /// Create a new [`CompactStr`]. /// - /// If `&str` is `'static` and no more than `MAX_INLINE_LEN` bytes, - /// prefer `CompactStr::new_const` which creates the `CompactStr` at compile time. + /// If `&str` is `'static` and no more than [`MAX_INLINE_LEN`] bytes, + /// prefer [`CompactStr::new_const`] which creates the [`CompactStr`] at + /// compile time. /// /// # Examples /// ``` @@ -132,15 +148,15 @@ impl CompactStr { Self(CompactString::new(s)) } - /// Create a `CompactStr` at compile time. + /// Create a [`CompactStr`] at compile time. /// - /// String must be no longer than `MAX_INLINE_LEN` bytes. + /// String must be no longer than [`MAX_INLINE_LEN`] bytes. /// - /// Prefer this over `CompactStr::new` or `CompactStr::from` where string - /// is `'static` and not longer than `MAX_INLINE_LEN` bytes. + /// Prefer this over [`CompactStr::new`] or [`CompactStr::from`] where + /// string is `'static` and not longer than [`MAX_INLINE_LEN`] bytes. /// /// # Panics - /// Panics if string is longer than `MAX_INLINE_LEN` bytes. + /// Panics if string is longer than [`MAX_INLINE_LEN`] bytes. /// /// # Examples /// ``` @@ -158,19 +174,36 @@ impl CompactStr { self.0.as_str() } - /// Convert a `CompactStr` into a `String`. + /// Convert a [`CompactStr`] into a [`String`]. #[inline] pub fn into_string(self) -> String { self.0.into_string() } - /// Get length of `CompactStr`. + /// Get length of [`CompactStr`]. + /// + /// # Examples + /// ``` + /// use oxc_span::CompactStr; + /// + /// assert_eq!(CompactStr::new("").len(), 0); + /// assert_eq!(CompactStr::new_const("").len(), 0); + /// assert_eq!(CompactStr::new("hello").len(), 5); + /// ``` #[inline] pub fn len(&self) -> usize { self.0.len() } - /// Check if a `CompactStr` is empty (0 length). + /// Check if a [`CompactStr`] is empty (0 length). + /// + /// # Examples + /// ``` + /// use oxc_span::CompactStr; + /// + /// assert!(CompactStr::new("").is_empty()); + /// assert!(!CompactStr::new("hello").is_empty()); + /// ``` #[inline] pub fn is_empty(&self) -> bool { self.0.is_empty()