A PATH body is packed segment records (L2/L3 codec)¶
An address on the wire is a PATH (0x06) whose body is opt.PL = 0 and holds a
self-delimiting run of segment records — each [u8 len][len bytes of UTF-8], in order
(RFC-0018,
CONTEXT.md §Segment / view). No per-segment type byte, no per-segment
option byte, hence exactly one spelling per address — which is what lets the vertex map be
keyed on the body bytes directly rather than on a materialized string.
Register a vertex shows the other end of this: path_t parses its string
once into exactly these bytes. Here they are built by hand and compared.
What to notice¶
The body is the key.
wire::path_keyon the decodedPATHandpath_t("/sensor/temp").key()produce byte-identical output. One is a peer’s frame, the other a local literal; the dispatcher cannot tell them apart, which is the point.A
PATHhas zero children. That is RFC-0018 in one assertion. The pre-RFC spelling used aNAMETLV per component, and its option byte admitted several legal spellings of one address — so a byte key was a hope rather than a guarantee.NAME(0x02) itself is not retired; it survives for SETTINGS keys,:schemalabels and:children[]members.The walk is one byte load and one add.
p += 1 + body[p], with the bounds compare the load already needed.packed_path_valid_keyis exactly that walk, asking whether the body tiles cleanly into literal records.emit_path_segmentrefuses what it cannot spell. An empty segment would collide with the escape record, and anything past 255 bytes will not fit the length field; both append nothing and return false rather than emitting a half-record.The key bytes belong to the
path_t.key()hands out a span into the path object, so the object has to outlive it — the example names it rather than callingkey()on a temporary.Nothing here is conditional — the target builds and runs under every CI leg.
Source¶
1/*
2 * SPDX-License-Identifier: Apache-2.0
3 * SPDX-FileCopyrightText: Copyright 2026 avatarsd LLC
4 */
5
6/**
7 * @file
8 * @brief ONE CONCEPT — a `PATH` body is packed segment records, and IS the vertex-map key.
9 *
10 * Since RFC-0018 a `PATH` (`0x06`) body is `opt.PL = 0` and holds a self-delimiting run of
11 * **segment records**, each `[u8 len][len bytes of UTF-8]` — no per-segment type byte, no
12 * per-segment option byte, hence exactly ONE spelling per address. That is what lets the
13 * vertex map be keyed on the body bytes directly: this example builds `/sensor/temp`'s body
14 * by hand and checks it is byte-identical to what `tr::graph::path_t` parsed from the
15 * string (`docs/reference/03-addressing.md`, `CONTEXT.md` §Segment / view).
16 *
17 * The decoded `PATH` has ZERO children, which is the RFC-0018 change in one assertion.
18 *
19 * Runs under ctest as `example_wire_packed_path`; returns non-zero on any failed check.
20 */
21
22#include <algorithm>
23#include <cstddef>
24#include <cstdio>
25#include <vector>
26
27#include "libtracer/packed_path.hpp"
28#include "libtracer/tlv_emit.hpp"
29#include "libtracer/tracer.hpp"
30
31namespace {
32
33using tr::wire::opt_t;
34using tr::wire::type_t;
35
36/** @brief Report expectation @p what and record a failure on @p ok. */
37void check(bool& ok, bool cond, const char* what) {
38 std::printf(" [%s] %s\n", cond ? "ok" : "FAIL", what);
39 ok = ok && cond;
40}
41
42} // namespace
43
44int main() {
45 bool ok = true;
46
47 // Two segment records, appended in order: 06 "sensor", 04 "temp" — 12 bytes.
48 std::vector<std::byte> body;
49 check(ok, tr::wire::emit_path_segment(body, "sensor"), "the first segment record appends");
50 check(ok, tr::wire::emit_path_segment(body, "temp"), "the second appends after it");
51 std::printf("/sensor/temp packs into %zu body bytes\n", body.size());
52 check(ok, body.size() == (1 + 6) + (1 + 4), "each record costs one length byte plus its text");
53 check(ok, tr::wire::packed_path_valid_key(body), "the body tiles exactly into literal records");
54
55 std::vector<std::byte> frame;
56 tr::wire::emit_tlv(frame, type_t::PATH, opt_t{}, body);
57 const auto decoded = tr::wire::decode(frame);
58 check(ok, decoded.has_value(), "the PATH TLV decodes");
59 check(ok, decoded && decoded->children.empty(),
60 "a PATH has no children — the records are the body (RFC-0018)");
61
62 // The key the graph would look this up by, from both directions.
63 const auto key = decoded ? tr::wire::path_key(*decoded) : std::nullopt;
64 // The path OBJECT owns the key bytes, so it has to outlive the span it hands out.
65 const tr::graph::path_t path("/sensor/temp");
66 const std::span<const std::byte> parsed = path.key();
67 check(ok, key.has_value(), "path_key answers for a well-framed literal body");
68 check(ok, key && std::equal(key->begin(), key->end(), parsed.begin(), parsed.end()),
69 "and the bytes match what path_t parsed from the string");
70 return ok ? 0 : 1;
71}
See also: path module · frame codec · addressing reference.