pub trait ToJson {
const MIN_SERIALIZED_LEN: usize = 0;
const MAX_SERIALIZED_LEN: usize = 0;
const NEEDS_VALIDATION: bool = false;
// Required method
fn write_json<W: JsonWrite + ?Sized>(
&self,
w: &mut W,
) -> Result<(), W::Error>;
// Provided methods
unsafe fn write_json_in_reserved<W: JsonWrite + ?Sized>(
&self,
w: &mut W,
) -> Result<(), W::Error> { ... }
fn pre_validate_slice(slice: &[Self]) -> Result<(), Error>
where Self: Sized { ... }
}Expand description
Types that know how to serialize themselves to a JsonWrite sink.
This is the dual of crate::FromJson. Implementors call sink methods
directly — there is no intermediate Value representation.
Provided Associated Constants§
Sourceconst MIN_SERIALIZED_LEN: usize = 0
const MIN_SERIALIZED_LEN: usize = 0
Sourceconst MAX_SERIALIZED_LEN: usize = 0
const MAX_SERIALIZED_LEN: usize = 0
Upper bound on the bytes a single write_json call emits, used by
sequence impls to pre-reserve buffer capacity. 0 means “no useful
upper bound” — sequence impls skip the reservation in that case.
Primitives with a known maximum output length (floats, ints, bools)
override this. Variable-length types (str, Vec<T>, structs) keep
the default, since their per-element size depends on payload.
Sourceconst NEEDS_VALIDATION: bool = false
const NEEDS_VALIDATION: bool = false
Whether this type requires a pre-scan validation pass before
the per-element fast path can be entered. Defaults to false.
f64 / f32 set this to true so the slice writer scans the
whole slice once for non-finite values and rejects up front.
The inner element-by-element loop then runs branchless w.r.t.
finiteness — measured 13.43% of all mispredicts before the
pre-scan was added.
Required Methods§
Provided Methods§
Sourceunsafe fn write_json_in_reserved<W: JsonWrite + ?Sized>(
&self,
w: &mut W,
) -> Result<(), W::Error>
unsafe fn write_json_in_reserved<W: JsonWrite + ?Sized>( &self, w: &mut W, ) -> Result<(), W::Error>
Serialize self into w ASSUMING the caller has already reserved
at least MAX_SERIALIZED_LEN writable bytes in the sink. Used by
[[T]::write_json] after its reserve_hint call so the per-element
path skips its own cap checks.
Default impl forwards to write_json (safe + checked). Primitives
override with sink-specific unchecked variants. For MAX_SERIALIZED_LEN == 0 types this method is never called.
§Safety
Self::MAX_SERIALIZED_LEN bytes of sink capacity must be guaranteed
available before this call. For types where
Self::NEEDS_VALIDATION is true, Self::pre_validate_slice
must have been called on the enclosing slice (and returned Ok)
before invoking this method, so the per-element write can assume
the type’s validity precondition (e.g. finiteness for floats).
Sourcefn pre_validate_slice(slice: &[Self]) -> Result<(), Error>where
Self: Sized,
fn pre_validate_slice(slice: &[Self]) -> Result<(), Error>where
Self: Sized,
Validate that every element of slice satisfies the type’s
per-element precondition (e.g. finiteness). Called by the slice
writer ONCE before the per-element loop when NEEDS_VALIDATION
is true.
Default impl is a no-op. The Result carries crate::Error
directly because all current validators reject with that type;
callers that want a different sink error must map.
slice is &[Self] rather than &[T] because the validator
always sees a homogeneous slice (it’s invoked from the slice
impl). On non-slice paths this method is never called.
Dyn Compatibility§
This trait is not dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety".
Implementations on Foreign Types§
Source§impl ToJson for Duration
Available on crate feature std only.Encode Duration as fractional seconds, mirroring the parse-side
from_secs_f64 adapter. Negative durations are unrepresentable
(Duration is unsigned), and the float impl already rejects
non-finite output, so this never errors for valid inputs.
impl ToJson for Duration
std only.Encode Duration as fractional seconds, mirroring the parse-side
from_secs_f64 adapter. Negative durations are unrepresentable
(Duration is unsigned), and the float impl already rejects
non-finite output, so this never errors for valid inputs.
Source§impl ToJson for PathBuf
Available on crate feature std only.PathBuf round-trips only for paths whose bytes are valid UTF-8.
Path::display() lossily replaces invalid bytes — we want a
clean error in that case, but JSON has no lossless path encoding
anyway, so the convention matches the parse side: assume UTF-8.
to_string_lossy here is the symmetric move.
impl ToJson for PathBuf
std only.PathBuf round-trips only for paths whose bytes are valid UTF-8.
Path::display() lossily replaces invalid bytes — we want a
clean error in that case, but JSON has no lossless path encoding
anyway, so the convention matches the parse side: assume UTF-8.
to_string_lossy here is the symmetric move.
Source§impl ToJson for SocketAddr
Available on crate feature std only.
impl ToJson for SocketAddr
std only.Source§impl ToJson for SystemTime
Available on crate feature std only.Encode SystemTime as fractional seconds since UNIX_EPOCH.
Times before the epoch serialize as negative numbers; the
parse side accepts the same shape.
impl ToJson for SystemTime
std only.Encode SystemTime as fractional seconds since UNIX_EPOCH.
Times before the epoch serialize as negative numbers; the
parse side accepts the same shape.
Source§impl ToJson for char
JSON has no char primitive — encode as a one-character string,
matching the FromJson direction.
impl ToJson for char
JSON has no char primitive — encode as a one-character string,
matching the FromJson direction.
Source§impl ToJson for f32
f32 widens losslessly to f64 for serialization. The decoded
form on the parse side narrows via as f32, mirroring this.
impl ToJson for f32
f32 widens losslessly to f64 for serialization. The decoded
form on the parse side narrows via as f32, mirroring this.
Source§unsafe fn write_json_in_reserved<W: JsonWrite + ?Sized>(
&self,
w: &mut W,
) -> Result<(), W::Error>
unsafe fn write_json_in_reserved<W: JsonWrite + ?Sized>( &self, w: &mut W, ) -> Result<(), W::Error>
SAFETY: caller has reserved MAX_SERIALIZED_LEN bytes via
reserve_hint. Non-finite inputs are tolerated via the
sink’s taint accumulator.
const MIN_SERIALIZED_LEN: usize = 1
const MAX_SERIALIZED_LEN: usize = 32
const NEEDS_VALIDATION: bool = false
fn write_json<W: JsonWrite + ?Sized>(&self, w: &mut W) -> Result<(), W::Error>
Source§impl ToJson for f64
impl ToJson for f64
Source§unsafe fn write_json_in_reserved<W: JsonWrite + ?Sized>(
&self,
w: &mut W,
) -> Result<(), W::Error>
unsafe fn write_json_in_reserved<W: JsonWrite + ?Sized>( &self, w: &mut W, ) -> Result<(), W::Error>
SAFETY: caller (write_array_reserved) has reserved
MAX_SERIALIZED_LEN bytes via reserve_hint. Non-finite
inputs do not break safety — they are routed through the
sink’s taint-tracking float write, which substitutes a
finite placeholder before calling teju and accumulates a
taint bit. The slice writer queries the sink’s taint after
the loop and converts it to an error.
Source§fn pre_validate_slice(_slice: &[Self]) -> Result<(), Error>
fn pre_validate_slice(_slice: &[Self]) -> Result<(), Error>
Validation is deferred into the per-element taint write —
the pre-scan pass was costing ~20% of total cycles per
perf record -c cycles (the SIMD pand/pcmpeqd loop). The
merged taint path costs only ~3 extra instructions per
element (bit-mask check + cmov substitute + OR accumulate)
and removes the separate pass entirely.