Skip to main content

token_value_map/
token.rs

1//! A string token type used as a key in token-value maps.
2
3#[cfg(feature = "facet")]
4use facet::Facet;
5#[cfg(feature = "serde")]
6use serde::{Deserialize, Serialize};
7
8use std::fmt;
9
10/// A string token used as a key in [`TokenValueMap`](crate::TokenValueMap) and
11/// [`GenericTokenValueMap`](crate::GenericTokenValueMap).
12///
13/// When the `ustr` feature is enabled, wraps [`Ustr`](ustr::Ustr) for
14/// O(1) equality via interned string comparison. Otherwise wraps [`String`].
15///
16/// Archives as [`ArchivedString`](rkyv::string::ArchivedString) via manual
17/// [`Archive`](rkyv::Archive) impl, so `rkyv` support works regardless of
18/// whether the `ustr` backend provides its own rkyv support.
19#[derive(Clone, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
20#[cfg_attr(feature = "ustr", derive(Copy))]
21#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
22#[cfg_attr(feature = "serde", serde(transparent))]
23#[cfg_attr(feature = "facet", derive(Facet))]
24#[cfg_attr(feature = "facet", facet(opaque))]
25#[repr(transparent)]
26pub struct Token(
27    #[cfg(feature = "ustr")] pub ustr::Ustr,
28    #[cfg(not(feature = "ustr"))] pub std::string::String,
29);
30
31// AIDEV-NOTE: Manual rkyv impl archives Token as ArchivedString regardless of
32// inner type (Ustr or String). This avoids requiring Ustr: Archive, which the
33// crates.io ustr (1.x) does not provide.
34#[cfg(feature = "rkyv")]
35const _: () = {
36    use rkyv::{
37        Archive, Deserialize, Place, Serialize, SerializeUnsized,
38        rancor::{Fallible, Source},
39        string::{ArchivedString, StringResolver},
40    };
41
42    impl Archive for Token {
43        type Archived = ArchivedString;
44        type Resolver = StringResolver;
45
46        fn resolve(&self, resolver: Self::Resolver, out: Place<Self::Archived>) {
47            ArchivedString::resolve_from_str(self.as_str(), resolver, out);
48        }
49    }
50
51    impl<S: Fallible + ?Sized> Serialize<S> for Token
52    where
53        S::Error: Source,
54        str: SerializeUnsized<S>,
55    {
56        fn serialize(&self, serializer: &mut S) -> Result<Self::Resolver, S::Error> {
57            ArchivedString::serialize_from_str(self.as_str(), serializer)
58        }
59    }
60
61    impl<D: Fallible + ?Sized> Deserialize<Token, D> for ArchivedString {
62        fn deserialize(&self, _: &mut D) -> Result<Token, D::Error> {
63            Ok(Token::from(self.as_str()))
64        }
65    }
66};
67
68impl Token {
69    /// Creates a new `Token` from a string slice.
70    pub fn new(s: &str) -> Self {
71        Self::from(s)
72    }
73
74    /// Returns the underlying string slice.
75    pub fn as_str(&self) -> &str {
76        #[cfg(feature = "ustr")]
77        {
78            self.0.as_str()
79        }
80        #[cfg(not(feature = "ustr"))]
81        {
82            &self.0
83        }
84    }
85}
86
87impl fmt::Debug for Token {
88    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
89        write!(f, "Token({:?})", self.as_str())
90    }
91}
92
93impl fmt::Display for Token {
94    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
95        f.write_str(self.as_str())
96    }
97}
98
99impl std::ops::Deref for Token {
100    type Target = str;
101
102    fn deref(&self) -> &str {
103        self.as_str()
104    }
105}
106
107impl AsRef<str> for Token {
108    fn as_ref(&self) -> &str {
109        self.as_str()
110    }
111}
112
113impl std::borrow::Borrow<str> for Token {
114    fn borrow(&self) -> &str {
115        self.as_str()
116    }
117}
118
119impl From<&str> for Token {
120    fn from(s: &str) -> Self {
121        Self(s.into())
122    }
123}
124
125impl From<std::string::String> for Token {
126    fn from(s: std::string::String) -> Self {
127        #[cfg(feature = "ustr")]
128        {
129            Self(ustr::ustr(&s))
130        }
131        #[cfg(not(feature = "ustr"))]
132        {
133            Self(s)
134        }
135    }
136}
137
138#[cfg(feature = "ustr")]
139impl From<ustr::Ustr> for Token {
140    fn from(u: ustr::Ustr) -> Self {
141        Self(u)
142    }
143}
144
145#[cfg(feature = "ustr")]
146impl From<Token> for ustr::Ustr {
147    fn from(t: Token) -> Self {
148        t.0
149    }
150}