oxc_span/
atom.rs

1use std::{
2    borrow::{Borrow, Cow},
3    fmt, hash,
4    ops::Deref,
5};
6
7use oxc_allocator::{Allocator, CloneIn, FromIn};
8#[cfg(feature = "serialize")]
9use serde::Serialize;
10
11use crate::{CompactStr, ContentEq};
12
13/// An inlinable string for oxc_allocator.
14///
15/// Use [CompactStr] with [Atom::to_compact_str] or [Atom::into_compact_str] for
16/// the lifetimeless form.
17#[derive(Clone, Copy, Eq)]
18#[cfg_attr(feature = "serialize", derive(Serialize))]
19#[cfg_attr(feature = "serialize", serde(transparent))]
20pub struct Atom<'a>(&'a str);
21
22impl Atom<'static> {
23    /// Get an [`Atom`] containing a static string.
24    #[inline]
25    pub const fn new_const(s: &'static str) -> Self {
26        Atom(s)
27    }
28
29    /// Get an [`Atom`] containing the empty string (`""`).
30    #[inline]
31    pub const fn empty() -> Self {
32        Self::new_const("")
33    }
34}
35
36impl<'a> Atom<'a> {
37    /// Borrow a string slice.
38    #[inline]
39    pub fn as_str(&self) -> &'a str {
40        self.0
41    }
42
43    /// Convert this [`Atom`] into a [`String`].
44    ///
45    /// This is the explicit form of [`Into<String>`], which [`Atom`] also implements.
46    #[inline]
47    pub fn into_string(self) -> String {
48        String::from(self.as_str())
49    }
50
51    /// Convert this [`Atom`] into a [`CompactStr`].
52    ///
53    /// This is the explicit form of [`Into<CompactStr>`], which [`Atom`] also implements.
54    #[inline]
55    pub fn into_compact_str(self) -> CompactStr {
56        CompactStr::new(self.as_str())
57    }
58
59    /// Convert this [`Atom`] into a [`CompactStr`] without consuming `self`.
60    #[inline]
61    pub fn to_compact_str(&self) -> CompactStr {
62        CompactStr::new(self.as_str())
63    }
64}
65
66impl<'new_alloc> CloneIn<'new_alloc> for Atom<'_> {
67    type Cloned = Atom<'new_alloc>;
68
69    fn clone_in(&self, allocator: &'new_alloc Allocator) -> Self::Cloned {
70        Atom::from_in(self.as_str(), allocator)
71    }
72}
73
74impl<'alloc> FromIn<'alloc, &Atom<'alloc>> for Atom<'alloc> {
75    fn from_in(s: &Atom<'alloc>, _: &'alloc Allocator) -> Self {
76        *s
77    }
78}
79
80impl<'alloc> FromIn<'alloc, &str> for Atom<'alloc> {
81    fn from_in(s: &str, allocator: &'alloc Allocator) -> Self {
82        Self::from(&*allocator.alloc_str(s))
83    }
84}
85
86impl<'alloc> FromIn<'alloc, String> for Atom<'alloc> {
87    fn from_in(s: String, allocator: &'alloc Allocator) -> Self {
88        Self::from_in(s.as_str(), allocator)
89    }
90}
91
92impl<'alloc> FromIn<'alloc, &String> for Atom<'alloc> {
93    fn from_in(s: &String, allocator: &'alloc Allocator) -> Self {
94        Self::from_in(s.as_str(), allocator)
95    }
96}
97
98impl<'alloc> FromIn<'alloc, Cow<'_, str>> for Atom<'alloc> {
99    fn from_in(s: Cow<'_, str>, allocator: &'alloc Allocator) -> Self {
100        Self::from_in(&*s, allocator)
101    }
102}
103
104impl<'a> From<&'a str> for Atom<'a> {
105    fn from(s: &'a str) -> Self {
106        Self(s)
107    }
108}
109
110impl<'alloc> From<oxc_allocator::String<'alloc>> for Atom<'alloc> {
111    fn from(s: oxc_allocator::String<'alloc>) -> Self {
112        Self::from(s.into_bump_str())
113    }
114}
115
116impl<'a> From<Atom<'a>> for &'a str {
117    fn from(s: Atom<'a>) -> Self {
118        s.as_str()
119    }
120}
121
122impl From<Atom<'_>> for CompactStr {
123    #[inline]
124    fn from(val: Atom<'_>) -> Self {
125        val.into_compact_str()
126    }
127}
128
129impl From<Atom<'_>> for String {
130    #[inline]
131    fn from(val: Atom<'_>) -> Self {
132        val.into_string()
133    }
134}
135
136impl<'a> From<Atom<'a>> for Cow<'a, str> {
137    #[inline]
138    fn from(value: Atom<'a>) -> Self {
139        Cow::Borrowed(value.as_str())
140    }
141}
142
143impl Deref for Atom<'_> {
144    type Target = str;
145
146    fn deref(&self) -> &Self::Target {
147        self.as_str()
148    }
149}
150
151impl AsRef<str> for Atom<'_> {
152    fn as_ref(&self) -> &str {
153        self.as_str()
154    }
155}
156
157impl Borrow<str> for Atom<'_> {
158    fn borrow(&self) -> &str {
159        self.as_str()
160    }
161}
162
163impl<T: AsRef<str>> PartialEq<T> for Atom<'_> {
164    fn eq(&self, other: &T) -> bool {
165        self.as_str() == other.as_ref()
166    }
167}
168
169impl PartialEq<Atom<'_>> for &str {
170    fn eq(&self, other: &Atom<'_>) -> bool {
171        *self == other.as_str()
172    }
173}
174
175impl PartialEq<str> for Atom<'_> {
176    fn eq(&self, other: &str) -> bool {
177        self.as_str() == other
178    }
179}
180
181impl PartialEq<Atom<'_>> for Cow<'_, str> {
182    fn eq(&self, other: &Atom<'_>) -> bool {
183        self.as_ref() == other.as_str()
184    }
185}
186
187impl ContentEq for Atom<'_> {
188    fn content_eq(&self, other: &Self) -> bool {
189        self == other
190    }
191}
192
193impl hash::Hash for Atom<'_> {
194    fn hash<H: hash::Hasher>(&self, hasher: &mut H) {
195        self.as_str().hash(hasher);
196    }
197}
198
199impl fmt::Debug for Atom<'_> {
200    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
201        fmt::Debug::fmt(self.as_str(), f)
202    }
203}
204
205impl fmt::Display for Atom<'_> {
206    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
207        fmt::Display::fmt(self.as_str(), f)
208    }
209}