1use bytes::Bytes;
34
35use crate::error::{Error, Result};
36
37pub const INLINE_THRESHOLD: usize = 256;
40
41#[derive(Debug)]
43pub struct Encoder {
44 buf: Vec<u8>,
45 frames: Vec<Bytes>,
46 inline_threshold: usize,
47}
48
49impl Default for Encoder {
50 fn default() -> Self {
51 Self::new()
52 }
53}
54
55impl Encoder {
56 pub fn new() -> Self {
58 Self::with_inline_threshold(INLINE_THRESHOLD)
59 }
60
61 pub fn with_inline_threshold(inline_threshold: usize) -> Self {
63 Self {
64 buf: Vec::new(),
65 frames: Vec::new(),
66 inline_threshold,
67 }
68 }
69
70 pub fn into_frames(self) -> Vec<Bytes> {
72 let mut frames = Vec::with_capacity(1 + self.frames.len());
73 frames.push(Bytes::from(self.buf));
74 frames.extend(self.frames);
75 frames
76 }
77
78 pub fn into_single_frame(self) -> Vec<u8> {
84 assert!(
85 self.frames.is_empty(),
86 "message has {} out-of-band frames; use into_frames",
87 self.frames.len()
88 );
89 self.buf
90 }
91
92 pub fn nil(&mut self) {
94 self.buf.push(0xc0);
95 }
96
97 pub fn bool(&mut self, value: bool) {
99 self.buf.push(if value { 0xc3 } else { 0xc2 });
100 }
101
102 pub fn int(&mut self, value: i64) {
104 if value >= 0 {
105 self.uint(value as u64);
106 } else if value >= -32 {
107 self.buf.push(value as u8);
108 } else if value >= i64::from(i8::MIN) {
109 self.buf.push(0xd0);
110 self.buf.push(value as i8 as u8);
111 } else if value >= i64::from(i16::MIN) {
112 self.buf.push(0xd1);
113 self.buf.extend_from_slice(&(value as i16).to_be_bytes());
114 } else if value >= i64::from(i32::MIN) {
115 self.buf.push(0xd2);
116 self.buf.extend_from_slice(&(value as i32).to_be_bytes());
117 } else {
118 self.buf.push(0xd3);
119 self.buf.extend_from_slice(&value.to_be_bytes());
120 }
121 }
122
123 pub fn uint(&mut self, value: u64) {
125 if value < 0x80 {
126 self.buf.push(value as u8);
127 } else if value <= u64::from(u8::MAX) {
128 self.buf.push(0xcc);
129 self.buf.push(value as u8);
130 } else if value <= u64::from(u16::MAX) {
131 self.buf.push(0xcd);
132 self.buf.extend_from_slice(&(value as u16).to_be_bytes());
133 } else if value <= u64::from(u32::MAX) {
134 self.buf.push(0xce);
135 self.buf.extend_from_slice(&(value as u32).to_be_bytes());
136 } else {
137 self.buf.push(0xcf);
138 self.buf.extend_from_slice(&value.to_be_bytes());
139 }
140 }
141
142 pub fn float(&mut self, value: f64) {
144 self.buf.push(0xcb);
145 self.buf.extend_from_slice(&value.to_be_bytes());
146 }
147
148 pub fn str(&mut self, value: &str) {
150 let len = value.len();
151 if len < 32 {
152 self.buf.push(0xa0 | len as u8);
153 } else {
154 self.len_header(len, [0xd9, 0xda, 0xdb]);
155 }
156 self.buf.extend_from_slice(value.as_bytes());
157 }
158
159 pub fn bin(&mut self, value: &[u8]) {
161 self.len_header(value.len(), [0xc4, 0xc5, 0xc6]);
162 self.buf.extend_from_slice(value);
163 }
164
165 pub fn array_len(&mut self, len: usize) {
167 if len < 16 {
168 self.buf.push(0x90 | len as u8);
169 } else {
170 self.len_header16(len, [0xdc, 0xdd]);
171 }
172 }
173
174 pub fn map_len(&mut self, len: usize) {
176 if len < 16 {
177 self.buf.push(0x80 | len as u8);
178 } else {
179 self.len_header16(len, [0xde, 0xdf]);
180 }
181 }
182
183 pub fn ext(&mut self, code: i8, data: &[u8]) {
185 let fixed = match data.len() {
186 1 => Some(0xd4),
187 2 => Some(0xd5),
188 4 => Some(0xd6),
189 8 => Some(0xd7),
190 16 => Some(0xd8),
191 _ => None,
192 };
193 match fixed {
194 Some(marker) => self.buf.push(marker),
195 None => self.len_header(data.len(), [0xc7, 0xc8, 0xc9]),
196 }
197 self.buf.push(code as u8);
198 self.buf.extend_from_slice(data);
199 }
200
201 pub(crate) fn buffer(&mut self, ext_code: i8, data: &Bytes) {
204 if data.len() < self.inline_threshold {
205 self.ext(ext_code, data);
206 } else {
207 self.frames.push(data.clone());
208 self.uint(self.frames.len() as u64);
210 }
211 }
212
213 fn len_header(&mut self, len: usize, markers: [u8; 3]) {
214 if len <= usize::from(u8::MAX) {
215 self.buf.push(markers[0]);
216 self.buf.push(len as u8);
217 } else {
218 self.len_header16(len, [markers[1], markers[2]]);
219 }
220 }
221
222 fn len_header16(&mut self, len: usize, markers: [u8; 2]) {
223 if len <= usize::from(u16::MAX) {
224 self.buf.push(markers[0]);
225 self.buf.extend_from_slice(&(len as u16).to_be_bytes());
226 } else {
227 let len = u32::try_from(len).expect("msgpack lengths are at most u32::MAX");
228 self.buf.push(markers[1]);
229 self.buf.extend_from_slice(&len.to_be_bytes());
230 }
231 }
232}
233
234#[derive(Debug, Clone, Copy, PartialEq, Eq)]
236pub enum Kind {
237 Nil,
239 Bool,
241 Int,
243 Float,
245 Str,
247 Bin,
249 Array,
251 Map,
253 Ext,
255}
256
257impl Kind {
258 fn of(marker: u8) -> Option<Self> {
259 Some(match marker {
260 0x00..=0x7f | 0xcc..=0xd3 | 0xe0..=0xff => Kind::Int,
261 0x80..=0x8f | 0xde | 0xdf => Kind::Map,
262 0x90..=0x9f | 0xdc | 0xdd => Kind::Array,
263 0xa0..=0xbf | 0xd9..=0xdb => Kind::Str,
264 0xc0 => Kind::Nil,
265 0xc2 | 0xc3 => Kind::Bool,
266 0xc4..=0xc6 => Kind::Bin,
267 0xc7..=0xc9 | 0xd4..=0xd8 => Kind::Ext,
268 0xca | 0xcb => Kind::Float,
269 0xc1 => return None,
270 })
271 }
272
273 fn name(self) -> &'static str {
274 match self {
275 Kind::Nil => "nil",
276 Kind::Bool => "bool",
277 Kind::Int => "int",
278 Kind::Float => "float",
279 Kind::Str => "str",
280 Kind::Bin => "bin",
281 Kind::Array => "array",
282 Kind::Map => "map",
283 Kind::Ext => "ext",
284 }
285 }
286}
287
288#[derive(Debug, Clone, Copy, PartialEq, Eq)]
290pub enum Integer {
291 Signed(i64),
293 Unsigned(u64),
295}
296
297impl Integer {
298 fn wide(self) -> i128 {
299 match self {
300 Integer::Signed(value) => i128::from(value),
301 Integer::Unsigned(value) => i128::from(value),
302 }
303 }
304
305 pub fn narrow<T: TryFrom<i128>>(self, target: &'static str) -> Result<T> {
307 let value = self.wide();
308 T::try_from(value).map_err(|_| Error::IntRange { value, target })
309 }
310}
311
312#[derive(Debug, Clone)]
314pub struct Decoder<'f> {
315 frames: &'f [Bytes],
316 pos: usize,
317}
318
319impl<'f> Decoder<'f> {
320 pub fn new(frames: &'f [Bytes]) -> Self {
326 assert!(!frames.is_empty(), "a message has at least one frame");
327 Self { frames, pos: 0 }
328 }
329
330 fn buf(&self) -> &'f Bytes {
331 &self.frames[0]
332 }
333
334 pub fn finish(&self) -> Result<()> {
336 let left = self.buf().len() - self.pos;
337 if left == 0 {
338 Ok(())
339 } else {
340 Err(Error::TrailingBytes(left))
341 }
342 }
343
344 pub(crate) fn frame(&self, index: Integer) -> Result<Bytes> {
346 let index: usize = index.narrow("frame index")?;
347 if index == 0 || index >= self.frames.len() {
348 return Err(Error::Invalid(format!(
349 "frame index {index} out of range: the message has {} out-of-band frames",
350 self.frames.len() - 1
351 )));
352 }
353 Ok(self.frames[index].clone())
354 }
355
356 pub fn peek_tag(&self) -> Result<&'f str> {
359 let mut probe = self.clone();
360 if probe.array_len()? == 0 {
361 return Err(Error::MissingField("_tag"));
362 }
363 probe.str()
364 }
365
366 pub fn peek_kind(&self) -> Result<Kind> {
368 let marker = self.peek_marker()?;
369 Kind::of(marker)
370 .ok_or_else(|| Error::Invalid(format!("reserved marker 0xc1 at offset {}", self.pos)))
371 }
372
373 pub fn take_nil(&mut self) -> Result<bool> {
375 if self.peek_marker()? == 0xc0 {
376 self.pos += 1;
377 Ok(true)
378 } else {
379 Ok(false)
380 }
381 }
382
383 pub fn bool(&mut self) -> Result<bool> {
385 match self.peek_marker()? {
386 0xc2 => {
387 self.pos += 1;
388 Ok(false)
389 }
390 0xc3 => {
391 self.pos += 1;
392 Ok(true)
393 }
394 _ => Err(self.type_error("bool")),
395 }
396 }
397
398 pub fn integer(&mut self) -> Result<Integer> {
400 let marker = self.peek_marker()?;
401 let start = self.pos;
402 let value = match marker {
403 0x00..=0x7f => {
404 self.pos += 1;
405 Integer::Unsigned(u64::from(marker))
406 }
407 0xe0..=0xff => {
408 self.pos += 1;
409 Integer::Signed(i64::from(marker as i8))
410 }
411 0xcc => Integer::Unsigned(u64::from(self.be::<1>(start)?[0])),
412 0xcd => Integer::Unsigned(u64::from(u16::from_be_bytes(self.be(start)?))),
413 0xce => Integer::Unsigned(u64::from(u32::from_be_bytes(self.be(start)?))),
414 0xcf => Integer::Unsigned(u64::from_be_bytes(self.be(start)?)),
415 0xd0 => Integer::Signed(i64::from(self.be::<1>(start)?[0] as i8)),
416 0xd1 => Integer::Signed(i64::from(i16::from_be_bytes(self.be(start)?))),
417 0xd2 => Integer::Signed(i64::from(i32::from_be_bytes(self.be(start)?))),
418 0xd3 => Integer::Signed(i64::from_be_bytes(self.be(start)?)),
419 _ => return Err(self.type_error("int")),
420 };
421 Ok(value)
422 }
423
424 pub fn float(&mut self) -> Result<f64> {
426 let start = self.pos;
427 match self.peek_marker()? {
428 0xca => Ok(f64::from(f32::from_be_bytes(self.be(start)?))),
429 0xcb => Ok(f64::from_be_bytes(self.be(start)?)),
430 marker if Kind::of(marker) == Some(Kind::Int) => Ok(self.integer()?.wide() as f64),
431 _ => Err(self.type_error("float")),
432 }
433 }
434
435 pub fn str(&mut self) -> Result<&'f str> {
437 let marker = self.peek_marker()?;
438 let start = self.pos;
439 let len = match marker {
440 0xa0..=0xbf => {
441 self.pos += 1;
442 usize::from(marker & 0x1f)
443 }
444 0xd9 => usize::from(self.be::<1>(start)?[0]),
445 0xda => usize::from(u16::from_be_bytes(self.be(start)?)),
446 0xdb => u32::from_be_bytes(self.be(start)?) as usize,
447 _ => return Err(self.type_error("str")),
448 };
449 let bytes = self.take(start, len)?;
450 std::str::from_utf8(bytes).map_err(|_| Error::Utf8 { offset: start })
451 }
452
453 pub fn bin(&mut self) -> Result<Bytes> {
455 let marker = self.peek_marker()?;
456 let start = self.pos;
457 let len = match marker {
458 0xc4 => usize::from(self.be::<1>(start)?[0]),
459 0xc5 => usize::from(u16::from_be_bytes(self.be(start)?)),
460 0xc6 => u32::from_be_bytes(self.be(start)?) as usize,
461 _ => return Err(self.type_error("bin")),
462 };
463 self.take_shared(start, len)
464 }
465
466 pub fn array_len(&mut self) -> Result<usize> {
468 let marker = self.peek_marker()?;
469 let start = self.pos;
470 match marker {
471 0x90..=0x9f => {
472 self.pos += 1;
473 Ok(usize::from(marker & 0x0f))
474 }
475 0xdc => Ok(usize::from(u16::from_be_bytes(self.be(start)?))),
476 0xdd => Ok(u32::from_be_bytes(self.be(start)?) as usize),
477 _ => Err(self.type_error("array")),
478 }
479 }
480
481 pub fn map_len(&mut self) -> Result<usize> {
483 let marker = self.peek_marker()?;
484 let start = self.pos;
485 match marker {
486 0x80..=0x8f => {
487 self.pos += 1;
488 Ok(usize::from(marker & 0x0f))
489 }
490 0xde => Ok(usize::from(u16::from_be_bytes(self.be(start)?))),
491 0xdf => Ok(u32::from_be_bytes(self.be(start)?) as usize),
492 _ => Err(self.type_error("map")),
493 }
494 }
495
496 pub fn ext(&mut self) -> Result<(i8, Bytes)> {
498 let marker = self.peek_marker()?;
499 let start = self.pos;
500 let len = match marker {
501 0xd4 => 1,
502 0xd5 => 2,
503 0xd6 => 4,
504 0xd7 => 8,
505 0xd8 => 16,
506 0xc7 => usize::from(self.be::<1>(start)?[0]),
507 0xc8 => usize::from(u16::from_be_bytes(self.be(start)?)),
508 0xc9 => u32::from_be_bytes(self.be(start)?) as usize,
509 _ => return Err(self.type_error("ext")),
510 };
511 if (0xd4..=0xd8).contains(&marker) {
512 self.pos += 1;
513 }
514 let code = self.take(start, 1)?[0] as i8;
515 Ok((code, self.take_shared(start, len)?))
516 }
517
518 pub fn skip(&mut self) -> Result<()> {
520 let mut pending: usize = 1;
521 while pending > 0 {
522 pending -= 1;
523 match self.peek_kind()? {
524 Kind::Nil | Kind::Bool => self.pos += 1,
525 Kind::Int => {
526 self.integer()?;
527 }
528 Kind::Float => {
529 self.float()?;
530 }
531 Kind::Str => {
532 self.str()?;
533 }
534 Kind::Bin => {
535 self.bin()?;
536 }
537 Kind::Ext => {
538 self.ext()?;
539 }
540 Kind::Array => pending += self.array_len()?,
541 Kind::Map => pending += 2 * self.map_len()?,
542 }
543 }
544 Ok(())
545 }
546
547 fn peek_marker(&self) -> Result<u8> {
548 self.buf().get(self.pos).copied().ok_or(Error::Truncated {
549 offset: self.pos,
550 needed: 1,
551 })
552 }
553
554 fn be<const N: usize>(&mut self, start: usize) -> Result<[u8; N]> {
556 self.pos = start + 1;
557 let bytes = self.take(start, N)?;
558 Ok(bytes.try_into().expect("take returned N bytes"))
559 }
560
561 fn take(&mut self, start: usize, len: usize) -> Result<&'f [u8]> {
562 let buf: &'f [u8] = self.buf();
563 let end = self
564 .pos
565 .checked_add(len)
566 .filter(|end| *end <= buf.len())
567 .ok_or(Error::Truncated {
568 offset: start,
569 needed: (self.pos + len).saturating_sub(buf.len()),
570 })?;
571 let bytes = &buf[self.pos..end];
572 self.pos = end;
573 Ok(bytes)
574 }
575
576 fn take_shared(&mut self, start: usize, len: usize) -> Result<Bytes> {
577 let from = self.pos;
578 self.take(start, len)?;
579 Ok(self.buf().slice(from..self.pos))
580 }
581
582 fn type_error(&self, expected: &'static str) -> Error {
583 let found = self
584 .buf()
585 .get(self.pos)
586 .and_then(|marker| Kind::of(*marker))
587 .map_or("reserved marker", Kind::name);
588 Error::Type {
589 expected,
590 found,
591 offset: self.pos,
592 }
593 }
594}
595
596#[cfg(test)]
597mod tests {
598 use super::*;
599
600 fn encoded(write: impl FnOnce(&mut Encoder)) -> Vec<u8> {
601 let mut encoder = Encoder::new();
602 write(&mut encoder);
603 encoder.into_single_frame()
604 }
605
606 #[test]
608 fn integers_use_the_smallest_format() {
609 let cases: &[(i64, &[u8])] = &[
610 (127, &[0x7f]),
611 (128, &[0xcc, 0x80]),
612 (255, &[0xcc, 0xff]),
613 (256, &[0xcd, 0x01, 0x00]),
614 (65535, &[0xcd, 0xff, 0xff]),
615 (65536, &[0xce, 0x00, 0x01, 0x00, 0x00]),
616 (-1, &[0xff]),
617 (-32, &[0xe0]),
618 (-33, &[0xd0, 0xdf]),
619 (-128, &[0xd0, 0x80]),
620 (-129, &[0xd1, 0xff, 0x7f]),
621 (1 << 32, &[0xcf, 0, 0, 0, 1, 0, 0, 0, 0]),
622 ];
623 for (value, expected) in cases {
624 assert_eq!(encoded(|e| e.int(*value)), *expected, "{value}");
625 let frames = [Bytes::copy_from_slice(expected)];
626 let mut decoder = Decoder::new(&frames);
627 let decoded: i64 = decoder.integer().unwrap().narrow("i64").unwrap();
628 assert_eq!(decoded, *value);
629 decoder.finish().unwrap();
630 }
631 }
632
633 #[test]
634 fn strings_switch_to_str8_at_32_bytes() {
635 assert_eq!(encoded(|e| e.str(&"a".repeat(31)))[0], 0xbf);
636 assert_eq!(encoded(|e| e.str(&"a".repeat(32)))[..2], [0xd9, 32]);
637 }
638
639 #[test]
640 fn ext_uses_fixext_for_power_of_two_sizes() {
641 assert_eq!(encoded(|e| e.ext(3, b"abcd")), b"\xd6\x03abcd");
642 assert_eq!(encoded(|e| e.ext(3, b"abc")), b"\xc7\x03\x03abc");
643 }
644
645 #[test]
646 fn float_fields_accept_integers() {
647 let frames = [Bytes::from_static(&[0x03])];
648 assert_eq!(Decoder::new(&frames).float().unwrap(), 3.0);
649 }
650
651 #[test]
652 fn truncated_and_trailing_input_fail() {
653 let frames = [Bytes::from_static(&[0xcd, 0x01])];
654 assert!(matches!(
655 Decoder::new(&frames).integer(),
656 Err(Error::Truncated { .. })
657 ));
658 let frames = [Bytes::from_static(&[0x01, 0x02])];
659 let mut decoder = Decoder::new(&frames);
660 decoder.integer().unwrap();
661 assert!(matches!(decoder.finish(), Err(Error::TrailingBytes(1))));
662 }
663
664 #[test]
665 fn narrowing_overflow_fails() {
666 let frames = [Bytes::from_static(&[0xcf, 0x80, 0, 0, 0, 0, 0, 0, 0])];
667 let value = Decoder::new(&frames).integer().unwrap();
668 assert!(matches!(
669 value.narrow::<i64>("i64"),
670 Err(Error::IntRange { .. })
671 ));
672 assert_eq!(value.narrow::<u64>("u64").unwrap(), 1 << 63);
673 }
674
675 #[test]
676 fn skip_walks_nested_values() {
677 let mut encoder = Encoder::new();
678 encoder.array_len(2);
679 encoder.map_len(1);
680 encoder.str("k");
681 encoder.array_len(2);
682 encoder.float(1.5);
683 encoder.nil();
684 encoder.bin(b"xy");
685 encoder.int(7);
686 let frames = [Bytes::from(encoder.into_single_frame())];
687 let mut decoder = Decoder::new(&frames);
688 decoder.skip().unwrap();
689 assert_eq!(decoder.integer().unwrap(), Integer::Unsigned(7));
690 decoder.finish().unwrap();
691 }
692}