codeq/codec/impls/
string_impl.rs1use std::io;
2
3use byteorder::BigEndian;
4use byteorder::ReadBytesExt;
5use byteorder::WriteBytesExt;
6
7use crate::Decode;
8use crate::Encode;
9
10impl Encode for &str {
11 fn encode<W: io::Write>(&self, mut w: W) -> Result<usize, io::Error> {
12 let bytes = self.as_bytes();
13 w.write_u32::<BigEndian>(bytes.len() as u32)?;
14 w.write_all(bytes)?;
15 Ok(bytes.len() + 4)
16 }
17}
18
19impl Encode for String {
20 fn encode<W: io::Write>(&self, w: W) -> Result<usize, io::Error> {
21 self.as_str().encode(w)
22 }
23}
24
25impl Decode for String {
26 fn decode<R: io::Read>(mut r: R) -> Result<Self, io::Error> {
27 let len = r.read_u32::<BigEndian>()? as usize;
28 let mut buf = vec![0; len];
29 r.read_exact(&mut buf)?;
30 String::from_utf8(buf).map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))
31 }
32}
33
34#[cfg(test)]
35mod tests {
36
37 use std::io;
38
39 use crate::Decode;
40 use crate::Encode;
41
42 #[test]
43 fn test_string_codec() -> Result<(), io::Error> {
44 let s = "hello".to_string();
45 let mut buf = Vec::new();
46 let n = s.encode(&mut buf)?;
47 assert_eq!(n, buf.len());
48 assert_eq!(buf.len(), 4 + s.len());
49
50 let b = String::decode(&mut buf.as_slice())?;
51 assert_eq!(s, b);
52
53 Ok(())
54 }
55
56 #[test]
57 fn test_str_encode() -> Result<(), io::Error> {
58 check_str_encode("hello", b"\x00\x00\x00\x05hello")
59 }
60
61 #[test]
62 fn test_str_encode_empty() -> Result<(), io::Error> {
63 check_str_encode("", b"\x00\x00\x00\x00")
64 }
65
66 #[test]
67 fn test_str_encode_multibyte() -> Result<(), io::Error> {
68 let s = "你好";
69 assert_eq!(s.chars().count(), 2, "2 characters");
70 assert_eq!(s.len(), 6, "but 6 UTF-8 bytes");
71
72 let mut buf = Vec::new();
73 s.encode(&mut buf)?;
74
75 assert_eq!(&buf[..4], &[0u8, 0, 0, 6]);
77 assert_eq!(&buf[4..], s.as_bytes());
78 assert_eq!(String::decode(&mut buf.as_slice())?, s);
79
80 Ok(())
81 }
82
83 #[test]
84 fn test_str_matches_string_encode() -> Result<(), io::Error> {
85 for s in ["", "hello", "你好"] {
86 let mut from_str = Vec::new();
87 s.encode(&mut from_str)?;
88
89 let mut from_string = Vec::new();
90 s.to_string().encode(&mut from_string)?;
91
92 assert_eq!(
93 from_str, from_string,
94 "&str and String must encode identically: {s:?}"
95 );
96 }
97 Ok(())
98 }
99
100 fn check_str_encode(s: &str, expect: &[u8]) -> Result<(), io::Error> {
103 let mut buf = Vec::new();
104 let n = s.encode(&mut buf)?;
105
106 assert_eq!(buf, expect, "exact wire bytes for {s:?}");
107 assert_eq!(n, buf.len(), "returned count equals bytes written");
108 assert_eq!(buf.len(), 4 + s.len(), "4-byte prefix + UTF-8 byte length");
109
110 let decoded = String::decode(&mut buf.as_slice())?;
111 assert_eq!(decoded, s, "round-trips through String::decode");
112
113 Ok(())
114 }
115}