1use std::collections::HashSet;
20
21use vitaminc_protected::{Controlled, OpaqueDebug, Protected, TimingSafeEq};
22use zeroize::Zeroize;
23
24use crate::leaf::{self, Form, Item, ScalarError};
25use crate::plaintext::{
26 Encrypt, Error, FixedType, Logical, MapSink, Physical, SeqSink, Sink, SourceError,
27};
28
29pub const ARRAY: u8 = 0xF0;
31pub const OBJECT: u8 = 0xF1;
34pub const PASSTHROUGH: u8 = 0xF2;
37
38pub const MAX_DEPTH: usize = 128;
42
43#[derive(Clone, Copy, OpaqueDebug, TimingSafeEq)]
48pub struct Frame<'a> {
49 bytes: &'a [u8],
50}
51
52#[derive(Debug, Clone, Copy, PartialEq, Eq, thiserror::Error)]
54#[error("malformed frame")]
55pub struct FrameError;
56
57impl<'a> Frame<'a> {
58 pub fn parse(bytes: &'a [u8]) -> Result<Self, FrameError> {
63 let (frame, rest) = Self::parse_nested(bytes, 0)?;
64 if !rest.is_empty() {
65 return Err(FrameError);
66 }
67 Ok(frame)
68 }
69
70 pub fn parse_nested(bytes: &'a [u8], depth: usize) -> Result<(Self, &'a [u8]), FrameError> {
78 let mut cursor = Cursor { buf: bytes, pos: 0 };
79 skip(&mut cursor, depth)?;
80 let (frame, rest) = bytes.split_at(cursor.pos);
81 Ok((Self { bytes: frame }, rest))
82 }
83
84 pub fn as_bytes(&self) -> &'a [u8] {
85 self.bytes
86 }
87}
88
89struct Cursor<'a> {
90 buf: &'a [u8],
91 pos: usize,
92}
93
94impl<'a> Cursor<'a> {
95 fn peek(&self) -> Result<u8, FrameError> {
96 self.buf.get(self.pos).copied().ok_or(FrameError)
97 }
98
99 fn byte(&mut self) -> Result<u8, FrameError> {
100 let b = self.peek()?;
101 self.pos += 1;
102 Ok(b)
103 }
104
105 fn take(&mut self, n: usize) -> Result<&'a [u8], FrameError> {
106 let end = self.pos.checked_add(n).ok_or(FrameError)?;
107 let s = self.buf.get(self.pos..end).ok_or(FrameError)?;
108 self.pos = end;
109 Ok(s)
110 }
111
112 fn count(&mut self) -> Result<usize, FrameError> {
113 let b = self.take(4)?;
114 Ok(u32::from_le_bytes(b.try_into().map_err(|_| FrameError)?) as usize)
115 }
116
117 fn key(&mut self) -> Result<&'a str, FrameError> {
118 let len = self.count()?;
119 core::str::from_utf8(self.take(len)?).map_err(|_| FrameError)
120 }
121
122 fn scalar(&mut self) -> Result<Item<'a>, FrameError> {
123 let (item, used) =
124 leaf::read_item(&self.buf[self.pos..], Form::Frame).map_err(|_| FrameError)?;
125 self.pos += used;
126 Ok(item)
127 }
128
129 fn node(&mut self, depth: usize) -> Result<Frame<'a>, FrameError> {
131 let start = self.pos;
132 skip(self, depth)?;
133 Ok(Frame {
134 bytes: &self.buf[start..self.pos],
135 })
136 }
137}
138
139fn skip(c: &mut Cursor<'_>, depth: usize) -> Result<(), FrameError> {
141 if depth > MAX_DEPTH {
142 return Err(FrameError);
143 }
144 match c.peek()? {
145 ARRAY => {
146 c.byte()?;
147 for _ in 0..c.count()? {
148 skip(c, depth + 1)?;
149 }
150 }
151 OBJECT => {
152 c.byte()?;
153 let count = c.count()?;
154 let mut seen = HashSet::new();
155 for _ in 0..count {
156 let key = c.key()?;
157 if !seen.insert(key) {
158 return Err(FrameError);
159 }
160 skip(c, depth + 1)?;
161 }
162 }
163 PASSTHROUGH => {
164 c.byte()?;
165 skip(c, depth + 1)?;
166 }
167 _ => {
168 c.scalar()?;
169 }
170 }
171 Ok(())
172}
173
174const VALIDATED: &str = "frame was validated by Frame::parse";
176
177impl Encrypt for Frame<'_> {
180 fn visit<S: Sink>(self, sink: S) -> Result<S::Ok, S::Error> {
181 visit_node(
182 &mut Cursor {
183 buf: self.bytes,
184 pos: 0,
185 },
186 sink,
187 )
188 }
189}
190
191impl Encrypt for &Frame<'_> {
193 fn visit<S: Sink>(self, sink: S) -> Result<S::Ok, S::Error> {
194 (*self).visit(sink)
195 }
196}
197
198fn visit_node<S: Sink>(c: &mut Cursor<'_>, sink: S) -> Result<S::Ok, S::Error> {
202 match c.peek().expect(VALIDATED) {
203 ARRAY => {
204 c.byte().expect(VALIDATED);
205 let count = c.count().expect(VALIDATED);
206 let mut seq = sink.seq(Some(count))?;
207 for _ in 0..count {
208 visit_node(c, seq.element()?)?;
209 }
210 seq.end()
211 }
212 OBJECT => {
213 c.byte().expect(VALIDATED);
214 let count = c.count().expect(VALIDATED);
215 let mut map = sink.map(Some(count))?;
216 for _ in 0..count {
217 let key = c.key().expect(VALIDATED);
218 visit_node(c, map.entry(key)?)?;
219 }
220 map.end()
221 }
222 PASSTHROUGH => {
223 c.byte().expect(VALIDATED);
224 sink.passthrough(c.node(0).expect(VALIDATED))
225 }
226 _ => match c.scalar().expect(VALIDATED) {
227 Item::Scalar(ty, v) => sink.scalar(ty, v),
228 Item::TypedNull(ty) => sink.typed_null(ty),
229 },
230 }
231}
232
233#[derive(Clone, OpaqueDebug, TimingSafeEq)]
238pub struct PassthroughFrame(pub Vec<u8>);
239
240impl PassthroughFrame {
241 pub fn parse(&self) -> Result<Frame<'_>, FrameError> {
243 Frame::parse(&self.0)
244 }
245}
246
247impl Encrypt for PassthroughFrame {
248 fn visit<S: Sink>(self, sink: S) -> Result<S::Ok, S::Error> {
249 self.parse()
250 .map_err(|e| S::Error::source(SourceError::new(e)))?
251 .visit(sink)
252 }
253}
254
255impl Encrypt for &PassthroughFrame {
256 fn visit<S: Sink>(self, sink: S) -> Result<S::Ok, S::Error> {
257 self.parse()
258 .map_err(|e| S::Error::source(SourceError::new(e)))?
259 .visit(sink)
260 }
261}
262
263#[derive(Debug, thiserror::Error)]
265pub enum FrameWriteError {
266 #[error("value nests deeper than {MAX_DEPTH} levels")]
268 TooDeep,
269 #[error("text, bytes, a key or a count is too long for a u32")]
271 TooLong,
272 #[error("value is not valid for its logical type")]
274 Invalid,
275 #[error("container length does not match its children")]
277 CountMismatch,
278 #[error("duplicate key")]
280 DuplicateKey,
281 #[error("a child sink was dropped without a value")]
284 Unwritten,
285 #[error("a container was never ended")]
288 Unfinished,
289 #[error("source failed: {0}")]
291 Source(#[source] SourceError),
292}
293
294impl Error for FrameWriteError {
295 fn source(error: SourceError) -> Self {
296 Self::Source(error)
297 }
298}
299
300pub fn to_frame<P: Encrypt>(p: P) -> Result<Protected<Vec<u8>>, FrameWriteError> {
307 to_frame_at(p, 0)
308}
309
310pub(crate) fn to_frame_at<P: Encrypt>(
314 p: P,
315 depth: usize,
316) -> Result<Protected<Vec<u8>>, FrameWriteError> {
317 let mut out = Protected::new(Vec::new());
318 p.visit(FrameWriter {
319 out: out.risky_inner_mut(),
320 depth,
321 })?;
322 Frame::parse(out.risky_ref()).map_err(|_| FrameWriteError::Unfinished)?;
323 Ok(out)
324}
325
326pub struct FrameWriter<'o> {
329 out: &'o mut Vec<u8>,
330 depth: usize,
331}
332
333impl<'o> FrameWriter<'o> {
334 pub fn new(out: &'o mut Vec<u8>) -> Self {
335 Self { out, depth: 0 }
336 }
337
338 pub fn at_depth(out: &'o mut Vec<u8>, depth: usize) -> Self {
342 Self { out, depth }
343 }
344
345 pub fn depth(&self) -> usize {
348 self.depth
349 }
350
351 fn node(self, tag: u8) -> Result<&'o mut Vec<u8>, FrameWriteError> {
352 if self.depth > MAX_DEPTH {
353 return Err(FrameWriteError::TooDeep);
354 }
355 reserve(self.out, 1);
356 self.out.push(tag);
357 Ok(self.out)
358 }
359
360 fn container(self, tag: u8) -> Result<Count<'o>, FrameWriteError> {
361 let depth = self.depth;
362 reserve(self.out, 5);
363 let out = self.node(tag)?;
364 let at = out.len();
365 out.extend_from_slice(&[0; 4]);
366 Ok(Count {
367 out,
368 depth,
369 at,
370 n: 0,
371 open: None,
372 })
373 }
374}
375
376pub(crate) fn reserve(out: &mut Vec<u8>, additional: usize) {
380 if out.capacity() - out.len() >= additional {
381 return;
382 }
383 let capacity = out
386 .len()
387 .saturating_add(additional)
388 .max(out.len().saturating_mul(2))
389 .max(64);
390 let mut grown = Vec::with_capacity(capacity);
391 grown.extend_from_slice(out);
392 out.zeroize();
393 *out = grown;
394}
395
396fn write_len(out: &mut Vec<u8>, len: usize) -> Result<(), FrameWriteError> {
397 let len = u32::try_from(len).map_err(|_| FrameWriteError::TooLong)?;
398 out.extend_from_slice(&len.to_le_bytes());
399 Ok(())
400}
401
402struct Count<'o> {
404 out: &'o mut Vec<u8>,
405 depth: usize,
406 at: usize,
407 n: usize,
408 open: Option<usize>,
412}
413
414impl Count<'_> {
415 fn settle(&mut self) -> Result<(), FrameWriteError> {
416 match self.open.take() {
417 Some(start) if self.out.len() == start => Err(FrameWriteError::Unwritten),
418 _ => Ok(()),
419 }
420 }
421
422 fn child(&mut self) -> FrameWriter<'_> {
423 self.n += 1;
424 self.open = Some(self.out.len());
425 FrameWriter {
426 out: &mut *self.out,
427 depth: self.depth + 1,
428 }
429 }
430
431 fn end(mut self, expected: Option<usize>) -> Result<(), FrameWriteError> {
432 self.settle()?;
433 if expected.is_some_and(|e| e != self.n) {
434 return Err(FrameWriteError::CountMismatch);
435 }
436 let n = u32::try_from(self.n).map_err(|_| FrameWriteError::TooLong)?;
437 self.out[self.at..self.at + 4].copy_from_slice(&n.to_le_bytes());
438 Ok(())
439 }
440}
441
442impl<'o> Sink for FrameWriter<'o> {
443 type Ok = ();
444 type Error = FrameWriteError;
445 type Seq = FrameSeq<'o>;
446 type Map = FrameMap<'o>;
447
448 fn scalar(self, ty: Option<Logical>, v: Physical<'_>) -> Result<(), FrameWriteError> {
449 if self.depth > MAX_DEPTH {
450 return Err(FrameWriteError::TooDeep);
451 }
452 reserve(self.out, leaf::max_len(&v));
453 leaf::write(ty, v, Form::Frame, self.out).map_err(|e| match e {
454 ScalarError::Invalid => FrameWriteError::Invalid,
455 ScalarError::TooLong | ScalarError::Malformed => FrameWriteError::TooLong,
456 })
457 }
458
459 fn typed_null(self, _: FixedType) -> Result<(), FrameWriteError> {
467 self.scalar(None, Physical::Null)
468 }
469
470 fn seq(self, len: Option<usize>) -> Result<FrameSeq<'o>, FrameWriteError> {
471 Ok(FrameSeq {
472 count: self.container(ARRAY)?,
473 expected: len,
474 })
475 }
476
477 fn map(self, len: Option<usize>) -> Result<FrameMap<'o>, FrameWriteError> {
478 Ok(FrameMap {
479 count: self.container(OBJECT)?,
480 expected: len,
481 seen: HashSet::new(),
482 })
483 }
484
485 fn passthrough<P: Encrypt + Clone>(self, value: P) -> Result<(), FrameWriteError> {
486 let depth = self.depth;
487 let out = self.node(PASSTHROUGH)?;
488 value.visit(FrameWriter {
489 out,
490 depth: depth + 1,
491 })
492 }
493}
494
495pub struct FrameSeq<'o> {
496 count: Count<'o>,
497 expected: Option<usize>,
498}
499
500impl SeqSink for FrameSeq<'_> {
501 type Ok = ();
502 type Error = FrameWriteError;
503 type Element<'s>
504 = FrameWriter<'s>
505 where
506 Self: 's;
507
508 fn element(&mut self) -> Result<FrameWriter<'_>, FrameWriteError> {
509 self.count.settle()?;
510 Ok(self.count.child())
511 }
512
513 fn end(self) -> Result<(), FrameWriteError> {
514 self.count.end(self.expected)
515 }
516}
517
518pub struct FrameMap<'o> {
519 count: Count<'o>,
520 expected: Option<usize>,
521 seen: HashSet<String>,
522}
523
524impl MapSink for FrameMap<'_> {
525 type Ok = ();
526 type Error = FrameWriteError;
527 type Entry<'s>
528 = FrameWriter<'s>
529 where
530 Self: 's;
531
532 fn entry(&mut self, key: &str) -> Result<FrameWriter<'_>, FrameWriteError> {
533 self.count.settle()?;
534 if !self.seen.insert(key.to_owned()) {
535 return Err(FrameWriteError::DuplicateKey);
536 }
537 reserve(self.count.out, key.len().saturating_add(4));
538 write_len(self.count.out, key.len())?;
539 self.count.out.extend_from_slice(key.as_bytes());
540 Ok(self.count.child())
541 }
542
543 fn end(self) -> Result<(), FrameWriteError> {
544 self.count.end(self.expected)
545 }
546}
547
548#[cfg(test)]
549mod tests {
550 use super::*;
551 use crate::plaintext::record::{record, Event, Owned};
552 use crate::plaintext::{visit_seq, Int};
553 use std::collections::BTreeMap;
554
555 fn frame_of<P: Encrypt>(p: P) -> Vec<u8> {
556 to_frame(p).expect("frames").risky_ref().clone()
557 }
558
559 #[test]
560 fn a_frame_round_trips_through_write_and_walk() {
561 let mut value = BTreeMap::new();
562 value.insert("name", vec![Some("Ada"), None]);
563 value.insert("empty", vec![]);
564 let bytes = frame_of(value.clone());
565 let frame = Frame::parse(&bytes).expect("parses");
566 assert_eq!(record(frame).expect("walks"), record(value).expect("walks"));
567 let borrowed: &Frame<'_> = &frame;
569 assert_eq!(
570 record(borrowed).expect("walks"),
571 record(frame).expect("walks")
572 );
573 assert_eq!(frame_of(frame), bytes);
575 }
576
577 #[test]
578 fn container_framing_is_tag_count_children() {
579 assert_eq!(
580 frame_of(vec![1u16, 2]),
581 [ARRAY, 2, 0, 0, 0, 0x0F, 1, 0, 0x0F, 2, 0]
582 );
583 let mut map = BTreeMap::new();
584 map.insert("k", true);
585 assert_eq!(frame_of(map), [OBJECT, 1, 0, 0, 0, 1, 0, 0, 0, b'k', 0x03]);
586 }
587
588 #[derive(Clone)]
590 struct DropsAChild {
591 map: bool,
592 }
593
594 impl Encrypt for DropsAChild {
595 fn visit<S: Sink>(self, sink: S) -> Result<S::Ok, S::Error> {
596 if self.map {
597 let mut map = sink.map(None)?;
598 let _ = map.entry("a")?;
599 1u16.visit(map.entry("b")?)?;
600 map.end()
601 } else {
602 let mut seq = sink.seq(None)?;
603 1u16.visit(seq.element()?)?;
604 let _ = seq.element()?;
605 seq.end()
606 }
607 }
608 }
609
610 #[test]
611 fn a_dropped_child_sink_is_refused_not_framed() {
612 for map in [false, true] {
613 assert!(matches!(
614 to_frame(DropsAChild { map }),
615 Err(FrameWriteError::Unwritten)
616 ));
617 }
618 struct Doc;
621 impl Encrypt for Doc {
622 fn visit<S: Sink>(self, sink: S) -> Result<S::Ok, S::Error> {
623 let mut seq = sink.seq(Some(2))?;
624 1u16.visit(seq.element()?)?;
625 seq.element()?.passthrough(DropsAChild { map: false })?;
626 seq.end()
627 }
628 }
629 assert!(matches!(
630 crate::plan::<_, (), _>(Doc, "ctx"),
631 Err(crate::EncryptError::Shape(_))
632 ));
633 }
634
635 #[test]
636 fn reserve_moves_to_a_bigger_buffer_and_keeps_the_bytes() {
637 let mut out = vec![1u8, 2, 3];
638 out.shrink_to_fit();
639 reserve(&mut out, 10);
640 assert_eq!(out, [1, 2, 3]);
641 assert!(out.capacity() >= 13);
642 let before = out.as_ptr();
643 reserve(&mut out, 10);
644 assert_eq!(out.as_ptr(), before, "enough room already: no move");
645
646 let mut full = vec![7u8; 100];
648 full.shrink_to_fit();
649 reserve(&mut full, 1);
650 assert!(full.capacity() >= 101);
651 assert_eq!(full, [7u8; 100]);
652 }
653
654 #[test]
655 fn a_parsed_frame_is_its_bytes() {
656 let bytes = frame_of(vec![1u8, 2]);
657 let frame = Frame::parse(&bytes).expect("parses");
658 assert_eq!(frame.as_bytes(), &bytes[..]);
659 assert_eq!(FrameError.to_string(), "malformed frame");
660 }
661
662 #[test]
663 fn passthrough_is_framed_in_the_clear() {
664 struct Pass;
665 impl Encrypt for Pass {
666 fn visit<S: Sink>(self, sink: S) -> Result<S::Ok, S::Error> {
667 sink.passthrough("public")
668 }
669 }
670 let bytes = frame_of(Pass);
671 assert_eq!(
672 bytes,
673 [
674 PASSTHROUGH,
675 0x0A,
676 6,
677 0,
678 0,
679 0,
680 b'p',
681 b'u',
682 b'b',
683 b'l',
684 b'i',
685 b'c'
686 ]
687 );
688 assert_eq!(
689 record(Frame::parse(&bytes).expect("parses")).expect("walks"),
690 [
691 Event::Passthrough,
692 Event::Scalar(None, Owned::Text("public".into()))
693 ]
694 );
695 let owned = PassthroughFrame(bytes.clone());
696 assert_eq!(frame_of(owned.clone()), bytes);
697 assert_eq!(frame_of(&owned), bytes);
698 }
699
700 #[test]
701 fn unknown_lengths_are_patched_in() {
702 struct Unsized(Vec<u32>);
703 impl Encrypt for Unsized {
704 fn visit<S: Sink>(self, sink: S) -> Result<S::Ok, S::Error> {
705 visit_seq(sink, None, self.0)
706 }
707 }
708 assert_eq!(frame_of(Unsized(vec![1, 2, 3])), frame_of(vec![1u32, 2, 3]));
709 }
710
711 #[test]
712 fn a_wrong_length_hint_is_refused() {
713 struct Lies;
714 impl Encrypt for Lies {
715 fn visit<S: Sink>(self, sink: S) -> Result<S::Ok, S::Error> {
716 visit_seq(sink, Some(5), vec![1u32])
717 }
718 }
719 assert!(matches!(
720 to_frame(Lies),
721 Err(FrameWriteError::CountMismatch)
722 ));
723 }
724
725 #[test]
726 fn duplicate_keys_are_refused_both_ways() {
727 struct Dup;
728 impl Encrypt for Dup {
729 fn visit<S: Sink>(self, sink: S) -> Result<S::Ok, S::Error> {
730 let mut map = sink.map(None)?;
731 1u32.visit(map.entry("k")?)?;
732 2u32.visit(map.entry("k")?)?;
733 map.end()
734 }
735 }
736 assert!(matches!(to_frame(Dup), Err(FrameWriteError::DuplicateKey)));
737 let bytes = [
738 OBJECT, 2, 0, 0, 0, 1, 0, 0, 0, b'k', 0x00, 1, 0, 0, 0, b'k', 0x00,
739 ];
740 assert_eq!(Frame::parse(&bytes), Err(FrameError));
741 }
742
743 #[test]
744 fn malformed_frames_are_refused() {
745 assert_eq!(Frame::parse(&[]), Err(FrameError));
746 assert_eq!(Frame::parse(&[0x00, 0x00]), Err(FrameError));
747 assert_eq!(Frame::parse(&[ARRAY, 1, 0, 0, 0]), Err(FrameError));
748 assert_eq!(
749 Frame::parse(&[OBJECT, 1, 0, 0, 0, 1, 0, 0, 0, 0xFF, 0x00]),
750 Err(FrameError)
751 );
752 assert_eq!(Frame::parse(&[PASSTHROUGH]), Err(FrameError));
753 assert_eq!(
754 Frame::parse(&[0x0A, 2, 0, 0, 0, b'a']).err(),
755 Some(FrameError)
756 );
757 }
758
759 #[derive(Clone, Copy)]
760 enum Kind {
761 Seq,
762 Map,
763 Pass,
764 }
765
766 #[derive(Clone, Copy)]
769 struct Nest(Kind, usize);
770
771 impl Encrypt for Nest {
772 fn visit<S: Sink>(self, sink: S) -> Result<S::Ok, S::Error> {
773 let Nest(kind, n) = self;
774 if n == 0 {
775 return sink.seq(Some(0))?.end();
776 }
777 let inner = Nest(kind, n - 1);
778 match kind {
779 Kind::Seq => {
780 let mut seq = sink.seq(Some(1))?;
781 inner.visit(seq.element()?)?;
782 seq.end()
783 }
784 Kind::Map => {
785 let mut map = sink.map(Some(1))?;
786 inner.visit(map.entry("k")?)?;
787 map.end()
788 }
789 Kind::Pass => sink.passthrough(inner),
790 }
791 }
792 }
793
794 #[test]
795 fn depth_is_bounded_both_ways() {
796 for kind in [Kind::Seq, Kind::Map, Kind::Pass] {
797 let bytes = frame_of(Nest(kind, MAX_DEPTH));
799 assert!(Frame::parse(&bytes).is_ok());
800
801 assert!(matches!(
803 to_frame(Nest(kind, MAX_DEPTH + 1)),
804 Err(FrameWriteError::TooDeep)
805 ));
806 let mut deeper = match kind {
807 Kind::Seq => vec![ARRAY, 1, 0, 0, 0],
808 Kind::Map => vec![OBJECT, 1, 0, 0, 0, 1, 0, 0, 0, b'k'],
809 Kind::Pass => vec![PASSTHROUGH],
810 };
811 deeper.extend_from_slice(&bytes);
812 assert_eq!(Frame::parse(&deeper), Err(FrameError));
813 }
814
815 struct Deep(usize);
816 impl Encrypt for Deep {
817 fn visit<S: Sink>(self, sink: S) -> Result<S::Ok, S::Error> {
818 if self.0 == 0 {
819 return sink.scalar(None, Physical::Int(Int::U8(0)));
820 }
821 let mut seq = sink.seq(Some(1))?;
822 Deep(self.0 - 1).visit(seq.element()?)?;
823 seq.end()
824 }
825 }
826 assert!(to_frame(Deep(MAX_DEPTH)).is_ok());
827 assert!(matches!(
828 to_frame(Deep(MAX_DEPTH + 1)),
829 Err(FrameWriteError::TooDeep)
830 ));
831 }
832
833 #[test]
834 fn parse_nested_takes_one_node_and_returns_the_rest() {
835 let mut bytes = frame_of(vec![1u16, 2]);
836 let trailing = frame_of("after");
837 bytes.extend_from_slice(&trailing);
838
839 assert_eq!(Frame::parse(&bytes), Err(FrameError));
841 let (frame, rest) = Frame::parse_nested(&bytes, 0).expect("parses the prefix");
842 assert_eq!(frame.as_bytes(), &frame_of(vec![1u16, 2])[..]);
843 assert_eq!(rest, &trailing[..]);
844
845 let (frame, rest) = Frame::parse_nested(rest, 0).expect("parses the rest");
847 assert_eq!(frame.as_bytes(), &trailing[..]);
848 assert!(rest.is_empty());
849
850 assert_eq!(Frame::parse_nested(&[], 0), Err(FrameError));
852 }
853
854 #[test]
855 fn parse_nested_counts_the_carrier_in_the_depth_bound() {
856 let bytes = frame_of(Nest(Kind::Seq, MAX_DEPTH));
859 assert!(Frame::parse_nested(&bytes, 0).is_ok());
860 assert_eq!(Frame::parse_nested(&bytes, 1), Err(FrameError));
861 let scalar = frame_of(1u16);
863 assert!(Frame::parse_nested(&scalar, MAX_DEPTH).is_ok());
864 assert_eq!(Frame::parse_nested(&scalar, MAX_DEPTH + 1), Err(FrameError));
865 }
866
867 #[test]
868 fn a_writer_at_depth_counts_from_the_top() {
869 let mut out = Vec::new();
870 let writer = FrameWriter::at_depth(&mut out, 7);
871 assert_eq!(writer.depth(), 7);
872 let mut seq = writer.seq(Some(1)).expect("seq");
873 assert_eq!(seq.element().expect("element").depth(), 8);
874
875 let mut out = Vec::new();
877 assert!(FrameWriter::at_depth(&mut out, MAX_DEPTH)
878 .scalar(None, Physical::Bool(true))
879 .is_ok());
880 assert!(matches!(
881 FrameWriter::at_depth(&mut out, MAX_DEPTH + 1).scalar(None, Physical::Bool(true)),
882 Err(FrameWriteError::TooDeep)
883 ));
884 }
885
886 #[test]
887 fn a_frame_debugs_redacted_and_compares_by_value() {
888 let bytes = frame_of("secret");
889 let frame = Frame::parse(&bytes).expect("parses");
890 let shown = format!("{frame:?}");
891 assert!(
892 shown.contains("***") && !shown.contains("secret"),
893 "{shown}"
894 );
895 assert!(!shown.contains(&bytes.len().to_string()), "{shown}");
896 let pass = format!("{:?}", PassthroughFrame(bytes.clone()));
897 assert!(pass.contains("***") && !pass.contains("secret"), "{pass}");
898
899 let same = bytes.clone();
900 let other = frame_of("public");
901 assert_eq!(frame, Frame::parse(&same).expect("parses"));
902 assert_ne!(frame, Frame::parse(&other).expect("parses"));
903 assert_eq!(PassthroughFrame(bytes.clone()), PassthroughFrame(same));
904 assert_ne!(PassthroughFrame(bytes), PassthroughFrame(other));
905 }
906
907 #[test]
908 fn frame_write_errors_say_what_failed() {
909 let cases = [
910 (
911 FrameWriteError::TooDeep,
912 "value nests deeper than 128 levels",
913 ),
914 (
915 FrameWriteError::TooLong,
916 "text, bytes, a key or a count is too long for a u32",
917 ),
918 (
919 FrameWriteError::Invalid,
920 "value is not valid for its logical type",
921 ),
922 (
923 FrameWriteError::CountMismatch,
924 "container length does not match its children",
925 ),
926 (FrameWriteError::DuplicateKey, "duplicate key"),
927 (
928 FrameWriteError::Unwritten,
929 "a child sink was dropped without a value",
930 ),
931 (FrameWriteError::Unfinished, "a container was never ended"),
932 (
933 FrameWriteError::Source(SourceError::msg("getter threw")),
934 "source failed: getter threw",
935 ),
936 ];
937 for (error, message) in cases {
938 assert_eq!(error.to_string(), message);
939 }
940 fn is_error<E: core::error::Error>(_: &E) {}
941 is_error(&FrameWriteError::TooDeep);
942 use core::error::Error as _;
943 let sourced = FrameWriteError::Source(SourceError::msg("getter threw"));
944 assert_eq!(
945 sourced.source().map(|cause| cause.to_string()),
946 Some("getter threw".into())
947 );
948 assert!(FrameWriteError::TooDeep.source().is_none());
949 }
950}