oxihuman_core/
message_pack_codec.rs1#![allow(dead_code)]
4
5#[derive(Debug, Clone, PartialEq)]
9pub enum MsgValue {
10 Nil,
11 Bool(bool),
12 Int(i64),
13 Float(f64),
14 Str(String),
15 Bin(Vec<u8>),
16 Array(Vec<MsgValue>),
17 Map(Vec<(MsgValue, MsgValue)>),
18}
19
20#[derive(Debug, Clone, PartialEq)]
22pub enum MsgError {
23 UnexpectedEnd,
24 UnknownFormat(u8),
25 InvalidUtf8,
26 LengthOverflow,
27}
28
29impl std::fmt::Display for MsgError {
30 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
31 match self {
32 Self::UnexpectedEnd => write!(f, "unexpected end of buffer"),
33 Self::UnknownFormat(b) => write!(f, "unknown format byte: 0x{b:02x}"),
34 Self::InvalidUtf8 => write!(f, "invalid UTF-8 in string"),
35 Self::LengthOverflow => write!(f, "length field overflows usize"),
36 }
37 }
38}
39
40pub fn encode(val: &MsgValue, buf: &mut Vec<u8>) {
42 match val {
43 MsgValue::Nil => buf.push(0xc0),
44 MsgValue::Bool(true) => buf.push(0xc3),
45 MsgValue::Bool(false) => buf.push(0xc2),
46 MsgValue::Int(i) => {
47 if (0..=127).contains(i) {
48 buf.push(*i as u8);
49 } else {
50 buf.push(0xd3);
51 buf.extend_from_slice(&i.to_be_bytes());
52 }
53 }
54 MsgValue::Float(f) => {
55 buf.push(0xcb);
56 buf.extend_from_slice(&f.to_bits().to_be_bytes());
57 }
58 MsgValue::Str(s) => {
59 let bytes = s.as_bytes();
60 if bytes.len() <= 31 {
61 buf.push(0xa0 | bytes.len() as u8);
62 } else {
63 buf.push(0xd9);
64 buf.push(bytes.len() as u8);
65 }
66 buf.extend_from_slice(bytes);
67 }
68 MsgValue::Bin(b) => {
69 buf.push(0xc4);
70 buf.push(b.len() as u8);
71 buf.extend_from_slice(b);
72 }
73 MsgValue::Array(arr) => {
74 buf.push(0x90 | arr.len().min(15) as u8);
75 for item in arr {
76 encode(item, buf);
77 }
78 }
79 MsgValue::Map(map) => {
80 buf.push(0x80 | map.len().min(15) as u8);
81 for (k, v) in map {
82 encode(k, buf);
83 encode(v, buf);
84 }
85 }
86 }
87}
88
89pub fn encoded_size(val: &MsgValue) -> usize {
91 match val {
92 MsgValue::Nil | MsgValue::Bool(_) => 1,
93 MsgValue::Int(i) => {
94 if (0..=127).contains(i) {
95 1
96 } else {
97 9
98 }
99 }
100 MsgValue::Float(_) => 9,
101 MsgValue::Str(s) => 1 + s.len(),
102 MsgValue::Bin(b) => 2 + b.len(),
103 MsgValue::Array(a) => 1 + a.iter().map(encoded_size).sum::<usize>(),
104 MsgValue::Map(m) => {
105 1 + m
106 .iter()
107 .map(|(k, v)| encoded_size(k) + encoded_size(v))
108 .sum::<usize>()
109 }
110 }
111}
112
113pub fn buffers_equal(a: &[u8], b: &[u8]) -> bool {
115 a == b
116}
117
118pub fn array_len(val: &MsgValue) -> usize {
120 if let MsgValue::Array(arr) = val {
121 arr.len()
122 } else {
123 0
124 }
125}
126
127pub fn is_nil(val: &MsgValue) -> bool {
129 matches!(val, MsgValue::Nil)
130}
131
132#[cfg(test)]
133mod tests {
134 use super::*;
135
136 #[test]
137 fn test_encode_nil() {
138 let mut buf = vec![];
140 encode(&MsgValue::Nil, &mut buf);
141 assert_eq!(buf, &[0xc0]);
142 }
143
144 #[test]
145 fn test_encode_bool_true() {
146 let mut buf = vec![];
148 encode(&MsgValue::Bool(true), &mut buf);
149 assert_eq!(buf, &[0xc3]);
150 }
151
152 #[test]
153 fn test_encode_bool_false() {
154 let mut buf = vec![];
156 encode(&MsgValue::Bool(false), &mut buf);
157 assert_eq!(buf, &[0xc2]);
158 }
159
160 #[test]
161 fn test_encode_positive_fixint() {
162 let mut buf = vec![];
164 encode(&MsgValue::Int(42), &mut buf);
165 assert_eq!(buf[0], 42);
166 }
167
168 #[test]
169 fn test_encode_str() {
170 let mut buf = vec![];
172 encode(&MsgValue::Str("hi".to_string()), &mut buf);
173 assert_eq!(buf[0], 0xa0 | 2);
174 }
175
176 #[test]
177 fn test_is_nil() {
178 assert!(is_nil(&MsgValue::Nil));
180 assert!(!is_nil(&MsgValue::Bool(false)));
181 }
182
183 #[test]
184 fn test_array_len() {
185 let v = MsgValue::Array(vec![MsgValue::Nil, MsgValue::Bool(true)]);
187 assert_eq!(array_len(&v), 2);
188 }
189
190 #[test]
191 fn test_encoded_size_nil() {
192 assert_eq!(encoded_size(&MsgValue::Nil), 1);
194 }
195
196 #[test]
197 fn test_buffers_equal() {
198 assert!(buffers_equal(&[1, 2, 3], &[1, 2, 3]));
200 assert!(!buffers_equal(&[1], &[2]));
201 }
202
203 #[test]
204 fn test_encode_bin() {
205 let mut buf = vec![];
207 encode(&MsgValue::Bin(vec![0xDE, 0xAD]), &mut buf);
208 assert_eq!(buf[0], 0xc4);
209 assert_eq!(buf[1], 2);
210 }
211}