pub struct Writer<'a, O: Options = Standard> { /* private fields */ }Expand description
Accumulates JSON output.
The lifetime is the borrow of an io::Write sink, and is 'static for
the ordinary in-memory writers built by Writer::new and friends.
O is the write policy, which decides at compile time
whether the output is indented and whether null members are left out. It
defaults to Standard, though a constructor cannot infer from that, so
build one as Writer::<Standard>::new(). Trait implementations take
&mut Writer<'_, O> and stay generic over it.
Implementations§
Source§impl<'a, O: Options> Writer<'a, O>
impl<'a, O: Options> Writer<'a, O>
Sourcepub fn to_sink(out: &'a mut dyn Write) -> Self
pub fn to_sink(out: &'a mut dyn Write) -> Self
Write through to out, buffering DEFAULT_SINK_BUFFER bytes at a
time.
The document is drained as it is produced, so peak memory is the buffer
plus the largest single scalar written, not the size of the output.
Writer::finish must be called to flush the tail and report any I/O
error; crate::to_writer does both.
Sourcepub fn to_sink_with_capacity(out: &'a mut dyn Write, capacity: usize) -> Self
pub fn to_sink_with_capacity(out: &'a mut dyn Write, capacity: usize) -> Self
Writer::to_sink with an explicit buffer size.
capacity is clamped up to one byte: draining always retains the last
byte written, because it may still be a trailing comma awaiting
overwrite by a closing brace.
Sourcepub fn as_bytes(&self) -> &[u8] ⓘ
pub fn as_bytes(&self) -> &[u8] ⓘ
The bytes written so far, or with a sink, the bytes not yet drained.
Sourcepub fn into_string(self) -> String
pub fn into_string(self) -> String
Take the output.
Everything written is valid UTF-8 by construction: string contents come
from &str, numbers and escapes are ASCII, and Writer::push rejects
non-ASCII bytes.
With a sink this returns only the undrained tail. Use
Writer::finish instead.
pub fn into_vec(self) -> Vec<u8> ⓘ
Sourcepub fn len(&self) -> usize
pub fn len(&self) -> usize
Bytes currently buffered.
With a sink this counts only what has not been drained, matching
Writer::as_bytes. A running total of the whole document is not
offered because a failed drain would make it a lie.
pub fn is_empty(&self) -> bool
Sourcepub fn finish(self) -> Result<()>
pub fn finish(self) -> Result<()>
Drain the remaining bytes to the sink and report the first I/O error.
Without a sink this is Ok(()) and does nothing.
By value on purpose. A sink writer that keeps going after its tail has been flushed would emit a second document’s worth of bytes into the middle of the first, and asking twice whether the write succeeded has no second answer worth giving.
Sourcepub fn push(&mut self, b: u8)
pub fn push(&mut self, b: u8)
Append one ASCII byte.
§Panics
If b is not ASCII. Writer::into_string converts without
re-validating, so the buffer has to stay valid UTF-8, and this is the
only way safe code could break that. At every internal call site b is
a literal, so the check folds away.
Sourcepub fn raw(&mut self, s: &str)
pub fn raw(&mut self, s: &str)
Append a string verbatim, without quoting or escaping it.
Whatever s holds becomes part of the document as written, so keeping
the result valid JSON is the caller’s job. Emitting a number literal is
a supported use of this, and
write_number_str is that use with the
literal checked.
Sourcepub fn write_object<T: WriteObject>(&mut self, value: &T)
pub fn write_object<T: WriteObject>(&mut self, value: &T)
Write a struct as a JSON object.
Members are written with an unconditional trailing comma, and the last
one is overwritten with }. That removes the per-field “am I first”
branch from the inner loop entirely.
The overwrite checks for that comma rather than assuming it.
WriteObject is a safe trait that anyone may implement, so nothing
guarantees write_fields wrote what it was asked to, and the buffer is
handed out by Writer::into_string without revalidation.
Sourcepub fn member<T: Write + ?Sized>(&mut self, prefix: &str, value: &T)
pub fn member<T: Write + ?Sized>(&mut self, prefix: &str, value: &T)
Write one "key":value, member. prefix is the pre-quoted key with its
colon, built at compile time by the macro.
Under Options::SKIP_NULL a member holding nothing is not written at
all, key included. The test is a constant plus a call that is false
for all but a handful of types, so a policy that does not ask for it
pays nothing and one that does pays a predictable branch on a value
already in hand.
Sourcepub fn member_with<A: WriteAs<T>, T: ?Sized>(&mut self, prefix: &str, value: &T)
pub fn member_with<A: WriteAs<T>, T: ?Sized>(&mut self, prefix: &str, value: &T)
Write one "key":value, member, the value through an adapter.
Self::member for a field whose declaration named an adapter, down to
the trailing comma and to Options::SKIP_NULL, which asks
WriteAs::is_null rather than the value itself. A member that writes
itself would escape both.
A appears in no argument, so it is always turned up explicitly:
w.member_with::<Millis, _>(prefix, value).
Sourcepub fn write_tagged<T: Write + ?Sized>(&mut self, prefix: &str, value: &T)
pub fn write_tagged<T: Write + ?Sized>(&mut self, prefix: &str, value: &T)
Write an enum variant that carries a value: {"Name":value}.
prefix is the pre-quoted name with its colon, built at compile time
by the macro, exactly as Self::member takes one. A variant carrying
nothing is not written here at all: it is its own name, so it goes
through Self::write_str.
Options::SKIP_NULL deliberately does not reach here. Dropping the
member would leave {}, which names no variant and so is not a smaller
spelling of this value but a different one.
Sourcepub fn write_array<T: WriteArray>(&mut self, value: &T)
pub fn write_array<T: WriteArray>(&mut self, value: &T)
Write a struct as a JSON array.
The bracket counterpart of Self::write_object, down to the trailing
comma each element writes and the closing bracket that overwrites the
last of them.
Sourcepub fn element<T: Write + ?Sized>(&mut self, value: &T)
pub fn element<T: Write + ?Sized>(&mut self, value: &T)
Write one value, element.
Options::SKIP_NULL deliberately does not reach here. Dropping a null
from a sequence would shorten it and shift every index after it, which
is a change to the data rather than to its presentation.
Sourcepub fn write_seq_with<'i, A, T, I>(&mut self, items: I)
pub fn write_seq_with<'i, A, T, I>(&mut self, items: I)
Write a sequence as a JSON array, each element through an adapter.
Self::write_seq for elements the adapter describes rather than their
own Write impl. It is what Vec<A>’s WriteAs is built on, and
it is public so that an adapter defined outside this crate can write a
sequence whose elements another adapter describes; the bracket methods
are pub(crate), so write_seq and this are the two ways to a JSON
array. Elements described by neither trait still have to be turned into
something that is.
Sourcepub fn write_keyed<'i, K, V, I>(&mut self, entries: I)
pub fn write_keyed<'i, K, V, I>(&mut self, entries: I)
Write a map as a JSON object.
Keys go through ToJsonKey, so numeric keys come
out quoted, which is the only form JSON has for an object key.
Sourcepub fn write_keyed_with<'i, KA, VA, K, V, I>(&mut self, entries: I)where
KA: WriteKeyAs<K>,
VA: WriteAs<V>,
K: 'i + ?Sized,
V: 'i + ?Sized,
I: IntoIterator<Item = (&'i K, &'i V)>,
pub fn write_keyed_with<'i, KA, VA, K, V, I>(&mut self, entries: I)where
KA: WriteKeyAs<K>,
VA: WriteAs<V>,
K: 'i + ?Sized,
V: 'i + ?Sized,
I: IntoIterator<Item = (&'i K, &'i V)>,
Write a map as a JSON object, keys and values each through an adapter.
Self::write_keyed with both halves adapted, which is what
HashMap<KA, VA>’s WriteAs is built on. Name
Same for a half that wants the type’s own impl.
pub fn write_bool(&mut self, v: bool)
pub fn write_null(&mut self)
pub fn write_u64(&mut self, v: u64)
pub fn write_i64(&mut self, v: i64)
Sourcepub fn write_u128(&mut self, v: u128)
pub fn write_u128(&mut self, v: u128)
Write a u128.
Values past u64::MAX are rare enough that the wide path is a plain
loop rather than a table walk.
Sourcepub fn write_i128_raw(&mut self, v: i128)
pub fn write_i128_raw(&mut self, v: i128)
Write an i128, also used for the quoted-integer key path.
Sourcepub fn write_f64(&mut self, v: f64)
pub fn write_f64(&mut self, v: f64)
Write an f64. NaN and infinity have no JSON form, so they are written
as null, matching Glaze.
pub fn write_f32(&mut self, v: f32)
Sourcepub fn write_number_str(&mut self, s: &str)
pub fn write_number_str(&mut self, s: &str)
Write a number already in its JSON form.
The other half of
Parser::read_number_str,
which is where the case for the pair is written out.
§Panics
Under debug_assertions, if s is not one JSON number literal. That
is a bug in the caller rather than a condition to handle: the document
is already being written, so there is nowhere for an error to go and
nothing to do but publish something no reader will accept. Release
builds append s unchecked, as raw does.
use structio::{Standard, json::Writer};
let mut w = Writer::<Standard>::new();
w.write_number_str("-1.2345678901234567890123e400");
assert_eq!(w.into_string(), "-1.2345678901234567890123e400");