compact_str/features/
rkyv.rs

1#![cfg_attr(docsrs, doc(cfg(feature = "rkyv")))]
2
3use rkyv::rancor::{Fallible, Source};
4use rkyv::string::{ArchivedString, StringResolver};
5use rkyv::{Archive, Deserialize, DeserializeUnsized, Place, Serialize, SerializeUnsized};
6
7use crate::CompactString;
8
9impl Archive for CompactString {
10    type Archived = ArchivedString;
11    type Resolver = StringResolver;
12
13    #[inline]
14    fn resolve(&self, resolver: Self::Resolver, out: Place<Self::Archived>) {
15        ArchivedString::resolve_from_str(self.as_str(), resolver, out);
16    }
17}
18
19impl<S: Fallible + ?Sized> Serialize<S> for CompactString
20where
21    str: SerializeUnsized<S>,
22    S::Error: Source,
23{
24    #[inline]
25    fn serialize(&self, serializer: &mut S) -> Result<Self::Resolver, S::Error> {
26        ArchivedString::serialize_from_str(self.as_str(), serializer)
27    }
28}
29
30impl<D: Fallible + ?Sized> Deserialize<CompactString, D> for ArchivedString
31where
32    str: DeserializeUnsized<str, D>,
33{
34    #[inline]
35    fn deserialize(&self, _: &mut D) -> Result<CompactString, D::Error> {
36        Ok(self.as_str().into())
37    }
38}
39
40impl PartialEq<CompactString> for ArchivedString {
41    #[inline]
42    fn eq(&self, other: &CompactString) -> bool {
43        PartialEq::eq(self.as_str(), other.as_str())
44    }
45}
46
47impl PartialOrd<CompactString> for ArchivedString {
48    #[inline]
49    fn partial_cmp(&self, other: &CompactString) -> Option<core::cmp::Ordering> {
50        PartialOrd::partial_cmp(self.as_str(), other.as_str())
51    }
52}
53
54#[cfg(test)]
55mod tests {
56    use alloc::string::String;
57
58    use rkyv::string::ArchivedString;
59    use rkyv::{rancor, Archive};
60    use test_strategy::proptest;
61
62    use crate::CompactString;
63
64    #[cfg_attr(miri, ignore)] // https://github.com/rust-lang/unsafe-code-guidelines/issues/134
65    #[test]
66    fn test_roundtrip() {
67        const VALUE: &str = "Hello, 🌍!";
68
69        let bytes_compact = rkyv::to_bytes::<rancor::Error>(&CompactString::from(VALUE)).unwrap();
70        let bytes_control = rkyv::to_bytes::<rancor::Error>(&String::from(VALUE)).unwrap();
71        assert_eq!(&*bytes_compact, &*bytes_control);
72
73        let archived = rkyv::access::<ArchivedString, rancor::Error>(&bytes_compact).unwrap();
74        let compact = rkyv::deserialize::<CompactString, rancor::Error>(archived).unwrap();
75        let control = rkyv::deserialize::<String, rancor::Error>(archived).unwrap();
76        assert_eq!(archived, VALUE);
77        assert_eq!(compact, VALUE);
78        assert_eq!(control, VALUE);
79
80        let archived = rkyv::access::<ArchivedString, rancor::Error>(&bytes_compact).unwrap();
81        let compact = rkyv::deserialize::<CompactString, rancor::Error>(archived).unwrap();
82        let control = rkyv::deserialize::<String, rancor::Error>(archived).unwrap();
83        assert_eq!(archived, VALUE);
84        assert_eq!(compact, VALUE);
85        assert_eq!(control, VALUE);
86    }
87
88    #[cfg_attr(miri, ignore)]
89    #[proptest]
90    fn proptest_roundtrip(s: String) {
91        let bytes_compact = rkyv::to_bytes::<rancor::Error>(&CompactString::from(&s)).unwrap();
92        let bytes_control = rkyv::to_bytes::<rancor::Error>(&s).unwrap();
93        assert_eq!(&*bytes_compact, &*bytes_control);
94
95        let archived =
96            rkyv::access::<<CompactString as Archive>::Archived, rancor::Error>(&bytes_compact)
97                .unwrap();
98        let compact = rkyv::deserialize::<CompactString, rancor::Error>(archived).unwrap();
99        let control = rkyv::deserialize::<String, rancor::Error>(archived).unwrap();
100        assert_eq!(archived, &s);
101        assert_eq!(compact, s);
102        assert_eq!(control, s);
103
104        let archived =
105            rkyv::access::<<String as Archive>::Archived, rancor::Error>(&bytes_compact).unwrap();
106        let compact = rkyv::deserialize::<CompactString, rancor::Error>(archived).unwrap();
107        let control = rkyv::deserialize::<String, rancor::Error>(archived).unwrap();
108        assert_eq!(archived, &s);
109        assert_eq!(compact, s);
110        assert_eq!(control, s);
111    }
112}