Skip to main content

yo_doc/
build.rs

1//! Writing a YOJB value.
2//!
3//! The builder is a stream of pushes rather than a tree, because the thing that
4//! feeds it most is a serializer walking a struct field by field and the thing
5//! that feeds it second most is a parser walking JSON text. Neither has a tree
6//! to hand and neither should have to build one.
7//!
8//! ```
9//! use yo_doc::{Builder, Value};
10//!
11//! let mut b = Builder::new();
12//! b.begin_object().unwrap();
13//! b.key(b"id").unwrap();
14//! b.int(7).unwrap();
15//! b.key(b"tags").unwrap();
16//! b.begin_array().unwrap();
17//! b.text("red").unwrap();
18//! b.text("blue").unwrap();
19//! b.end_array().unwrap();
20//! b.end_object().unwrap();
21//! let bytes = b.finish().unwrap();
22//!
23//! let v = Value::new(&bytes).unwrap();
24//! assert_eq!(v.get(b"id").unwrap().as_int(), Some(7));
25//! assert_eq!(v.get(b"tags").unwrap().at(1).unwrap().as_text(), Some("blue"));
26//! ```
27
28use yo_common::{Code, Error, Result};
29
30use crate::head::{self, ARRAY, COUNT_MAX, DEPTH_MAX, INTERNED, OFFSETS, SORTED, Tag};
31use crate::layout;
32use crate::read::{Value, key_order};
33
34/// A value under construction.
35///
36/// Reusable: [`Builder::finish`] hands back the bytes and [`Builder::clear`]
37/// puts it back to empty with its buffers intact, so a loop over a million
38/// documents allocates a handful of times rather than a million.
39#[derive(Debug, Default)]
40pub struct Builder {
41    /// Everything written so far. A container's children land here as they
42    /// arrive and are moved into place once, when the container closes.
43    out: Vec<u8>,
44    /// One entry per container that has been begun and not yet ended.
45    open: Vec<Open>,
46    /// Pending members, for every open container at once. A container owns the
47    /// tail of this from its own `first`.
48    members: Vec<Member>,
49    /// Pending key bytes, same arrangement.
50    keys: Vec<u8>,
51    /// Where a closing container parks its children while it writes its entry
52    /// table in front of them.
53    scratch: Vec<u8>,
54    /// The key the next value will be stored under.
55    pending: Option<Member>,
56    /// Ticks once per member, so that a sort can be made stable by hand and two
57    /// members with the same key can be told apart.
58    seq: u32,
59}
60
61/// A container that has been begun and not yet ended.
62#[derive(Debug)]
63struct Open {
64    /// Where its header goes. Its children start four bytes later.
65    at: usize,
66    /// `ARRAY` and `INTERNED`, decided when it was begun.
67    flags: u32,
68    /// The first of its members in [`Builder::members`].
69    first: usize,
70    /// Where its members' keys start in [`Builder::keys`]. Its own key, if it
71    /// has one, is below this.
72    keys_at: usize,
73    /// The key it will be stored under in its own parent.
74    key: Member,
75}
76
77/// One element of a container, while the container is still open.
78#[derive(Debug, Default, Clone, Copy)]
79struct Member {
80    /// The element's own header, copied into the entry table at close.
81    head: u32,
82    /// Where the element's bytes are in [`Builder::out`] right now.
83    at: u32,
84    /// How many bytes they are.
85    len: u32,
86    /// Where its key is in [`Builder::keys`], and how long.
87    key_at: u32,
88    key_len: u32,
89    /// Its intern table id, when the container has interned keys.
90    id: u16,
91    /// Insertion order.
92    seq: u32,
93}
94
95impl Builder {
96    /// An empty builder.
97    #[must_use]
98    pub fn new() -> Builder {
99        Builder::default()
100    }
101
102    /// Empty, with room for `bytes` of value already reserved.
103    #[must_use]
104    pub fn with_capacity(bytes: usize) -> Builder {
105        Builder {
106            out: Vec::with_capacity(bytes),
107            ..Builder::default()
108        }
109    }
110
111    /// Throw away everything written so far and keep the buffers.
112    pub fn clear(&mut self) {
113        self.out.clear();
114        self.open.clear();
115        self.members.clear();
116        self.keys.clear();
117        self.pending = None;
118        self.seq = 0;
119    }
120
121    /// The finished value.
122    ///
123    /// An error here means the value is not finished: a container was begun and
124    /// not ended, a key was written with no value after it, or nothing was
125    /// written at all.
126    pub fn finish(&mut self) -> Result<&[u8]> {
127        if let Some(open) = self.open.last() {
128            let what = if open.flags & ARRAY != 0 {
129                "array"
130            } else {
131                "object"
132            };
133            return Err(Error::fmt(
134                Code::Invalid,
135                format_args!("the document ends inside an unclosed {what}"),
136            ));
137        }
138        if self.pending.is_some() {
139            return Err(Error::new(Code::Invalid, "a key with no value after it"));
140        }
141        if self.out.is_empty() {
142            return Err(Error::new(Code::Invalid, "the document holds no value"));
143        }
144        Ok(&self.out)
145    }
146
147    /// Write `null`.
148    pub fn null(&mut self) -> Result<()> {
149        self.scalar(Tag::Null, &[])
150    }
151
152    /// Write a boolean.
153    pub fn bool(&mut self, v: bool) -> Result<()> {
154        self.scalar(if v { Tag::True } else { Tag::False }, &[])
155    }
156
157    /// Write an integer, in as few bytes as it fits in.
158    pub fn int(&mut self, v: i64) -> Result<()> {
159        let raw = v.to_le_bytes();
160        self.scalar(Tag::Int, &raw[..int_width(v)])
161    }
162
163    /// Write a float.
164    pub fn float(&mut self, v: f64) -> Result<()> {
165        self.scalar(Tag::Float, &v.to_le_bytes())
166    }
167
168    /// Write a string.
169    pub fn text(&mut self, v: &str) -> Result<()> {
170        self.scalar(Tag::Text, v.as_bytes())
171    }
172
173    /// Write a string that is already bytes.
174    ///
175    /// The bytes are stored as they are and are not checked, so a caller that
176    /// hands over something that is not UTF-8 gets a document whose
177    /// [`Value::as_text`] answers `None` where it should have answered a
178    /// string. It exists because RESP carries strings as bytes and re-checking
179    /// what a client already sent is a copy nobody asked for.
180    pub fn text_bytes(&mut self, v: &[u8]) -> Result<()> {
181        self.scalar(Tag::Text, v)
182    }
183
184    /// Copy a value that is already encoded.
185    ///
186    /// This is how a path update writes the parts of a document it is not
187    /// changing: they are already in the right form, so they are memcpy and not
188    /// a re-encode.
189    pub fn embed(&mut self, v: &Value<'_>) -> Result<()> {
190        let bytes = v
191            .as_bytes()
192            .ok_or_else(|| Error::new(Code::Corrupt, "the value being copied is not readable"))?;
193        self.start()?;
194        let at = self.out.len();
195        self.out.extend_from_slice(bytes);
196        self.record(at)
197    }
198
199    /// Begin an object. Every value inside it needs a [`Builder::key`] first.
200    pub fn begin_object(&mut self) -> Result<()> {
201        self.begin(0)
202    }
203
204    /// Begin an object whose keys are ids from a collection's intern table.
205    ///
206    /// Every value inside it needs a [`Builder::key_id`] first. This is what a
207    /// typed collection writes, and it is where the size of a document
208    /// collection mostly goes: the same twenty field names on every document
209    /// cost two bytes each here instead of their bytes.
210    pub fn begin_object_interned(&mut self) -> Result<()> {
211        self.begin(INTERNED)
212    }
213
214    /// Begin an array.
215    pub fn begin_array(&mut self) -> Result<()> {
216        self.begin(ARRAY)
217    }
218
219    /// End the object begun by the matching [`Builder::begin_object`].
220    pub fn end_object(&mut self) -> Result<()> {
221        self.end(false)
222    }
223
224    /// End the array begun by the matching [`Builder::begin_array`].
225    pub fn end_array(&mut self) -> Result<()> {
226        self.end(true)
227    }
228
229    /// The key the next value goes under.
230    ///
231    /// Members may be written in any order, since the container sorts them when
232    /// it closes. Writing the same key twice keeps the last one, which is what
233    /// every JSON parser does and what `JSON.SET` has to do.
234    pub fn key(&mut self, key: &[u8]) -> Result<()> {
235        let open = self.expect_object()?;
236        if open.flags & INTERNED != 0 {
237            return Err(Error::new(
238                Code::Invalid,
239                "this object takes key ids, not key bytes",
240            ));
241        }
242        if key.len() > COUNT_MAX {
243            return Err(Error::new(Code::Full, "the key is longer than 16 MiB"));
244        }
245        self.stash(Member {
246            key_at: u32::try_from(self.keys.len()).map_err(|_| too_big())?,
247            key_len: key.len() as u32,
248            ..Member::default()
249        })?;
250        self.keys.extend_from_slice(key);
251        Ok(())
252    }
253
254    /// The intern table id the next value goes under.
255    pub fn key_id(&mut self, id: u16) -> Result<()> {
256        let open = self.expect_object()?;
257        if open.flags & INTERNED == 0 {
258            return Err(Error::new(
259                Code::Invalid,
260                "this object takes key bytes, not key ids",
261            ));
262        }
263        self.stash(Member {
264            id,
265            ..Member::default()
266        })
267    }
268
269    /// The innermost open container, if it is an object.
270    fn expect_object(&self) -> Result<&Open> {
271        match self.open.last() {
272            Some(open) if open.flags & ARRAY == 0 => Ok(open),
273            Some(_) => Err(Error::new(Code::Invalid, "an array element has no key")),
274            None => Err(Error::new(Code::Invalid, "there is no object open")),
275        }
276    }
277
278    /// Park a key until the value that goes under it arrives.
279    fn stash(&mut self, key: Member) -> Result<()> {
280        if self.pending.is_some() {
281            return Err(Error::new(Code::Invalid, "two keys in a row"));
282        }
283        self.pending = Some(key);
284        Ok(())
285    }
286
287    /// Write a scalar's header and payload.
288    fn scalar(&mut self, tag: Tag, payload: &[u8]) -> Result<()> {
289        if payload.len() > COUNT_MAX {
290            return Err(Error::new(Code::Full, "the value is longer than 16 MiB"));
291        }
292        self.start()?;
293        let at = self.out.len();
294        let h = head::head(tag, 0, payload.len());
295        self.out.extend_from_slice(&h.to_le_bytes());
296        self.out.extend_from_slice(payload);
297        self.record(at)
298    }
299
300    /// Check that a value may be written here, and that it has a key if it
301    /// needs one.
302    fn start(&mut self) -> Result<()> {
303        match self.open.last() {
304            Some(open) if open.flags & ARRAY == 0 && self.pending.is_none() => Err(Error::new(
305                Code::Invalid,
306                "an object member needs a key before its value",
307            )),
308            Some(_) => Ok(()),
309            None if self.out.is_empty() => Ok(()),
310            None => Err(Error::new(
311                Code::Invalid,
312                "a document holds one value, and it is already written",
313            )),
314        }
315    }
316
317    /// Note the value that was just written at `at` as a member of whatever is
318    /// open around it.
319    fn record(&mut self, at: usize) -> Result<()> {
320        if self.open.is_empty() {
321            return Ok(());
322        }
323        let mut m = self.pending.take().unwrap_or_default();
324        m.head = head::read(&self.out, at).expect("the header was just written");
325        m.at = u32::try_from(at).map_err(|_| too_big())?;
326        m.len = u32::try_from(self.out.len() - at).map_err(|_| too_big())?;
327        m.seq = self.seq;
328        self.seq += 1;
329        self.members.push(m);
330        Ok(())
331    }
332
333    /// Open a container and reserve the four bytes its header will go in.
334    fn begin(&mut self, flags: u32) -> Result<()> {
335        if self.open.len() >= DEPTH_MAX {
336            return Err(Error::fmt(
337                Code::Full,
338                format_args!("a document nests at most {DEPTH_MAX} deep"),
339            ));
340        }
341        self.start()?;
342        let at = self.out.len();
343        self.out.extend_from_slice(&[0; 4]);
344        self.open.push(Open {
345            at,
346            flags,
347            first: self.members.len(),
348            keys_at: self.keys.len(),
349            key: self.pending.take().unwrap_or_default(),
350        });
351        Ok(())
352    }
353
354    /// Close a container: sort its members, then write its header, its entry
355    /// table and its key region in front of the children that are already
356    /// there.
357    ///
358    /// The children move once, through [`Builder::scratch`], because the entry
359    /// table's size is not known until the count is and the count is not known
360    /// until here. Each byte of a document is therefore copied once per level
361    /// it is nested under, which is why [`DEPTH_MAX`] is a number and not a
362    /// suggestion.
363    fn end(&mut self, array: bool) -> Result<()> {
364        let Some(open) = self.open.pop() else {
365            return Err(Error::new(Code::Invalid, "nothing is open"));
366        };
367        if array != (open.flags & ARRAY != 0) {
368            return Err(Error::new(
369                Code::Invalid,
370                "an object is not ended by ending an array, or the other way round",
371            ));
372        }
373        if self.pending.is_some() {
374            return Err(Error::new(Code::Invalid, "a key with no value after it"));
375        }
376        if !array {
377            self.sort_members(&open);
378        }
379        let n = self.members.len() - open.first;
380        if n > COUNT_MAX {
381            return Err(Error::fmt(
382                Code::Full,
383                format_args!("a container holds at most {COUNT_MAX} elements"),
384            ));
385        }
386
387        let sorted = if array { 0 } else { SORTED };
388        let h = head::head(Tag::Container, open.flags | OFFSETS | sorted, n);
389        let entries_end = 4 + layout::keys_area(h, n) + n * 8;
390        let key_bytes: usize = self.members[open.first..]
391            .iter()
392            .map(|m| m.key_len as usize)
393            .sum();
394
395        let children_at = open.at + 4;
396        self.scratch.clear();
397        self.scratch.extend_from_slice(&self.out[children_at..]);
398        self.out.truncate(children_at);
399        self.out[open.at..children_at].copy_from_slice(&h.to_le_bytes());
400
401        if !array {
402            if open.flags & INTERNED != 0 {
403                for i in open.first..self.members.len() {
404                    self.out
405                        .extend_from_slice(&self.members[i].id.to_le_bytes());
406                }
407                // Two byte ids leave the entry table off a four byte stride
408                // half the time, so the area is padded up rather than the
409                // reader being made to cope with both.
410                if n % 2 == 1 {
411                    self.out.extend_from_slice(&[0; 2]);
412                }
413            } else {
414                let mut key_at = entries_end;
415                for i in open.first..self.members.len() {
416                    let off = u32::try_from(key_at).map_err(|_| too_big())?;
417                    self.out.extend_from_slice(&off.to_le_bytes());
418                    key_at += self.members[i].key_len as usize;
419                }
420            }
421        }
422
423        let mut val_at = entries_end + key_bytes;
424        for i in open.first..self.members.len() {
425            let m = self.members[i];
426            self.out.extend_from_slice(&m.head.to_le_bytes());
427            let off = u32::try_from(val_at).map_err(|_| too_big())?;
428            self.out.extend_from_slice(&off.to_le_bytes());
429            val_at += m.len as usize;
430        }
431
432        if !array && open.flags & INTERNED == 0 {
433            for i in open.first..self.members.len() {
434                let m = self.members[i];
435                let at = m.key_at as usize;
436                self.out
437                    .extend_from_slice(&self.keys[at..at + m.key_len as usize]);
438            }
439        }
440
441        // The children come back in entry order, so the value region ends up
442        // sorted the way the entry table is. That is what lets a reader work
443        // out one element's length from the next element's offset, and the
444        // whole container's from its last.
445        for i in open.first..self.members.len() {
446            let m = self.members[i];
447            let from = m.at as usize - children_at;
448            self.out
449                .extend_from_slice(&self.scratch[from..from + m.len as usize]);
450        }
451
452        self.members.truncate(open.first);
453        self.keys.truncate(open.keys_at);
454        if !self.open.is_empty() {
455            self.pending = Some(open.key);
456        }
457        self.record(open.at)
458    }
459
460    /// Put an object's members in key order, and drop all but the last of any
461    /// key written more than once.
462    fn sort_members(&mut self, open: &Open) {
463        let interned = open.flags & INTERNED != 0;
464        let keys = &self.keys;
465        let key_of = |m: &Member| {
466            let at = m.key_at as usize;
467            &keys[at..at + m.key_len as usize]
468        };
469        self.members[open.first..].sort_by(|a, b| {
470            if interned {
471                a.id.cmp(&b.id).then(a.seq.cmp(&b.seq))
472            } else {
473                key_order(key_of(a), key_of(b)).then(a.seq.cmp(&b.seq))
474            }
475        });
476
477        let same = |a: &Member, b: &Member| {
478            if interned {
479                a.id == b.id
480            } else {
481                key_of(a) == key_of(b)
482            }
483        };
484        let mut write = open.first;
485        let mut read = open.first;
486        while read < self.members.len() {
487            let mut run = read + 1;
488            while run < self.members.len() && same(&self.members[read], &self.members[run]) {
489                run += 1;
490            }
491            // Equal keys are adjacent and in insertion order, so the last of a
492            // run is the one that wins. The ones that lose stay in `out` as
493            // bytes nothing points at, which costs space in a document that
494            // repeats a key and nothing at all in one that does not.
495            self.members[write] = self.members[run - 1];
496            write += 1;
497            read = run;
498        }
499        self.members.truncate(write);
500    }
501}
502
503/// The fewest bytes `v` fits in, two's complement.
504fn int_width(v: i64) -> usize {
505    if i64::from(v as i8) == v {
506        1
507    } else if i64::from(v as i16) == v {
508        2
509    } else if i64::from(v as i32) == v {
510        4
511    } else {
512        8
513    }
514}
515
516fn too_big() -> Error {
517    Error::new(Code::Full, "a document is at most four gigabytes")
518}
519
520#[cfg(test)]
521mod tests {
522    use super::*;
523    use crate::head::Kind;
524
525    /// Build a value and check that it is sound in every way the reader can
526    /// check, then hand the bytes back.
527    fn built(f: impl FnOnce(&mut Builder) -> Result<()>) -> Vec<u8> {
528        let mut b = Builder::new();
529        f(&mut b).expect("the builder accepted every call");
530        let bytes = b.finish().expect("the value is finished").to_vec();
531        let v = Value::new(&bytes).expect("the reader accepts it");
532        assert!(v.validate(), "the value is self consistent");
533        assert_eq!(
534            v.encoded_len(),
535            Some(bytes.len()),
536            "the value is exactly as long as the buffer"
537        );
538        bytes
539    }
540
541    #[test]
542    fn every_scalar_comes_back_as_itself() {
543        let cases: Vec<(Vec<u8>, Kind)> = vec![
544            (built(|b| b.null()), Kind::Null),
545            (built(|b| b.bool(true)), Kind::Bool),
546            (built(|b| b.bool(false)), Kind::Bool),
547            (built(|b| b.int(-9)), Kind::Int),
548            (built(|b| b.float(1.5)), Kind::Float),
549            (built(|b| b.text("hello")), Kind::Text),
550        ];
551        for (bytes, kind) in &cases {
552            assert_eq!(Value::new(bytes).expect("readable").kind(), *kind);
553        }
554        assert!(Value::new(&cases[0].0).expect("readable").is_null());
555        assert_eq!(
556            Value::new(&cases[1].0).expect("readable").as_bool(),
557            Some(true)
558        );
559        assert_eq!(
560            Value::new(&cases[2].0).expect("readable").as_bool(),
561            Some(false)
562        );
563        assert_eq!(
564            Value::new(&cases[3].0).expect("readable").as_int(),
565            Some(-9)
566        );
567        assert_eq!(
568            Value::new(&cases[4].0).expect("readable").as_float(),
569            Some(1.5)
570        );
571        assert_eq!(
572            Value::new(&cases[5].0).expect("readable").as_text(),
573            Some("hello")
574        );
575    }
576
577    #[test]
578    fn an_integer_takes_as_few_bytes_as_it_fits_in() {
579        // The width changes where two's complement says it should, and both
580        // sides of every boundary read back as themselves.
581        let cases = [
582            (0i64, 1usize),
583            (127, 1),
584            (-128, 1),
585            (128, 2),
586            (-129, 2),
587            (32_767, 2),
588            (-32_768, 2),
589            (32_768, 4),
590            (2_147_483_647, 4),
591            (-2_147_483_648, 4),
592            (2_147_483_648, 8),
593            (i64::MIN, 8),
594            (i64::MAX, 8),
595        ];
596        for (v, width) in cases {
597            let bytes = built(|b| b.int(v));
598            assert_eq!(bytes.len(), 4 + width, "{v} takes {width} bytes");
599            assert_eq!(Value::new(&bytes).expect("readable").as_int(), Some(v));
600        }
601    }
602
603    #[test]
604    fn an_object_comes_back_in_key_order_whatever_order_it_went_in() {
605        let bytes = built(|b| {
606            b.begin_object()?;
607            for k in ["zebra", "b", "aa", "a", "yak"] {
608                b.key(k.as_bytes())?;
609                b.text(k)?;
610            }
611            b.end_object()
612        });
613        let v = Value::new(&bytes).expect("readable");
614        let keys: Vec<&[u8]> = v.members().map(|(k, _)| k).collect();
615        // Shorter first, then by bytes.
616        assert_eq!(keys, [&b"a"[..], b"b", b"aa", b"yak", b"zebra"]);
617        for k in ["zebra", "b", "aa", "a", "yak"] {
618            assert_eq!(v.get(k.as_bytes()).expect("found").as_text(), Some(k));
619        }
620        assert!(v.get(b"nope").is_none());
621        assert!(v.get(b"").is_none());
622    }
623
624    #[test]
625    fn writing_a_key_twice_keeps_the_last_one_and_leaves_no_dead_bytes() {
626        let bytes = built(|b| {
627            b.begin_object()?;
628            b.key(b"a")?;
629            b.int(1)?;
630            b.key(b"b")?;
631            b.int(2)?;
632            b.key(b"a")?;
633            b.text("the winner")?;
634            b.key(b"a")?;
635            b.int(3)?;
636            b.end_object()
637        });
638        let v = Value::new(&bytes).expect("readable");
639        assert_eq!(v.len(), 2, "two keys, however many times they were written");
640        assert_eq!(v.get(b"a").expect("found").as_int(), Some(3));
641        assert_eq!(v.get(b"b").expect("found").as_int(), Some(2));
642        // `built` already checked that the encoded length is the buffer length,
643        // which is the check that the losing values were not left behind.
644        assert_eq!(bytes.len(), 4 + 2 * 4 + 2 * 8 + 2 + 5 + 5);
645    }
646
647    #[test]
648    fn a_nested_document_reads_at_every_level() {
649        let bytes = built(|b| {
650            b.begin_object()?;
651            b.key(b"id")?;
652            b.int(7)?;
653            b.key(b"lines")?;
654            b.begin_array()?;
655            for i in 0..3i64 {
656                b.begin_object()?;
657                b.key(b"sku")?;
658                b.int(i)?;
659                b.key(b"note")?;
660                b.text("a line of some length so the offsets move")?;
661                b.end_object()?;
662            }
663            b.end_array()?;
664            b.key(b"open")?;
665            b.bool(true)?;
666            b.end_object()
667        });
668        let v = Value::new(&bytes).expect("readable");
669        assert_eq!(v.get(b"id").expect("found").as_int(), Some(7));
670        assert_eq!(v.get(b"open").expect("found").as_bool(), Some(true));
671        let lines = v.get(b"lines").expect("found");
672        assert_eq!(lines.kind(), Kind::Array);
673        assert_eq!(lines.len(), 3);
674        for i in 0..3i64 {
675            let line = lines.at(i as usize).expect("an element");
676            assert_eq!(line.get(b"sku").expect("found").as_int(), Some(i));
677            assert!(line.get(b"note").expect("found").as_text().is_some());
678            // A child is a whole value on its own, which is what makes a copy
679            // out of a document a memcpy and not a re-encode.
680            let alone = line.as_bytes().expect("a length");
681            let again = Value::new(alone).expect("readable on its own");
682            assert!(again.validate());
683            assert_eq!(again.get(b"sku").expect("found").as_int(), Some(i));
684        }
685    }
686
687    #[test]
688    fn an_empty_container_is_four_bytes() {
689        let obj = built(|b| {
690            b.begin_object()?;
691            b.end_object()
692        });
693        assert_eq!(obj.len(), 4);
694        let v = Value::new(&obj).expect("readable");
695        assert_eq!(v.kind(), Kind::Object);
696        assert!(v.is_empty());
697        assert!(v.get(b"a").is_none());
698
699        let arr = built(|b| {
700            b.begin_array()?;
701            b.end_array()
702        });
703        assert_eq!(arr.len(), 4);
704        let v = Value::new(&arr).expect("readable");
705        assert_eq!(v.kind(), Kind::Array);
706        assert!(v.is_empty());
707        assert!(v.at(0).is_none());
708    }
709
710    #[test]
711    fn an_interned_object_looks_up_by_id() {
712        // Odd and even counts both, since an odd number of two byte ids leaves
713        // the entry table off a four byte stride without the padding.
714        for n in [1u16, 2, 3, 8, 9] {
715            let bytes = built(|b| {
716                b.begin_object_interned()?;
717                for id in (0..n).rev() {
718                    b.key_id(id * 3)?;
719                    b.int(i64::from(id))?;
720                }
721                b.end_object()
722            });
723            let v = Value::new(&bytes).expect("readable");
724            assert!(v.is_interned());
725            assert_eq!(v.len(), usize::from(n));
726            for id in 0..n {
727                assert_eq!(
728                    v.get_id(id * 3).expect("found").as_int(),
729                    Some(i64::from(id))
730                );
731            }
732            assert!(v.get_id(1).is_none(), "1 is not a multiple of 3");
733            assert!(v.key_at(0).is_none(), "the names are not in the document");
734            assert_eq!(v.key_id_at(0), Some(0));
735        }
736    }
737
738    #[test]
739    fn a_thousand_keys_are_all_findable() {
740        // Fewer names under Miri. What is being checked is that a lookup finds
741        // every one of them, which is the binary search over the entry table,
742        // and that search is the same search at a hundred and fifty keys as at
743        // a thousand. Both counts below come from the list itself.
744        let count = if cfg!(miri) { 150 } else { 1_000 };
745        let names: Vec<String> = (0..count).map(|i| format!("field{i}")).collect();
746        let bytes = built(|b| {
747            b.begin_object()?;
748            for (i, name) in names.iter().enumerate() {
749                b.key(name.as_bytes())?;
750                b.int(i as i64)?;
751            }
752            b.end_object()
753        });
754        let v = Value::new(&bytes).expect("readable");
755        assert_eq!(v.len(), names.len());
756        for (i, name) in names.iter().enumerate() {
757            assert_eq!(
758                v.get(name.as_bytes()).expect("found").as_int(),
759                Some(i as i64)
760            );
761        }
762        assert!(v.get(format!("field{count}").as_bytes()).is_none());
763    }
764
765    #[test]
766    fn a_value_that_is_already_encoded_can_be_copied_in() {
767        let inner = built(|b| {
768            b.begin_object()?;
769            b.key(b"x")?;
770            b.int(3)?;
771            b.end_object()
772        });
773        let bytes = built(|b| {
774            b.begin_array()?;
775            b.int(1)?;
776            b.embed(&Value::new(&inner).expect("readable"))?;
777            b.int(2)?;
778            b.end_array()
779        });
780        let v = Value::new(&bytes).expect("readable");
781        assert_eq!(v.len(), 3);
782        assert_eq!(
783            v.at(1)
784                .expect("an element")
785                .get(b"x")
786                .expect("found")
787                .as_int(),
788            Some(3)
789        );
790    }
791
792    #[test]
793    fn a_builder_can_be_used_again() {
794        let mut b = Builder::new();
795        b.int(1).expect("a value");
796        assert_eq!(b.finish().expect("finished").len(), 5);
797        b.clear();
798        b.text("hello").expect("a value");
799        let bytes = b.finish().expect("finished");
800        assert_eq!(
801            Value::new(bytes).expect("readable").as_text(),
802            Some("hello")
803        );
804    }
805
806    #[test]
807    fn the_builder_says_no_to_every_way_of_getting_it_wrong() {
808        let bad = |f: fn(&mut Builder) -> Result<()>| {
809            let mut b = Builder::new();
810            f(&mut b).unwrap_err()
811        };
812
813        // A key with nothing after it.
814        assert!(
815            bad(|b| {
816                b.begin_object()?;
817                b.key(b"a")?;
818                b.end_object()
819            })
820            .message()
821            .contains("no value")
822        );
823        // Two keys in a row.
824        assert!(
825            bad(|b| {
826                b.begin_object()?;
827                b.key(b"a")?;
828                b.key(b"b")
829            })
830            .message()
831            .contains("two keys")
832        );
833        // A value in an object with no key.
834        assert!(
835            bad(|b| {
836                b.begin_object()?;
837                b.int(1)
838            })
839            .message()
840            .contains("needs a key")
841        );
842        // A key in an array.
843        assert!(
844            bad(|b| {
845                b.begin_array()?;
846                b.key(b"a")
847            })
848            .message()
849            .contains("no key")
850        );
851        // A key with nothing open.
852        assert!(bad(|b| b.key(b"a")).message().contains("no object open"));
853        // Ending the wrong thing.
854        assert!(
855            bad(|b| {
856                b.begin_object()?;
857                b.end_array()
858            })
859            .message()
860            .contains("not ended by")
861        );
862        // Ending nothing.
863        assert!(
864            bad(|b| b.end_object())
865                .message()
866                .contains("nothing is open")
867        );
868        // Two values at the top level.
869        assert!(
870            bad(|b| {
871                b.int(1)?;
872                b.int(2)
873            })
874            .message()
875            .contains("already written")
876        );
877        // Key bytes into an interned object and the other way round.
878        assert!(
879            bad(|b| {
880                b.begin_object_interned()?;
881                b.key(b"a")
882            })
883            .message()
884            .contains("key ids")
885        );
886        assert!(
887            bad(|b| {
888                b.begin_object()?;
889                b.key_id(1)
890            })
891            .message()
892            .contains("key bytes")
893        );
894    }
895
896    #[test]
897    fn finishing_early_is_an_error_and_not_a_short_document() {
898        let mut b = Builder::new();
899        assert!(b.finish().unwrap_err().message().contains("no value"));
900        b.begin_array().expect("open");
901        assert!(b.finish().unwrap_err().message().contains("unclosed array"));
902        b.end_array().expect("close");
903        b.finish().expect("finished now");
904
905        let mut b = Builder::new();
906        b.begin_object().expect("open");
907        assert!(
908            b.finish()
909                .unwrap_err()
910                .message()
911                .contains("unclosed object")
912        );
913    }
914
915    /// Not shrunk. The depth is the claim on both sides: that the builder takes
916    /// [`DEPTH_MAX`] levels and refuses the one after it, and that the reader
917    /// then walks all of them. A shallower version says nothing about where the
918    /// limit is, and the limit is a compile time constant so there is no knob
919    /// to move it.
920    #[test]
921    #[cfg_attr(miri, ignore = "the depth limit is the claim and it is 128 levels")]
922    fn a_document_nests_as_deep_as_the_reader_will_walk_and_no_deeper() {
923        let mut b = Builder::new();
924        for _ in 0..DEPTH_MAX {
925            b.begin_array().expect("within the limit");
926        }
927        assert!(
928            b.begin_array()
929                .unwrap_err()
930                .message()
931                .contains("nests at most"),
932            "one past the limit is refused"
933        );
934        for _ in 0..DEPTH_MAX {
935            b.end_array().expect("close");
936        }
937        let bytes = b.finish().expect("finished").to_vec();
938        let v = Value::new(&bytes).expect("readable");
939        assert!(v.validate(), "the reader walks all of it");
940        assert_eq!(v.encoded_len(), Some(bytes.len()));
941    }
942}