1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
//! Payload encoding posture (ADR-020 §4): payloads cross the trait as
//! [`serde_json::Value`]; engines serialize with serde_json and store
//! exactly those bytes — nothing re-encodes on the way out.
//!
//! Core provides the encode helper (the `Value` → stored-bytes
//! serialization the engines call) and the [`payload_as`] decode
//! convenience used by [`Job`](crate::Job) and
//! [`StreamEvent`](crate::StreamEvent). `serde`/`serde_json` are core's
//! only dependencies beyond `thiserror`.
use DeserializeOwned;
use crateError;
/// Serialize a trait-crossing payload `Value` to the stored byte form.
///
/// The engines call this at enqueue/publish time and store exactly the
/// returned bytes (ADR-020 §4): the stored bytes of a job row or
/// stream event row are, contract-pinned, the serde_json serialization
/// of the `Value` the call carried. Cross-engine byte equality falls
/// out — the same `Value` serializes identically on both engines.
///
/// Fallible per ADR-023 §1: serialization failure is
/// [`Error::Codec`](crate::Error::Codec), typed at this helper — no
/// silent fallback form exists (an empty-byte store would decode to
/// `Null`, silent data corruption). Failures here are two-fold: a
/// `Value` nested deeper than the depth limit (`PAYLOAD_DEPTH_LIMIT`)
/// is rejected — the stored bytes could never be read back, and the
/// serializer's own unguarded recursion would otherwise abort deep
/// enough — and genuine serialization failure maps through the same
/// typed arm.
/// The payload nesting cap: aligned with serde_json's deserialization
/// recursion limit (a nested-open at container depth 128 fails to
/// decode; depths through 127 read back). A `Value` nested deeper than
/// the cap produces stored bytes no decoder can read — silent data
/// loss at read time — and deep enough the (unguarded) serializer
/// itself would overflow the stack abortably; the encode side refuses
/// it instead.
const PAYLOAD_DEPTH_LIMIT: usize = 127;
/// The maximum number of containers on any path through `value`
/// (iterative, not recursive — a recursive walk would itself overflow
/// the stack on exactly the deep inputs this guards against).
/// Decode stored payload bytes into a concrete target type.
///
/// Used by [`Job::payload_as`](crate::Job::payload_as) and
/// [`StreamEvent::payload_as`](crate::StreamEvent::payload_as). The
/// error is [`Error::Codec`] on any deserialization failure (pinned).