pub struct CliEmitter<W: Write> { /* private fields */ }Expand description
Where a CliEmitter sends its events, selected by --output-to.
The stream an event lands on follows the program’s consumption mode, not the event’s shape (see the spec’s CLI Event Framing):
OutputTo::Split(the default) is finite one-shot mode:resultgoes tostdout, whileerror/progress/loggo tostderr.stdouttherefore carries only successful payloads, so a shell capture or pipe never mistakes a failure for data.OutputTo::Stdout/OutputTo::Stderrare event-stream mode: every event, includingerror, is collapsed onto that one stream so a consumer reading it in order (kind-branching) sees preserved ordering.
A command is an event stream when it produces more than one caller-needed
output over time — a chunked payload, or an address the caller must act on
before the command can report its outcome. Such a command defaults to
OutputTo::Stdout and rejects an explicit split, because splitting it
would strand the caller’s data on the diagnostic stream. If a
kind:"progress" event carries a payload the caller must read, the command
is an event stream that has not declared itself.
Stateful emitter for structured CLI executions.
The output format, redaction policy, and stream routing are fixed when the emitter is created. Emitting after a terminal event, emitting a repeated terminal event, and writer failures all return explicit errors.
Routing follows the consumption mode (OutputTo):
CliEmitter::finite/CliEmitter::finite_with— finite one-shot:result→ the primary writer (stdout),error/progress/log→ the diagnostic writer (stderr). This is the recommended default for a one-shot CLI, so shell capture and pipelines never treat a failure as data.CliEmitter::stream— event stream: every event, includingerror, goes to the single writer, preserving interleaved ordering.CliEmitter::from_output_tobuilds either shape from a parsedOutputToselector.
Implementations§
Source§impl<W: Write> CliEmitter<W>
impl<W: Write> CliEmitter<W>
Sourcepub fn new(writer: W, format: OutputFormat) -> Self
pub fn new(writer: W, format: OutputFormat) -> Self
Create an event-stream emitter: every event goes to writer.
Alias for CliEmitter::stream. Use CliEmitter::finite for a
one-shot command that should split result/error across stdout/stderr.
Sourcepub fn with_options(
writer: W,
format: OutputFormat,
output_options: OutputOptions,
) -> Self
pub fn with_options( writer: W, format: OutputFormat, output_options: OutputOptions, ) -> Self
Create an event-stream emitter with custom output options.
Sourcepub fn stream(writer: W, format: OutputFormat) -> Self
pub fn stream(writer: W, format: OutputFormat) -> Self
Create an event-stream emitter: every event, including error, goes to
the single writer, preserving interleaved ordering. Pick this when the
consumer reads one ordered stream and branches on kind.
Sourcepub fn finite_with(
result_writer: W,
diagnostic: impl Write + 'static,
format: OutputFormat,
) -> Self
pub fn finite_with( result_writer: W, diagnostic: impl Write + 'static, format: OutputFormat, ) -> Self
Create a finite one-shot emitter with explicit sinks: result goes to
result_writer, while error/progress/log go to diagnostic.
Sourcepub fn finite_with_options(
result_writer: W,
diagnostic: impl Write + 'static,
format: OutputFormat,
output_options: OutputOptions,
) -> Self
pub fn finite_with_options( result_writer: W, diagnostic: impl Write + 'static, format: OutputFormat, output_options: OutputOptions, ) -> Self
Create a finite one-shot emitter with explicit sinks and output options.
Sourcepub fn with_strict_protocol(self) -> Self
pub fn with_strict_protocol(self) -> Self
Require the AFDATA recommended strict profile for every emitted event.
Sourcepub fn emit(&mut self, event: Event) -> Result<(), CliEmitterError>
pub fn emit(&mut self, event: Event) -> Result<(), CliEmitterError>
Emit a typed Event (unified entry for all event kinds).
Accepts only SDK-constructed Event; for dynamic JSON, use emit_validated_value.
Sourcepub fn emit_validated_value(
&mut self,
value: Value,
) -> Result<(), CliEmitterError>
pub fn emit_validated_value( &mut self, value: Value, ) -> Result<(), CliEmitterError>
Emit and validate dynamic JSON, then apply redaction/formatting/write.
Runs strict validation first, ensuring the dynamic JSON is safe.
Sourcepub fn emit_result(&mut self, payload: Value) -> Result<(), CliEmitterError>
pub fn emit_result(&mut self, payload: Value) -> Result<(), CliEmitterError>
Convenience: build and emit a result event.
Sourcepub fn emit_error(
&mut self,
code: &str,
message: &str,
) -> Result<(), CliEmitterError>
pub fn emit_error( &mut self, code: &str, message: &str, ) -> Result<(), CliEmitterError>
Convenience: build and emit an error event.
Sourcepub fn emit_progress(&mut self, message: &str) -> Result<(), CliEmitterError>
pub fn emit_progress(&mut self, message: &str) -> Result<(), CliEmitterError>
Convenience: build and emit a progress event.
Sourcepub fn emit_log(
&mut self,
level: LogLevel,
message: &str,
) -> Result<(), CliEmitterError>
pub fn emit_log( &mut self, level: LogLevel, message: &str, ) -> Result<(), CliEmitterError>
Convenience: build and emit a log event.
Sourcepub fn finish(&mut self, event: Event, success_code: u8) -> u8
pub fn finish(&mut self, event: Event, success_code: u8) -> u8
Emit event as the terminal event and resolve the outcome to a process
exit code, so a one-shot CLI need not hand-roll the emit-then-exit dance.
A successful write returns success_code; a broken pipe (the reader hung
up) returns 0; any other write or validation failure returns 4. A
library never calls process::exit itself — return this code from main
(std::process::ExitCode::from(code)).
Sourcepub fn finish_result(&mut self, payload: Value) -> u8
pub fn finish_result(&mut self, payload: Value) -> u8
Convenience over CliEmitter::finish: emit a result payload and
return 0 on success.
For an error, build it with json_error (.hint(…), .retryable(…),
.field(…) as needed) and pass the event to CliEmitter::finish with
the desired exit code — the builder is the error type, so no separate
error-emitting convenience is needed.
Sourcepub fn into_inner(self) -> W
pub fn into_inner(self) -> W
Access the underlying writer.
Source§impl CliEmitter<Stdout>
impl CliEmitter<Stdout>
Sourcepub fn finite(format: OutputFormat) -> Self
pub fn finite(format: OutputFormat) -> Self
Create a finite one-shot emitter wired to the process streams: result
→ stdout, error/progress/log → stderr. The recommended default
for a one-shot CLI.
Sourcepub fn finite_options(
format: OutputFormat,
output_options: OutputOptions,
) -> Self
pub fn finite_options( format: OutputFormat, output_options: OutputOptions, ) -> Self
Create a finite one-shot emitter wired to the process streams, with custom output options.
Source§impl CliEmitter<Box<dyn Write>>
impl CliEmitter<Box<dyn Write>>
Sourcepub fn from_output_to(selector: OutputTo, format: OutputFormat) -> Self
pub fn from_output_to(selector: OutputTo, format: OutputFormat) -> Self
Build an emitter from a parsed OutputTo selector, wired to the
process streams: Split is finite mode (result → stdout, everything
else → stderr); Stdout/Stderr are event-stream mode onto that stream.
Sourcepub fn from_output_to_with(
selector: OutputTo,
format: OutputFormat,
output_options: OutputOptions,
) -> Self
pub fn from_output_to_with( selector: OutputTo, format: OutputFormat, output_options: OutputOptions, ) -> Self
As CliEmitter::from_output_to, with custom output options.