ember_protocol/
serialize.rs1use bytes::BufMut;
8use bytes::BytesMut;
9
10use crate::types::Frame;
11
12impl Frame {
13 pub fn serialize(&self, dst: &mut BytesMut) {
18 match self {
19 Frame::Simple(s) => {
20 dst.put_u8(b'+');
21 dst.put_slice(s.as_bytes());
22 dst.put_slice(b"\r\n");
23 }
24 Frame::Error(msg) => {
25 dst.put_u8(b'-');
26 dst.put_slice(msg.as_bytes());
27 dst.put_slice(b"\r\n");
28 }
29 Frame::Integer(n) => {
30 dst.put_u8(b':');
31 write_i64(*n, dst);
32 dst.put_slice(b"\r\n");
33 }
34 Frame::Bulk(data) => {
35 dst.put_u8(b'$');
36 write_i64(data.len() as i64, dst);
37 dst.put_slice(b"\r\n");
38 dst.put_slice(data);
39 dst.put_slice(b"\r\n");
40 }
41 Frame::Array(items) => {
42 dst.put_u8(b'*');
43 write_i64(items.len() as i64, dst);
44 dst.put_slice(b"\r\n");
45 for item in items {
46 item.serialize(dst);
47 }
48 }
49 Frame::Null => {
50 dst.put_slice(b"_\r\n");
51 }
52 Frame::Map(pairs) => {
53 dst.put_u8(b'%');
54 write_i64(pairs.len() as i64, dst);
55 dst.put_slice(b"\r\n");
56 for (key, val) in pairs {
57 key.serialize(dst);
58 val.serialize(dst);
59 }
60 }
61 }
62 }
63}
64
65fn write_i64(val: i64, dst: &mut BytesMut) {
67 let mut buf = itoa::Buffer::new();
68 dst.put_slice(buf.format(val).as_bytes());
69}
70
71#[cfg(test)]
72mod tests {
73 use bytes::Bytes;
74
75 use super::*;
76
77 fn serialize(frame: &Frame) -> Vec<u8> {
78 let mut buf = BytesMut::new();
79 frame.serialize(&mut buf);
80 buf.to_vec()
81 }
82
83 #[test]
84 fn simple_string() {
85 assert_eq!(serialize(&Frame::Simple("OK".into())), b"+OK\r\n");
86 }
87
88 #[test]
89 fn error() {
90 assert_eq!(serialize(&Frame::Error("ERR bad".into())), b"-ERR bad\r\n");
91 }
92
93 #[test]
94 fn integer() {
95 assert_eq!(serialize(&Frame::Integer(42)), b":42\r\n");
96 assert_eq!(serialize(&Frame::Integer(-1)), b":-1\r\n");
97 assert_eq!(serialize(&Frame::Integer(0)), b":0\r\n");
98 }
99
100 #[test]
101 fn bulk_string() {
102 assert_eq!(
103 serialize(&Frame::Bulk(Bytes::from_static(b"hello"))),
104 b"$5\r\nhello\r\n"
105 );
106 }
107
108 #[test]
109 fn empty_bulk_string() {
110 assert_eq!(
111 serialize(&Frame::Bulk(Bytes::from_static(b""))),
112 b"$0\r\n\r\n"
113 );
114 }
115
116 #[test]
117 fn null() {
118 assert_eq!(serialize(&Frame::Null), b"_\r\n");
119 }
120
121 #[test]
122 fn array() {
123 let frame = Frame::Array(vec![Frame::Simple("hello".into()), Frame::Integer(42)]);
124 assert_eq!(serialize(&frame), b"*2\r\n+hello\r\n:42\r\n");
125 }
126
127 #[test]
128 fn empty_array() {
129 assert_eq!(serialize(&Frame::Array(vec![])), b"*0\r\n");
130 }
131
132 #[test]
133 fn map() {
134 let frame = Frame::Map(vec![(Frame::Simple("key".into()), Frame::Integer(1))]);
135 assert_eq!(serialize(&frame), b"%1\r\n+key\r\n:1\r\n");
136 }
137
138 #[test]
139 fn round_trip() {
140 use crate::parse::parse_frame;
141
142 let frames = vec![
143 Frame::Simple("OK".into()),
144 Frame::Error("ERR nope".into()),
145 Frame::Integer(i64::MAX),
146 Frame::Integer(i64::MIN),
147 Frame::Bulk(Bytes::from_static(b"binary\x00data")),
148 Frame::Bulk(Bytes::from_static(b"")),
149 Frame::Null,
150 Frame::Array(vec![
151 Frame::Integer(1),
152 Frame::Bulk(Bytes::from_static(b"two")),
153 Frame::Null,
154 ]),
155 Frame::Map(vec![
156 (Frame::Simple("a".into()), Frame::Integer(1)),
157 (Frame::Simple("b".into()), Frame::Integer(2)),
158 ]),
159 Frame::Array(vec![
160 Frame::Array(vec![Frame::Integer(1), Frame::Integer(2)]),
161 Frame::Array(vec![Frame::Integer(3)]),
162 ]),
163 ];
164
165 for original in &frames {
166 let mut buf = BytesMut::new();
167 original.serialize(&mut buf);
168
169 let (parsed, consumed) = parse_frame(&buf)
170 .expect("round-trip parse should not error")
171 .expect("round-trip parse should return a frame");
172
173 assert_eq!(&parsed, original, "round-trip failed for {original:?}");
174 assert_eq!(consumed, buf.len(), "should consume entire buffer");
175 }
176 }
177}