Skip to main content

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}