Skip to main content

moq_json/
lib.rs

1//! JSON publishing over [`moq-net`](moq_net) tracks, in two modes:
2//!
3//! - [`snapshot`]: **lossy**. One JSON value updated over time; a consumer only gets the most
4//!   recent value. Intermediate updates are collapsed and older groups are dropped.
5//! - [`stream`]: **lossless**. An ordered append-log of self-contained records; every record is
6//!   preserved and delivered in order, nothing is ever superseded.
7//!
8//! Pick [`snapshot`] when consumers care about "what is the value now" (a catalog, a status
9//! document) and [`stream`] when they care about every record (an event log, a media timeline).
10//!
11//! Each mode comes in two layers. `Producer`/`Consumer` own a [`moq_net`] track and manage its
12//! groups. `Encoder`/`Decoder` are the same logic without the track: values in, frame payloads out
13//! (and back), with the encoder saying where the group boundaries fall. Reach for the codec layer
14//! when something else already owns the track, such as a `moq_mux::container::Producer` also
15//! managing a timeline and a catalog estimate.
16
17mod diff;
18pub mod snapshot;
19pub mod stream;
20
21pub use crate::diff::{Diff, diff};
22
23/// Errors produced while publishing or consuming JSON.
24#[derive(thiserror::Error, Debug, Clone)]
25#[non_exhaustive]
26pub enum Error {
27	/// An error from the underlying track.
28	#[error(transparent)]
29	Net(#[from] moq_net::Error),
30
31	/// A value failed to serialize, deserialize, or apply as a merge patch.
32	///
33	/// Stored as a string since [`serde_json::Error`] is not [`Clone`].
34	#[error("json: {0}")]
35	Json(String),
36
37	/// A compressed frame could not be decoded (malformed, truncated, or oversized).
38	#[error(transparent)]
39	Flate(#[from] moq_flate::Error),
40
41	/// A merge patch arrived with no snapshot to apply it to.
42	///
43	/// Every group opens with a full snapshot, so this means frames reached
44	/// [`snapshot::Decoder`] out of order, or a group's first frame was routed as a delta.
45	#[error("delta before snapshot")]
46	MissingSnapshot,
47
48	/// A compressed [`stream`] frame was encoded but never written, so the shared DEFLATE window is
49	/// ahead of what the consumer holds and nothing later in this group can be decoded.
50	///
51	/// Unlike [`snapshot`], a stream has no keyframe to resynchronize on, so the encoder refuses to
52	/// continue rather than emit frames that cannot be read. Recover by rolling a new group and
53	/// calling [`stream::Encoder::reset`].
54	#[error("compression desynchronized: a frame was encoded but never written")]
55	Desync,
56}
57
58impl From<serde_json::Error> for Error {
59	fn from(err: serde_json::Error) -> Self {
60		Error::Json(err.to_string())
61	}
62}
63
64/// A [`Result`](std::result::Result) using this crate's [`Error`].
65pub type Result<T> = std::result::Result<T, Error>;