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
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
//! Portable figures: a self-describing artifact that renders itself anywhere.
//!
//! This module implements the `.riz` artifact of `design/10-portable-figure.md`
//! (issue #287): a chunked binary container holding a strict, versioned wire
//! model of the semantic figure — `Figure → Axes → Artists`, data, and rcparams
//! — from which an identical [`Figure`](crate::figure::Figure) is
//! reconstructed and rendered through the ordinary pipeline. The promise is
//! **pixel identity**: `Figure::from_portable(fig.to_portable()?)` renders
//! byte-for-byte the same PNG as `fig` itself.
//!
//! - `spec` — the wire model: plain serde mirrors of the live types, every
//! struct `deny_unknown_fields`, every enum closed. Unknown content is a hard
//! error, never silently dropped: a figure missing an artist is a
//! scientifically wrong figure.
//! - `data` — typed binary accessors: bulk arrays live in one binary chunk,
//! referenced by index from the JSON spec.
//! - `container` — the `RZFG` chunked container framing JSON + binary.
//!
//! The public entry points live on `Figure`:
//! [`to_portable`](crate::figure::Figure::to_portable),
//! [`save_portable`](crate::figure::Figure::save_portable), and
//! [`from_portable`](crate::figure::Figure::from_portable).
// The wire types (`spec`, and the accessor descriptors in `data`) are always
// compiled: the `Scale`/`Locator`/`Formatter` hooks on the public axis traits
// name them regardless of feature. The machinery that *uses* them — container
// framing and the data bank — is feature-gated along with the JSON codec.
pub
pub
pub
/// The portable wire form of a built-in [`Scale`](crate::axis::scale::Scale).
///
/// Opaque by design. The wire model is rizzma's own schema, so only the
/// built-in scales can produce one: a third-party [`Scale`](crate::axis::scale::Scale)
/// returns `None` from [`Scale::portable_spec`](crate::axis::scale::Scale::portable_spec),
/// and exporting a figure that uses it fails loudly rather than substituting a
/// different scale.
ScaleWire);
/// The portable wire form of a built-in [`Locator`](crate::axis::ticker::Locator).
///
/// Opaque by design; see [`PortableScale`].
LocatorSpec);
/// The portable wire form of a built-in [`Formatter`](crate::axis::ticker::Formatter).
///
/// Opaque by design; see [`PortableScale`]. Notably
/// [`FuncFormatter`](crate::axis::ticker::FuncFormatter) has none — a Rust
/// closure cannot cross the wire — so exporting an axis that uses one fails
/// with [`PortableError::Unsupported`].
FormatterSpec);
/// Wire-format schema version written into every artifact.
///
/// Bumped whenever anything changes that would alter how an existing artifact
/// renders. Loaders support the contiguous range
/// [`SCHEMA_MIN`]`..=`[`SCHEMA_VERSION`] and reject anything newer with a hard
/// error rather than render a figure with content missing.
pub const SCHEMA_VERSION: u32 = 1;
/// Oldest schema version this build can still load.
pub const SCHEMA_MIN: u32 = 1;
/// Errors from portable-figure export and import.
///
/// The import path is strict by design: malformed containers, out-of-bounds
/// accessors, unknown fields or enum variants, and future schema versions all
/// fail loudly instead of best-effort rendering.