1#![no_std]
30#![cfg_attr(docsrs, feature(doc_cfg))]
31#[cfg(feature = "alloc")]
32extern crate alloc;
33#[cfg(feature = "std")]
34extern crate std;
35
36mod dec;
38mod enc;
39pub use crate::dec::*;
40pub use crate::enc::*;
41
42#[inline]
45pub const fn max_encoding_overhead(source_len: usize) -> usize {
46 if source_len == 0 {
47 return 1;
48 }
49 source_len.div_ceil(254)
50}
51
52#[inline]
56pub const fn max_encoding_length(source_len: usize) -> usize {
57 source_len + max_encoding_overhead(source_len)
58}
59
60#[cfg(test)]
61mod tests {
62 use super::*;
63 use std::vec;
64 use std::vec::Vec;
65
66 const ENCODED_BUF: [u8; max_encoding_length(5)] = [0; max_encoding_length(5)];
68
69 pub(crate) fn test_encode_decode_free_functions(source: &[u8], encoded: &[u8]) {
70 let mut test_encoded = encoded.to_vec();
71 let mut test_decoded = source.to_vec();
72
73 test_encoded.iter_mut().for_each(|i| *i = 0x80);
75 encode(source, &mut test_encoded[..]);
76 test_encoded.push(0x00);
77
78 test_decoded.iter_mut().for_each(|i| *i = 0x80);
80 decode(&test_encoded, &mut test_decoded[..]).unwrap();
81 assert_eq!(encoded, &test_encoded[..test_encoded.len() - 1]);
82 assert_eq!(source, test_decoded);
83 }
84
85 pub(crate) fn test_decode_in_place(source: &[u8], encoded: &[u8]) {
86 let mut test_encoded = encoded.to_vec();
87 let report = decode_in_place_report(&mut test_encoded).unwrap();
88 assert_eq!(&test_encoded[0..report.frame_size()], source);
89 assert_eq!(report.parsed_size(), encoded.len());
90
91 test_encoded = encoded.to_vec();
92 let result = decode_in_place(&mut test_encoded).unwrap();
93 assert_eq!(&test_encoded[0..result], source);
94 }
95
96 pub(crate) fn test_pair(source: &[u8], encoded: &[u8]) {
97 test_encode_decode_free_functions(source, encoded);
98 test_decode_in_place(source, encoded);
99 }
100
101 #[test]
102 fn test_buf_len() {
103 assert_eq!(ENCODED_BUF.len(), 6);
104 }
105
106 #[test]
107 fn test_overhead_empty() {
108 assert_eq!(max_encoding_overhead(0), 1);
109 }
110
111 #[test]
112 fn test_overhead_one() {
113 assert_eq!(max_encoding_overhead(1), 1);
114 }
115
116 #[test]
117 fn test_overhead_larger() {
118 assert_eq!(max_encoding_overhead(253), 1);
119 assert_eq!(max_encoding_overhead(254), 1);
120 }
121
122 #[test]
123 fn test_overhead_two() {
124 assert_eq!(max_encoding_overhead(255), 2);
125 }
126
127 #[test]
128 fn stream_chunk_with_2_frames() {
129 let mut dest: [u8; 32] = [0; 32];
130 let data = b"hello world";
131 let data2 = b"second";
132 let mut encoded_data: [u8; 32] = [0; 32];
133 encoded_data[0] = 0x00;
135 let mut encoded_len = 1;
136 encoded_len += encode(data, &mut encoded_data[encoded_len..]);
137 encoded_data[encoded_len] = 0x00;
139 encoded_len += 1;
140 let first_frame_len = encoded_len;
141 encoded_data[encoded_len] = 0x00;
142 encoded_len += 1;
143 encoded_len += encode(data2, &mut encoded_data[encoded_len..]);
144 encoded_data[encoded_len] = 0x00;
145 encoded_len += 1;
146 let second_frame_len = encoded_len - first_frame_len;
147 let mut decoder = CobsDecoder::new(&mut dest);
148 let result = decoder.push(&encoded_data[0..encoded_len]).unwrap();
149 assert!(result.is_some());
150 let frame_report = result.unwrap();
151 assert_eq!(frame_report.frame_size(), data.len());
152 assert_eq!(frame_report.parsed_size(), first_frame_len);
153 let result = decoder
155 .push(&encoded_data[frame_report.parsed_size()..])
156 .unwrap();
157 assert!(result.is_some());
158 let frame_report = result.unwrap();
159 assert_eq!(frame_report.frame_size(), data2.len());
160 assert_eq!(frame_report.parsed_size(), second_frame_len);
161 }
162
163 #[test]
164 fn decoding_broken_packet() {
165 let mut dest: [u8; 32] = [0; 32];
166 let data = b"hello world";
167 let mut encoded_data: [u8; 32] = [0; 32];
168 encode(data, &mut encoded_data[1..]);
169 let mut encoded_len = encode(data, &mut encoded_data[6..]);
170 encoded_data[0] = 0x00;
172 encoded_data[5] = 0x00;
175 encoded_data[5 + encoded_len + 1] = 0x00;
176 encoded_len = 5 + encoded_len + 2;
177 let mut decoder = CobsDecoder::new(&mut dest);
178 for (idx, byte) in encoded_data.iter().take(encoded_len - 1).enumerate() {
179 if idx == 5 {
180 if let Err(DecodeError::InvalidFrame { decoded_bytes }) = decoder.push(&[*byte]) {
181 assert_eq!(decoded_bytes, 3);
182 }
183 } else {
184 decoder.push(&[*byte]).unwrap();
185 }
186 }
187 if let Ok(Some(msg_size)) = decoder.feed(encoded_data[encoded_len - 1]) {
188 assert_eq!(msg_size, data.len());
189 assert_eq!(data, &decoder.dest()[0..msg_size]);
190 } else {
191 panic!("decoding call did not yield expected frame");
192 }
193 }
194
195 #[test]
196 fn stream_roundtrip() {
197 for ct in 1..=1000 {
198 let source: alloc::vec::Vec<u8> =
199 (ct..2 * ct).map(|x: usize| (x & 0xFF) as u8).collect();
200
201 let mut dest = alloc::vec![0u8; max_encoding_length(source.len())];
202
203 let encoded_size = {
204 let mut encoder = CobsEncoder::new(&mut dest);
205
206 for chunk in source.chunks(17) {
207 encoder.push(chunk).unwrap();
208 }
209 encoder.finalize()
210 };
211
212 let mut decoded = source.clone();
213 decoded.iter_mut().for_each(|i| *i = 0x80);
214 let decoded_size = {
215 let mut decoder = CobsDecoder::new(&mut decoded);
216
217 for chunk in dest[0..encoded_size].chunks(11) {
218 decoder.push(chunk).unwrap();
219 }
220
221 match decoder.feed(0) {
222 Ok(sz_msg) => sz_msg.unwrap(),
223 Err(written) => panic!("decoding failed, {} bytes written to output", written),
224 }
225 };
226
227 assert_eq!(decoded_size, source.len());
228 assert_eq!(source, decoded);
229 }
230 }
231
232 #[test]
233 fn test_max_encoding_length() {
234 assert_eq!(max_encoding_length(0), 1);
235 assert_eq!(max_encoding_length(253), 254);
236 assert_eq!(max_encoding_length(254), 255);
237 assert_eq!(max_encoding_length(255), 257);
238 assert_eq!(max_encoding_length(254 * 2), 255 * 2);
239 assert_eq!(max_encoding_length(254 * 2 + 1), 256 * 2);
240 }
241
242 #[test]
243 fn wikipedia_ex_6() {
244 let mut unencoded: Vec<u8> = vec![];
245
246 (1..=0xFE).for_each(|i| unencoded.push(i));
247
248 let mut encoded: Vec<u8> = vec![];
250 encoded.push(0xFF);
251 (1..=0xFE).for_each(|i| encoded.push(i));
252
253 test_pair(&unencoded, &encoded);
254 }
255
256 #[test]
257 fn wikipedia_ex_7() {
258 let mut unencoded: Vec<u8> = vec![];
259
260 (0..=0xFE).for_each(|i| unencoded.push(i));
261
262 let mut encoded: Vec<u8> = vec![];
264 encoded.push(0x01);
265 encoded.push(0xFF);
266 (1..=0xFE).for_each(|i| encoded.push(i));
267
268 test_pair(&unencoded, &encoded);
269 }
270
271 #[test]
272 fn wikipedia_ex_8() {
273 let mut unencoded: Vec<u8> = vec![];
274
275 (1..=0xFF).for_each(|i| unencoded.push(i));
276
277 let mut encoded: Vec<u8> = vec![];
279 encoded.push(0xFF);
280 (1..=0xFE).for_each(|i| encoded.push(i));
281 encoded.push(0x02);
282 encoded.push(0xFF);
283
284 test_pair(&unencoded, &encoded);
285 }
286
287 #[test]
288 fn wikipedia_ex_9() {
289 let mut unencoded: Vec<u8> = vec![];
290
291 (2..=0xFF).for_each(|i| unencoded.push(i));
292 unencoded.push(0x00);
293
294 let mut encoded: Vec<u8> = vec![];
296 encoded.push(0xFF);
297 (2..=0xFF).for_each(|i| encoded.push(i));
298 encoded.push(0x01);
299 encoded.push(0x01);
300
301 test_pair(&unencoded, &encoded);
302 }
303
304 #[test]
305 fn wikipedia_ex_10() {
306 let mut unencoded: Vec<u8> = vec![];
307
308 (3..=0xFF).for_each(|i| unencoded.push(i));
309 unencoded.push(0x00);
310 unencoded.push(0x01);
311
312 let mut encoded: Vec<u8> = vec![];
314 encoded.push(0xFE);
315 (3..=0xFF).for_each(|i| encoded.push(i));
316 encoded.push(0x02);
317 encoded.push(0x01);
318
319 test_pair(&unencoded, &encoded);
320 }
321
322 #[test]
323 fn issue_15() {
324 let my_string_buf = b"\x00\x11\x00\x22";
327 let max_len = max_encoding_length(my_string_buf.len());
328 assert!(max_len < 128);
329 let mut buf = [0u8; 128];
330
331 let len = encode_with_sentinel(my_string_buf, &mut buf, b'\x00');
332
333 let cobs_buf = &buf[0..len];
334
335 let mut decoded_dest_buf = [0u8; 128];
336 let new_len = decode_with_sentinel(cobs_buf, &mut decoded_dest_buf, b'\x00').unwrap();
337 let decoded_buf = &decoded_dest_buf[0..new_len];
338
339 assert_eq!(my_string_buf, decoded_buf);
340 }
341
342 #[test]
343 fn issue_19_test_254_block_all_ones() {
344 let src: [u8; 254] = [1; 254];
345 let mut dest: [u8; 256] = [0; 256];
346 let encode_len = encode(&src, &mut dest);
347 assert_eq!(encode_len, 255);
348 let mut decoded: [u8; 254] = [1; 254];
349 let result = decode(&dest, &mut decoded).expect("decoding failed");
350 assert_eq!(result.frame_size(), 254);
351 assert_eq!(result.parsed_size(), 256);
352 assert_eq!(&src, &decoded);
353 }
354
355 #[cfg(feature = "alloc")]
356 mod alloc_tests {
357 use super::*;
358 use quickcheck::{TestResult, quickcheck};
359
360 #[test]
361 fn test_roundtrip_1() {
362 test_roundtrip(&[1, 2, 3]);
363 }
364
365 #[test]
366 fn test_roundtrip_2() {
367 for i in 0..5usize {
368 let mut v = Vec::new();
369 for j in 0..252 + i {
370 v.push(j as u8);
371 }
372 test_roundtrip(&v);
373 }
374 }
375
376 fn identity(source: Vec<u8>, sentinel: u8) -> TestResult {
377 let encoded = encode_vec_with_sentinel(&source[..], sentinel);
378
379 if source.is_empty() {
380 return TestResult::passed();
381 }
382
383 for x in encoded.iter() {
385 if *x == sentinel {
386 return TestResult::error("Sentinel found in encoded message.");
387 }
388 }
389
390 match decode_vec_with_sentinel(&encoded[..], sentinel) {
392 Ok(decoded) => {
393 if source == decoded {
394 TestResult::passed()
395 } else {
396 TestResult::failed()
397 }
398 }
399 Err(_) => TestResult::error("decoding Error"),
400 }
401 }
402
403 #[test]
404 fn test_encode_decode_with_sentinel() {
405 quickcheck(identity as fn(Vec<u8>, u8) -> TestResult);
406 }
407
408 #[test]
409 fn test_encode_decode() {
410 fn identity_default_sentinel(source: Vec<u8>) -> TestResult {
411 identity(source, 0)
412 }
413 quickcheck(identity_default_sentinel as fn(Vec<u8>) -> TestResult);
414 }
415
416 fn test_roundtrip(source: &[u8]) {
417 let mut encoded = encode_vec(source);
418 encoded.push(0x00);
420 let decoded = decode_vec(&encoded).expect("decode_vec");
421 assert_eq!(source, decoded);
422 }
423 }
424}