1#[cfg(feature = "serde")]
4use serde::{Deserialize, Serialize};
5
6use std::fmt;
7
8#[derive(Clone, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
19#[cfg_attr(feature = "ustr", derive(Copy))]
20#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
21#[cfg_attr(feature = "serde", serde(transparent))]
22#[repr(transparent)]
23pub struct Token(
24 #[cfg(feature = "ustr")] pub ustr::Ustr,
25 #[cfg(not(feature = "ustr"))] pub std::string::String,
26);
27
28#[cfg(feature = "rkyv")]
32const _: () = {
33 use rkyv::{
34 Archive, Deserialize, Place, Serialize, SerializeUnsized,
35 rancor::{Fallible, Source},
36 string::{ArchivedString, StringResolver},
37 };
38
39 impl Archive for Token {
40 type Archived = ArchivedString;
41 type Resolver = StringResolver;
42
43 fn resolve(&self, resolver: Self::Resolver, out: Place<Self::Archived>) {
44 ArchivedString::resolve_from_str(self.as_str(), resolver, out);
45 }
46 }
47
48 impl<S: Fallible + ?Sized> Serialize<S> for Token
49 where
50 S::Error: Source,
51 str: SerializeUnsized<S>,
52 {
53 fn serialize(&self, serializer: &mut S) -> Result<Self::Resolver, S::Error> {
54 ArchivedString::serialize_from_str(self.as_str(), serializer)
55 }
56 }
57
58 impl<D: Fallible + ?Sized> Deserialize<Token, D> for ArchivedString {
59 fn deserialize(&self, _: &mut D) -> Result<Token, D::Error> {
60 Ok(Token::from(self.as_str()))
61 }
62 }
63};
64
65#[cfg(feature = "facet")]
71const _: () = {
72 use facet::{
73 Def, Facet, OxPtrConst, OxPtrUninit, ParseError, PtrConst, Shape, ShapeBuilder,
74 TryFromOutcome, Type, UserType, VTableIndirect,
75 };
76
77 unsafe fn display_token(
78 source: OxPtrConst,
79 f: &mut core::fmt::Formatter<'_>,
80 ) -> Option<core::fmt::Result> {
81 unsafe { Some(write!(f, "{}", source.get::<Token>())) }
82 }
83
84 unsafe fn partial_eq_token(a: OxPtrConst, b: OxPtrConst) -> Option<bool> {
85 unsafe { Some(a.get::<Token>() == b.get::<Token>()) }
86 }
87
88 unsafe fn try_from_token(
89 target: OxPtrUninit,
90 src_shape: &'static Shape,
91 src: PtrConst,
92 ) -> TryFromOutcome {
93 unsafe {
94 if src_shape.id == <&str as Facet>::SHAPE.id {
95 target.put(Token::new(src.get::<&str>()));
96 TryFromOutcome::Converted
97 } else if src_shape.id == <std::string::String as Facet>::SHAPE.id {
98 target.put(Token::from(src.read::<std::string::String>()));
99 TryFromOutcome::Converted
100 } else {
101 TryFromOutcome::Unsupported
102 }
103 }
104 }
105
106 unsafe fn parse_token(s: &str, target: OxPtrUninit) -> Option<Result<(), ParseError>> {
108 unsafe {
109 target.put(Token::new(s));
110 Some(Ok(()))
111 }
112 }
113
114 static TOKEN_VTABLE: VTableIndirect = VTableIndirect {
115 display: Some(display_token),
116 partial_eq: Some(partial_eq_token),
117 try_from: Some(try_from_token),
118 parse: Some(parse_token),
119 ..VTableIndirect::EMPTY
120 };
121
122 unsafe impl Facet<'_> for Token {
123 const SHAPE: &'static Shape = &const {
124 ShapeBuilder::for_sized::<Token>("Token")
125 .module_path("token_value_map::token")
126 .ty(Type::User(UserType::Opaque))
127 .def(Def::Scalar)
128 .vtable_indirect(&TOKEN_VTABLE)
129 .eq()
130 .build()
131 };
132 }
133};
134
135impl Token {
136 pub fn new(s: &str) -> Self {
138 Self::from(s)
139 }
140
141 pub fn as_str(&self) -> &str {
143 #[cfg(feature = "ustr")]
144 {
145 self.0.as_str()
146 }
147 #[cfg(not(feature = "ustr"))]
148 {
149 &self.0
150 }
151 }
152}
153
154impl fmt::Debug for Token {
155 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
156 write!(f, "Token({:?})", self.as_str())
157 }
158}
159
160impl fmt::Display for Token {
161 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
162 f.write_str(self.as_str())
163 }
164}
165
166impl std::ops::Deref for Token {
167 type Target = str;
168
169 fn deref(&self) -> &str {
170 self.as_str()
171 }
172}
173
174impl AsRef<str> for Token {
175 fn as_ref(&self) -> &str {
176 self.as_str()
177 }
178}
179
180impl std::borrow::Borrow<str> for Token {
181 fn borrow(&self) -> &str {
182 self.as_str()
183 }
184}
185
186impl From<&str> for Token {
187 fn from(s: &str) -> Self {
188 Self(s.into())
189 }
190}
191
192impl From<std::string::String> for Token {
193 fn from(s: std::string::String) -> Self {
194 #[cfg(feature = "ustr")]
195 {
196 Self(ustr::ustr(&s))
197 }
198 #[cfg(not(feature = "ustr"))]
199 {
200 Self(s)
201 }
202 }
203}
204
205#[cfg(feature = "ustr")]
206impl From<ustr::Ustr> for Token {
207 fn from(u: ustr::Ustr) -> Self {
208 Self(u)
209 }
210}
211
212#[cfg(feature = "ustr")]
213impl From<Token> for ustr::Ustr {
214 fn from(t: Token) -> Self {
215 t.0
216 }
217}