1use core::str;
16use std::{borrow::Cow, ops::Deref};
17
18use inline_array::InlineArray;
19
20#[derive(PartialEq, Eq, PartialOrd, Ord, Clone)]
21#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
22pub struct InlineStr {
23 inner: InlineArray,
24}
25
26impl std::fmt::Display for InlineStr {
27 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
28 std::fmt::Display::fmt(&**self, f)
29 }
30}
31
32impl std::fmt::Debug for InlineStr {
33 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
34 std::fmt::Debug::fmt(&**self, f)
35 }
36}
37
38impl std::hash::Hash for InlineStr {
39 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
40 let as_str: &str = &*self;
41 as_str.hash(state);
42 }
43}
44
45impl From<String> for InlineStr {
46 fn from(value: String) -> Self {
47 Self {
48 inner: InlineArray::from(value.as_bytes()),
49 }
50 }
51}
52
53impl From<&String> for InlineStr {
54 fn from(value: &String) -> Self {
55 Self {
56 inner: InlineArray::from(value.as_bytes()),
57 }
58 }
59}
60
61impl From<&str> for InlineStr {
62 fn from(value: &str) -> Self {
63 Self {
64 inner: InlineArray::from(value.as_bytes()),
65 }
66 }
67}
68
69impl Deref for InlineStr {
70 type Target = str;
71
72 fn deref(&self) -> &Self::Target {
73 unsafe { str::from_utf8_unchecked(&self.inner) }
76 }
77}
78
79impl PartialEq<String> for InlineStr {
80 fn eq(&self, other: &String) -> bool {
81 (**self).eq(other)
82 }
83}
84
85impl PartialEq<InlineStr> for String {
86 fn eq(&self, other: &InlineStr) -> bool {
87 other.eq(self)
88 }
89}
90
91impl<'a> PartialEq<&'a str> for InlineStr {
92 fn eq(&self, other: &&'a str) -> bool {
93 (&&**self).eq(other)
94 }
95}
96
97impl PartialEq<InlineStr> for &str {
98 fn eq(&self, other: &InlineStr) -> bool {
99 other.eq(self)
100 }
101}
102
103impl PartialEq<Cow<'_, str>> for InlineStr {
104 fn eq(&self, other: &Cow<'_, str>) -> bool {
105 (**self).eq(other)
106 }
107}
108
109impl PartialEq<InlineStr> for Cow<'_, str> {
110 fn eq(&self, other: &InlineStr) -> bool {
111 other.eq(self)
112 }
113}
114
115#[cfg(test)]
116mod tests {
117 use std::hash::{BuildHasher, RandomState};
118
119 use super::*;
120
121 #[test]
122 fn test_basic_eq() {
123 let words = "the quick brown fox";
124 let inline_words = InlineStr::from(words);
125
126 assert_eq!(words, &*inline_words);
127 assert_eq!(words, inline_words);
128 assert_eq!(inline_words, words);
129 }
130
131 #[test]
132 fn test_basic_hash() {
133 let hasher = RandomState::new();
134
135 let words = "the quick brown fox";
136 let inline_words = InlineStr::from(words);
137
138 let words_hash = hasher.hash_one(words);
139 let words_hash_2 = hasher.hash_one(words);
140 let inline_hash = hasher.hash_one(inline_words);
141
142 assert_eq!(words_hash, words_hash_2);
143 assert_eq!(words_hash, inline_hash);
144 }
145}