revision/implementations/
string.rs1use core::str;
2
3use crate::{DeserializeRevisioned, Error, Revisioned, SerializeRevisioned};
4
5use super::vecs::serialize_bytes;
6
7impl SerializeRevisioned for String {
8 #[inline]
9 fn serialize_revisioned<W: std::io::Write>(&self, writer: &mut W) -> Result<(), Error> {
10 serialize_bytes(self.as_bytes(), writer)
11 }
12}
13
14impl DeserializeRevisioned for String {
15 #[inline]
16 fn deserialize_revisioned<R: std::io::Read>(reader: &mut R) -> Result<Self, Error> {
17 let bytes = Vec::<u8>::deserialize_revisioned(reader)?;
18 String::from_utf8(bytes).map_err(|x| Error::Utf8Error(x.utf8_error()))
19 }
20}
21
22impl Revisioned for String {
23 #[inline]
24 fn revision() -> u16 {
25 1
26 }
27}
28
29impl SerializeRevisioned for str {
30 #[inline]
31 fn serialize_revisioned<W: std::io::Write>(&self, writer: &mut W) -> Result<(), Error> {
32 serialize_bytes(self.as_bytes(), writer)
33 }
34}
35
36impl Revisioned for str {
37 #[inline]
38 fn revision() -> u16 {
39 1
40 }
41}
42
43impl SerializeRevisioned for char {
44 #[inline]
45 fn serialize_revisioned<W: std::io::Write>(&self, w: &mut W) -> Result<(), Error> {
46 let buffer = &mut [0u8; 4];
47 w.write_all(self.encode_utf8(buffer).as_bytes()).map_err(Error::Io)
48 }
49}
50
51impl DeserializeRevisioned for char {
52 #[inline]
53 fn deserialize_revisioned<R: std::io::Read>(r: &mut R) -> Result<Self, Error> {
54 let mut buffer = [0u8; 4];
55 r.read_exact(&mut buffer[..1]).map_err(Error::Io)?;
56
57 let len = CHAR_LENGTH[buffer[0] as usize];
58
59 if len == 0 {
60 return Err(Error::InvalidCharEncoding);
61 }
62
63 r.read_exact(&mut buffer[1..(len as usize)]).map_err(Error::Io)?;
64
65 str::from_utf8(&buffer[..(len as usize)])
66 .map_err(|_| Error::InvalidCharEncoding)
67 .map(|x| x.chars().next().unwrap())
68 }
69}
70
71impl Revisioned for char {
72 #[inline]
73 fn revision() -> u16 {
74 1
75 }
76}
77
78static CHAR_LENGTH: [u8; 256] = const {
79 let mut r = [0u8; 256];
80 let mut i = 0;
81 while i < 256 {
82 if i & 0b1000_0000 == 0 {
83 r[i] = 1;
84 } else if i & 0b1110_0000 == 0b1100_0000 {
85 r[i] = 2;
86 } else if i & 0b1111_0000 == 0b1110_0000 {
87 r[i] = 3;
88 } else if i & 0b1111_1000 == 0b1111_0000 {
89 r[i] = 4;
90 }
91
92 i += 1;
93 }
94
95 r
96};
97
98#[cfg(test)]
99mod tests {
100
101 use super::*;
102
103 use crate::implementations::assert_bincode_compat;
104
105 #[test]
106 fn test_string() {
107 let val = String::from("this is a test");
108 let mut mem: Vec<u8> = vec![];
109 val.serialize_revisioned(&mut mem).unwrap();
110 #[cfg(not(feature = "fixed-width-encoding"))]
111 assert_eq!(mem.len(), 15);
112 #[cfg(feature = "fixed-width-encoding")]
113 assert_eq!(mem.len(), 22);
114 let out =
115 <String as DeserializeRevisioned>::deserialize_revisioned(&mut mem.as_slice()).unwrap();
116 assert_eq!(val, out);
117 }
118
119 #[test]
120 fn test_char() {
121 let char = '𐃌';
122 let mut mem = Vec::new();
123 char.serialize_revisioned(&mut mem).unwrap();
124 let out = DeserializeRevisioned::deserialize_revisioned(&mut mem.as_slice()).unwrap();
125 assert_eq!(char, out);
126 }
127
128 #[test]
129 fn bincode_compat_char() {
130 assert_bincode_compat(&char::MAX);
131 assert_bincode_compat(&'\0');
132 assert_bincode_compat(&'z');
133 assert_bincode_compat(&'0');
134 assert_bincode_compat(&'ʘ');
136 assert_bincode_compat(&'ꚸ');
138 assert_bincode_compat(&'𐃌');
140 }
141
142 #[test]
143 fn bincode_compat_string() {
144 assert_bincode_compat(&char::MAX.to_string());
145 assert_bincode_compat(&'\0'.to_string());
146 assert_bincode_compat(&'z'.to_string());
147 assert_bincode_compat(&'0'.to_string());
148 assert_bincode_compat(&'ʘ'.to_string());
150 assert_bincode_compat(&'ꚸ'.to_string());
152 assert_bincode_compat(&'𐃌'.to_string());
154 }
155}