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#[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 #[inline]
25 pub const fn new_const(s: &'static str) -> Self {
26 Atom(s)
27 }
28
29 #[inline]
31 pub const fn empty() -> Self {
32 Self::new_const("")
33 }
34}
35
36impl<'a> Atom<'a> {
37 #[inline]
39 pub fn as_str(&self) -> &'a str {
40 self.0
41 }
42
43 #[inline]
47 pub fn into_string(self) -> String {
48 String::from(self.as_str())
49 }
50
51 #[inline]
55 pub fn into_compact_str(self) -> CompactStr {
56 CompactStr::new(self.as_str())
57 }
58
59 #[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}