as_is/foreign/
string.rs

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
8/// A stub for [`String`] used in `no_std` environments.
9///
10/// [`String`]: https://doc.rust-lang.org/alloc/string/struct.String.html
11pub 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}