yo_doc/layout.rs
1//! Where the pieces of a container sit, worked out in one place so that the
2//! builder and the reader cannot drift apart.
3//!
4//! ```text
5//! +--------+--------------+---------------+------------+--------------+
6//! | header | key entries | value entries | key region | value region |
7//! | 4 | objects only | 8 per element | | |
8//! +--------+--------------+---------------+------------+--------------+
9//! ```
10//!
11//! A key entry is four bytes, an offset into the container, and a key's length
12//! is the difference between its offset and the next one. An interned object's
13//! key entries are two byte ids instead, padded up so that the value entries
14//! stay on a four byte stride.
15//!
16//! A value entry is eight bytes: a copy of the element's own header, so that a
17//! scan over the entries never touches the value region, and the offset the
18//! element starts at. Offsets are relative to the container's header, so a
19//! container can be copied anywhere without rewriting it.
20//!
21//! Values are stored in entry order and tile the value region, which is what
22//! makes the last entry enough to work out the whole container's length.
23
24use crate::head::{ARRAY, INTERNED};
25
26/// How many bytes an object's key entries take, padding included.
27pub(crate) fn keys_area(head: u32, count: usize) -> usize {
28 if head & ARRAY != 0 {
29 return 0;
30 }
31 if head & INTERNED != 0 {
32 (count * 2).next_multiple_of(4)
33 } else {
34 count * 4
35 }
36}