1use crate::BorrowAsIs;
2use core::borrow::{Borrow, BorrowMut};
3use core::cmp::Ordering;
4use core::fmt;
5use core::hash::{Hash, Hasher};
6use core::str::{from_utf8, from_utf8_mut};
7
8pub struct StringStub([u8; 0]);
12
13impl StringStub {
14 fn as_str(&self) -> &str {
15 from_utf8(&self.0).ok().unwrap()
16 }
17
18 fn as_mut_str(&mut self) -> &mut str {
19 from_utf8_mut(&mut self.0).ok().unwrap()
20 }
21}
22
23impl fmt::Debug for StringStub {
24 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
25 self.as_str().fmt(f)
26 }
27}
28
29impl Borrow<str> for StringStub {
30 fn borrow(&self) -> &str {
31 self.as_str()
32 }
33}
34
35impl BorrowMut<str> for StringStub {
36 fn borrow_mut(&mut self) -> &mut str {
37 self.as_mut_str()
38 }
39}
40
41impl PartialEq for StringStub {
42 fn eq(&self, other: &Self) -> bool {
43 self.as_str().eq(other.as_str())
44 }
45}
46
47impl Eq for StringStub {}
48
49impl PartialOrd for StringStub {
50 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
51 Some(self.cmp(other))
52 }
53}
54
55impl Ord for StringStub {
56 fn cmp(&self, other: &Self) -> Ordering {
57 self.as_str().cmp(other.as_str())
58 }
59}
60
61impl Hash for StringStub {
62 fn hash<H: Hasher>(&self, state: &mut H) {
63 self.as_str().hash(state);
64 }
65}
66
67impl BorrowAsIs for str {
68 type Is = str;
69}
70
71#[cfg(not(feature = "alloc"))]
72impl crate::ToOwned for str {
73 type Owned = StringStub;
74}
75
76#[cfg(feature = "alloc")]
77mod impl_for_string {
78 use crate::{AsIs, BorrowAsIs, Is};
79 use alloc::string::String;
80
81 impl BorrowAsIs for String {
82 type Is = String;
83 }
84
85 impl AsIs for String {
86 fn as_is<'a>(self) -> Is<'a, Self> {
87 Is::Owned(self)
88 }
89 }
90}
91
92#[cfg(test)]
93mod tests {
94 use super::*;
95 use char_buf::CharBuf;
96 use fmt::Write;
97 use siphasher::sip::SipHasher;
98
99 macro_rules! format {
100 ($($arg:tt)*) => {
101 {
102 let mut w = CharBuf::<2>::new();
103 write!(w, $($arg)*).unwrap();
104 w
105 }
106 };
107 }
108
109 #[test]
110 fn string_stub() {
111 let mut s = StringStub([]);
112
113 assert_eq!(Borrow::<str>::borrow(&s), "");
114 assert_eq!(BorrowMut::<str>::borrow_mut(&mut s), "");
115 assert_eq!(s < s, "" < "");
116 assert_eq!(s == s, "" == "");
117 assert_eq!(s.cmp(&s), "".cmp(&""));
118 assert_eq!(format!("{:?}", s), "\"\"");
119
120 let mut h1 = SipHasher::new();
121 s.hash(&mut h1);
122
123 let mut h2 = SipHasher::new();
124 "".hash(&mut h2);
125
126 assert_eq!(h1.finish(), h2.finish());
127 }
128}