1pub use crate::hash::InternedStringHash;
2use crate::lookup::{local_intern, local_lookup};
3use crate::serde_util::BorrowedStrVisitor;
4use serde::{Deserialize, Deserializer, Serialize, Serializer};
5use std::fmt::{Debug, Display};
6use std::ops::Deref;
7use std::str::FromStr;
8use std::sync::Arc;
9pub mod hash;
10pub mod lookup;
11mod serde_util;
12mod utils;
13
14#[derive(Clone, PartialEq, Eq, Hash, Copy)]
15pub struct InternedString {
16 hash: InternedStringHash,
17}
18
19impl InternedString {
20 pub fn new(s: impl Into<String>) -> InternedString {
21 let string = s.into();
22 let hash = InternedStringHash::from_str(&string);
23 if !hash.is_inlined() {
24 local_intern(hash, string);
25 }
26 InternedString { hash }
27 }
28 pub fn from_str(s: &str) -> InternedString {
29 let hash = InternedStringHash::from_str(s);
30 if !hash.is_inlined() {
31 let looked_up = local_lookup(hash);
32 if looked_up.is_none() {
33 let string = s.to_string();
34 local_intern(hash, string);
35 }
36 }
37 InternedString { hash }
38 }
39
40 pub unsafe fn from_hash(hash: InternedStringHash) -> InternedString {
42 InternedString { hash }
43 }
44 pub fn as_str(&self) -> &str {
45 if self.hash.is_inlined() {
46 self.hash.get_inlined_str()
47 } else {
48 local_lookup(self.hash).unwrap()
49 }
50 }
51 pub fn hash(&self) -> InternedStringHash {
52 self.hash
53 }
54}
55impl<'a> From<&'a str> for InternedString {
56 fn from(s: &'a str) -> Self {
57 InternedString::from_str(s)
58 }
59}
60impl From<String> for InternedString {
61 fn from(s: String) -> Self {
62 InternedString::new(s)
63 }
64}
65impl From<Box<str>> for InternedString {
66 fn from(s: Box<str>) -> Self {
67 let s = String::from(s);
68 InternedString::new(s)
69 }
70}
71impl From<Arc<str>> for InternedString {
72 fn from(s: Arc<str>) -> Self {
73 let s = String::from(s.as_ref());
74 InternedString::new(s)
75 }
76}
77impl Into<String> for InternedString {
78 fn into(self) -> String {
79 self.as_str().to_string()
80 }
81}
82impl Into<Box<str>> for InternedString {
83 fn into(self) -> Box<str> {
84 self.as_str().into()
85 }
86}
87impl Into<Arc<str>> for InternedString {
88 fn into(self) -> Arc<str> {
89 self.as_str().into()
90 }
91}
92impl FromStr for InternedString {
93 type Err = std::convert::Infallible;
94 fn from_str(s: &str) -> Result<Self, Self::Err> {
95 Ok(InternedString::from_str(s))
96 }
97}
98impl AsRef<str> for InternedString {
99 fn as_ref(&self) -> &str {
100 self.as_str()
101 }
102}
103impl Deref for InternedString {
104 type Target = str;
105
106 fn deref(&self) -> &Self::Target {
107 self.as_str()
108 }
109}
110impl Display for InternedString {
111 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
112 Display::fmt(self.as_str(), f)
113 }
114}
115impl Debug for InternedString {
116 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
117 Debug::fmt(self.as_str(), f)
118 }
119}
120impl Serialize for InternedString {
121 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
122 where
123 S: Serializer,
124 {
125 self.as_str().serialize(serializer)
126 }
127}
128
129impl<'de> Deserialize<'de> for InternedString {
130 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
131 where
132 D: Deserializer<'de>,
133 {
134 let val = deserializer.deserialize_str(BorrowedStrVisitor)?;
135 Ok(InternedString::from_str(val))
136 }
137}
138#[cfg(test)]
139mod tests {
140 use super::*;
141
142 #[test]
143 fn test_small_strings() {
144 let s = "hello";
145 let interned = InternedString::from_str(s);
146 assert_eq!(interned.as_str(), s);
147 let interned = InternedString::from_str(s);
148 assert_eq!(interned.as_str(), s);
149 }
150}