char_sink.hpp¶
ProsCharSink — ICharSink over the V5's USB serial (chunk R1a): where TermSink's diagnostic bytes physically go on the robot (pros terminal displays them).
This header declares 1 type (2 members).
Extracted from include/shulib/hal/pros/char_sink.hpp — this page is that header's documentation, reformatted, so it cannot disagree with the code. Prose about how to think about the API lives in the user guide; worked recipes live in the cookbook; this page is the complete, mechanical list of what exists.
Contents¶
class ProsCharSink¶
The on-robot ICharSink: TermSink's diagnostic bytes onto the V5's USB serial, where pros terminal displays them. Writes through newlib stdout with fwrite, so it pulls in
class, declared at include/shulib/hal/pros/char_sink.hpp:43.
ProsCharSink::ProsCharSink¶
out must be NON-NULL and must outlive the sink; defaults to the V5 USB serial (stdout). The null check is not decoration: the banner advertises the FILE* as injectable precisely so a host test can hand it a tmpfile(), and that is the one call site most likely to hand over a null on failure — after which write()'s std::fwrite is undefined behaviour rather than a loud contract breach. Every other pointer-taking constructor in the tree already checks (MotorMechanism, PneumaticMechanism, MechanismDeps, RunGuardConfig); this one did not.
function, declared at include/shulib/hal/pros/char_sink.hpp:52.
ProsCharSink::write¶
Verbatim bytes + flush. MUST NOT throw (contract) — and cannot.
function, declared at include/shulib/hal/pros/char_sink.hpp:57.
Design commentary, from the header¶
The header opens with the reasoning behind these shapes. It is reproduced here in full because a reference that only lists signatures teaches nobody why.
The header’s own reasoning — 26 lines
ProsCharSink — ICharSink over the V5's USB serial (chunk R1a): where
TermSink's diagnostic bytes physically go on the robot (`pros terminal`
displays them).
BINDS: newlib stdout via std::fwrite + std::fflush. The PROS kernel wires
stdout to the USB serial, so this adapter deliberately includes NO <pros/*>
header at all — it lives under hal/pros/ because it is the ON-ROBOT sink
(and so the PROS-free guard's one exemption covers it if it ever needs the
direct serial API), but its only dependency is <cstdio>. This is the same
sink main.cpp carried privately as StdoutCharSink since C7, promoted to the
adapter tree so tests and future consumers share one implementation.
CONTRACT (char_sink.hpp:31-32): bytes verbatim, synchronous on the caller's
task, MUST NOT throw — fwrite/fflush cannot throw. One write() call carries
one complete line (the FORMATTER's framing), and fwrite is atomic per call
at this layer, so lines never interleave.
FLUSH PER WRITE, deliberately: boot-banner visibility is worth more than
buffered throughput here, and the diagnostics layer already rate-limits
(the C7 ruling, carried forward unchanged).
The FILE* is injectable (default stdout) so a host test can hand it a
tmpfile() and assert exact bytes — the same injected-device pattern that
made TermSink's output a testable claim in the first place (char_sink.hpp
header).
Last updated 2026-08-15 — published from the main release branch, commit fa545ff. This site tracks releases, so between them it can lag the repository — that lag is deliberate, and it is what keeps the development log off the public site. For the current state of the code, see the repository.