1#![allow(dead_code)]
4
5#[derive(Debug, Clone, Copy, PartialEq, Eq)]
9pub enum CborMajor {
10 Uint = 0,
11 Negint = 1,
12 Bstr = 2,
13 Tstr = 3,
14 Array = 4,
15 Map = 5,
16 Tag = 6,
17 Float = 7,
18}
19
20#[derive(Debug, Clone, PartialEq)]
22pub enum CborValue {
23 Uint(u64),
24 Negint(i64),
25 Bstr(Vec<u8>),
26 Tstr(String),
27 Array(Vec<CborValue>),
28 Map(Vec<(CborValue, CborValue)>),
29 Bool(bool),
30 Null,
31 Float(f64),
32}
33
34#[derive(Debug, Clone, PartialEq)]
36pub enum CborError {
37 UnexpectedEnd,
38 InvalidMajor(u8),
39 InvalidUtf8,
40 NotImplemented(&'static str),
41}
42
43impl std::fmt::Display for CborError {
44 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
45 match self {
46 Self::UnexpectedEnd => write!(f, "unexpected end of CBOR input"),
47 Self::InvalidMajor(b) => write!(f, "invalid major type: {b}"),
48 Self::InvalidUtf8 => write!(f, "invalid UTF-8 in tstr"),
49 Self::NotImplemented(s) => write!(f, "not implemented: {s}"),
50 }
51 }
52}
53
54pub fn encode_cbor(val: &CborValue, buf: &mut Vec<u8>) {
56 match val {
57 CborValue::Uint(n) => encode_uint(*n, 0, buf),
58 CborValue::Negint(n) => {
59 let encoded = (-1 - n) as u64;
60 encode_uint(encoded, 1, buf);
61 }
62 CborValue::Bstr(b) => {
63 encode_uint(b.len() as u64, 2, buf);
64 buf.extend_from_slice(b);
65 }
66 CborValue::Tstr(s) => {
67 let bytes = s.as_bytes();
68 encode_uint(bytes.len() as u64, 3, buf);
69 buf.extend_from_slice(bytes);
70 }
71 CborValue::Array(arr) => {
72 encode_uint(arr.len() as u64, 4, buf);
73 for item in arr {
74 encode_cbor(item, buf);
75 }
76 }
77 CborValue::Map(map) => {
78 encode_uint(map.len() as u64, 5, buf);
79 for (k, v) in map {
80 encode_cbor(k, buf);
81 encode_cbor(v, buf);
82 }
83 }
84 CborValue::Bool(true) => buf.push(0xf5),
85 CborValue::Bool(false) => buf.push(0xf4),
86 CborValue::Null => buf.push(0xf6),
87 CborValue::Float(f) => {
88 buf.push(0xfb);
89 buf.extend_from_slice(&f.to_bits().to_be_bytes());
90 }
91 }
92}
93
94fn encode_uint(n: u64, major: u8, buf: &mut Vec<u8>) {
95 let mt = major << 5;
96 if n <= 23 {
97 buf.push(mt | n as u8);
98 } else if n <= 0xFF {
99 buf.push(mt | 24);
100 buf.push(n as u8);
101 } else if n <= 0xFFFF {
102 buf.push(mt | 25);
103 buf.extend_from_slice(&(n as u16).to_be_bytes());
104 } else if n <= 0xFFFF_FFFF {
105 buf.push(mt | 26);
106 buf.extend_from_slice(&(n as u32).to_be_bytes());
107 } else {
108 buf.push(mt | 27);
109 buf.extend_from_slice(&n.to_be_bytes());
110 }
111}
112
113pub fn cbor_encoded_len(val: &CborValue) -> usize {
115 let mut buf = vec![];
116 encode_cbor(val, &mut buf);
117 buf.len()
118}
119
120pub fn cbor_is_null(val: &CborValue) -> bool {
122 matches!(val, CborValue::Null)
123}
124
125pub fn major_of(val: &CborValue) -> CborMajor {
127 match val {
128 CborValue::Uint(_) => CborMajor::Uint,
129 CborValue::Negint(_) => CborMajor::Negint,
130 CborValue::Bstr(_) => CborMajor::Bstr,
131 CborValue::Tstr(_) => CborMajor::Tstr,
132 CborValue::Array(_) => CborMajor::Array,
133 CborValue::Map(_) => CborMajor::Map,
134 CborValue::Bool(_) | CborValue::Null | CborValue::Float(_) => CborMajor::Float,
135 }
136}
137
138pub fn cbor_array_len(val: &CborValue) -> usize {
140 if let CborValue::Array(a) = val {
141 a.len()
142 } else {
143 0
144 }
145}
146
147#[cfg(test)]
148mod tests {
149 use super::*;
150
151 #[test]
152 fn test_encode_null() {
153 let mut buf = vec![];
155 encode_cbor(&CborValue::Null, &mut buf);
156 assert_eq!(buf, &[0xf6]);
157 }
158
159 #[test]
160 fn test_encode_bool_true() {
161 let mut buf = vec![];
163 encode_cbor(&CborValue::Bool(true), &mut buf);
164 assert_eq!(buf, &[0xf5]);
165 }
166
167 #[test]
168 fn test_encode_uint_small() {
169 let mut buf = vec![];
171 encode_cbor(&CborValue::Uint(10), &mut buf);
172 assert_eq!(buf, &[10]);
173 }
174
175 #[test]
176 fn test_encode_tstr() {
177 let mut buf = vec![];
179 encode_cbor(&CborValue::Tstr("a".to_string()), &mut buf);
180 assert_eq!(buf[0], 0x61); assert_eq!(buf[1], b'a');
182 }
183
184 #[test]
185 fn test_cbor_is_null() {
186 assert!(cbor_is_null(&CborValue::Null));
188 assert!(!cbor_is_null(&CborValue::Bool(false)));
189 }
190
191 #[test]
192 fn test_major_of_uint() {
193 assert_eq!(major_of(&CborValue::Uint(0)), CborMajor::Uint);
195 }
196
197 #[test]
198 fn test_array_len() {
199 let v = CborValue::Array(vec![CborValue::Null, CborValue::Null]);
201 assert_eq!(cbor_array_len(&v), 2);
202 }
203
204 #[test]
205 fn test_encoded_len_float() {
206 assert_eq!(cbor_encoded_len(&CborValue::Float(0.0)), 9);
208 }
209
210 #[test]
211 fn test_encode_negint() {
212 let mut buf = vec![];
214 encode_cbor(&CborValue::Negint(-1), &mut buf);
215 assert_eq!(buf[0] >> 5, 1); }
217
218 #[test]
219 fn test_encode_bstr() {
220 let mut buf = vec![];
222 encode_cbor(&CborValue::Bstr(vec![0xAB]), &mut buf);
223 assert_eq!(buf[0] >> 5, 2); }
225}