Skip to main content

wire/answer/
prefix.rs

1// This Source Code Form is subject to the terms of the Mozilla Public
2// License, v. 2.0. If a copy of the MPL was not distributed with this
3// file, You can obtain one at https://mozilla.org/MPL/2.0/.
4// Copyright (c) 2026 2youg1 and the sprawling contributors
5
6//! The system prompt one run was frozen with, and the general read of
7//! the content store it is recovered through.
8//!
9//! Both shapes live here because they are one question asked at two
10//! grains: a prefix answer is four store objects named by the record
11//! that froze them, and a content answer is one store object named by
12//! whoever holds its locator. A page that can draw the first can draw
13//! the second with no second vocabulary for "bytes this city kept".
14
15use kernel::{Address, B3Hash, Locator, RunId};
16use serde::{Deserialize, Serialize};
17
18/// The four slots of a frozen prefix, in the order they are sent.
19///
20/// Exhaustive and closed: the order is the cache economics, and a
21/// spelling a page had to match against a free string would let a
22/// segment arrive under a name nothing draws.
23#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
24#[serde(rename_all = "snake_case")]
25#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
26pub enum PrefixSlot {
27    City,
28    Building,
29    Resident,
30    Run,
31}
32
33/// One document a segment was assembled from, as the assembler saw it.
34///
35/// `dropped` is what the per-slot budget cut off the end of that
36/// document, so a reader can tell a segment that carries a whole file
37/// from one that carries the first half of it. Zero is the ordinary
38/// case and is still reported, because "nothing was cut" is a fact and
39/// an absent field is not.
40#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
41#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
42pub struct PrefixSource {
43    pub addr: Address,
44    pub kept: u64,
45    pub dropped: u64,
46}
47
48/// One frozen segment, as a reader needs it.
49///
50/// `bytes` is what the record says the segment measured and `text` is
51/// what the store still holds, so the two disagreeing is itself the
52/// finding: `stored` false means the object is gone and the text is
53/// empty because nothing could be read, not because the segment was.
54#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
55#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
56pub struct PrefixSegment {
57    pub slot: PrefixSlot,
58    pub hash: B3Hash,
59    pub bytes: u64,
60    pub text: String,
61    pub stored: bool,
62    pub sources: Vec<PrefixSource>,
63}
64
65/// What one run was told before it said anything.
66#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
67#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
68pub struct PrefixAnswer {
69    pub run: RunId,
70    /// City, building, resident, run - always four, in that order.
71    pub segments: Vec<PrefixSegment>,
72}
73
74/// One object of the content store, cut to what travels.
75///
76/// The same bound and the same text judgement `Document` puts on a file
77/// in the tree, for the same reasons: bytes with a NUL in the head are
78/// not text, and showing them as text would show a reader something the
79/// object does not say.
80#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
81#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
82pub struct ContentAnswer {
83    /// The locator asked for, handed back: the wire carries no request
84    /// id, so a page matches an answer to its question by content.
85    pub locator: Locator,
86    pub text: String,
87    pub bytes: u64,
88    pub truncated: bool,
89    pub binary: bool,
90}