Skip to main content

Writer

Struct Writer 

Source
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<O: Options> Writer<'static, O>

Source

pub fn new() -> Self

Source

pub fn with_capacity(n: usize) -> Self

Source

pub fn from_vec(buf: Vec<u8>) -> Self

Reuse an existing buffer, discarding whatever it held.

Source§

impl<'a, O: Options> Writer<'a, O>

Source

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.

Source

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.

Source

pub fn as_bytes(&self) -> &[u8] ⓘ

The bytes written so far, or with a sink, the bytes not yet drained.

Source

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.

Source

pub fn into_vec(self) -> Vec<u8> ⓘ

Source

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.

Source

pub fn is_empty(&self) -> bool

Source

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.

Source

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.

Source

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.

Source

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.

Examples found in repository?
examples/manual_impls.rs (line 71)
70    fn write<O: Options>(&self, w: &mut Writer<'_, O>) {
71        w.write_object(self)
72    }
Source

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.

Examples found in repository?
examples/manual_impls.rs (line 58)
57    fn write_fields<O: Options>(&self, w: &mut Writer<'_, O>) {
58        w.member("\"first_name\":", &self.first_name);
59        w.member("\"age\":", &self.age);
60        w.member("\"friends\":", &self.friends);
61    }
Source

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).

Source

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.

Source

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.

Source

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.

Source

pub fn write_seq<'i, T, I>(&mut self, items: I)
where T: Write + 'i, I: IntoIterator<Item = &'i T>,

Write a sequence as a JSON array.

Source

pub fn write_seq_with<'i, A, T, I>(&mut self, items: I)
where A: WriteAs<T>, T: 'i + ?Sized, I: IntoIterator<Item = &'i T>,

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.

Source

pub fn write_keyed<'i, K, V, I>(&mut self, entries: I)
where K: ToJsonKey + 'i, V: Write + 'i, I: IntoIterator<Item = (&'i K, &'i V)>,

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.

Source

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.

Source

pub fn write_bool(&mut self, v: bool)

Source

pub fn write_null(&mut self)

Source

pub fn write_u64(&mut self, v: u64)

Source

pub fn write_i64(&mut self, v: i64)

Source

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.

Source

pub fn write_i128_raw(&mut self, v: i128)

Write an i128, also used for the quoted-integer key path.

Source

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.

Source

pub fn write_f32(&mut self, v: f32)

Source

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");
Source

pub fn write_str(&mut self, s: &str)

Write a quoted, escaped JSON string.

The common case is a string with nothing to escape, so the scan runs eight bytes at a time and copies whole runs between escapes rather than testing byte by byte.

Trait Implementations§

Source§

impl<O: Options> Default for Writer<'static, O>

Source§

fn default() -> Self

Returns the “default value” for a type. Read more

Auto Trait Implementations§

§

impl<'a, O = Standard> !RefUnwindSafe for Writer<'a, O>

§

impl<'a, O = Standard> !Send for Writer<'a, O>

§

impl<'a, O = Standard> !Sync for Writer<'a, O>

§

impl<'a, O = Standard> !UnwindSafe for Writer<'a, O>

§

impl<'a, O> Freeze for Writer<'a, O>
where PhantomData<fn() -> O>: Freeze,

§

impl<'a, O> Unpin for Writer<'a, O>
where PhantomData<fn() -> O>: Unpin,

§

impl<'a, O> UnsafeUnpin for Writer<'a, O>
where PhantomData<fn() -> O>: UnsafeUnpin,

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.