subview: narrowing a window costs arithmetic (L1 views)¶
A view is {owner, offset, length}, so narrowing one is arithmetic on the offset and the
length plus a refcount bump (reference 08). This is
the primitive every zero-copy slice in the library reduces to: a child TLV’s payload, a routed
path suffix, a value handed to a subscriber. The pointers are the proof — a sub-window’s
bytes().data() is the parent’s plus the offset, in the same segment.
What to notice¶
Nesting composes against the segment, not the window.
whole.subview(4, 8).subview(2, 4)hasoffset == 6— offsets accumulate, and the second call’s2is relative to the first window. Reading byte 0 of the inner view yields byte 6 of the segment.Narrowing extends lifetime. The sub-window holds its own reference, so it may outlive the wide view it came from. That is what lets a decoder hand a caller a payload and forget the frame.
The window invariant is debug-asserted.
bytes()assertsoffset + length <= owner->bytes.size()— zero cost in a release build, and the reason an out-of-bounds window is caught at its source on the sanitizer CI leg rather than as a mysterious read somewhere downstream.A view is one contiguous window over one segment. Spanning several segments is the rope’s job, and taking a sub-range of one is
subrope— the same idea one level up.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 — `subview`: a narrower window over the SAME segment, no copy.
9 *
10 * A view is `{owner, offset, length}`, so narrowing it is arithmetic on the offset and the
11 * length plus a refcount bump — never a memcpy (`docs/reference/08-views-and-ownership.md`).
12 * This is the primitive every zero-copy slice in the library is built from: a child TLV's
13 * payload, a routed path suffix, a value handed to a subscriber. The pointers prove it —
14 * a sub-window's `bytes().data()` is the parent's plus the offset, in the same segment.
15 *
16 * Narrowing also EXTENDS lifetime: the sub-window holds its own reference, so the segment
17 * outlives the wide view it came from. `view_t::bytes()` debug-asserts the window invariant
18 * (`offset + length <= owner->bytes.size()`), which is why the sanitizer CI leg is where an
19 * out-of-bounds window is caught at its source.
20 *
21 * Runs under ctest as `example_view_subview`; returns non-zero on any failed check.
22 */
23
24#include <cstddef>
25#include <cstdio>
26#include <optional>
27
28#include "libtracer/tracer.hpp"
29
30namespace {
31
32/** @brief Report expectation @p what and record a failure on @p ok. */
33void check(bool& ok, bool cond, const char* what) {
34 std::printf(" [%s] %s\n", cond ? "ok" : "FAIL", what);
35 ok = ok && cond;
36}
37
38} // namespace
39
40int main() {
41 bool ok = true;
42 tr::view::segment_ptr_t seg = tr::view::heap_alloc(16);
43 check(ok, static_cast<bool>(seg), "a 16-byte heap segment");
44 if (!seg) return 1;
45 for (std::size_t i = 0; i < seg->bytes.size(); ++i) seg->bytes[i] = static_cast<std::byte>(i);
46
47 const tr::view::view_t whole = tr::view::view_t::over(seg);
48 check(ok, whole.length == 16, "over() covers the whole segment");
49
50 const tr::view::view_t mid = whole.subview(4, 8); // bytes 4..11
51 std::printf("whole=[0,16) sub=[%zu,%zu) use_count=%u\n", mid.offset, mid.offset + mid.length,
52 seg.use_count());
53 check(ok, mid.length == 8 && mid.offset == 4, "the sub-window is {offset, length} arithmetic");
54 check(ok, mid.bytes().data() == whole.bytes().data() + 4,
55 "and addresses the parent's bytes directly — zero copies");
56
57 const tr::view::view_t inner = mid.subview(2, 4); // bytes 6..9, relative to `mid`
58 check(ok, inner.offset == 6, "nesting composes offsets against the SEGMENT, not the window");
59 check(ok, inner.bytes()[0] == std::byte{6}, "so the first byte read back is byte 6");
60
61 const std::uint_least32_t held = seg.use_count();
62 check(ok, held == 4, "segment + three windows, each holding its own reference");
63 check(ok, !whole.empty() && !inner.empty(), "a narrowed window is still a view over bytes");
64 return ok ? 0 : 1;
65}
See also: views module · segment module · views & ownership reference.