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
143
144
145
//! Support for the [SQLite JSONB] format in [Müsli].
//!
//! JSONB is the binary representation which SQLite uses internally for its
//! `json` functions. It carries exactly the same data model as JSON, but every
//! element is prefixed with a header giving its type and the size of its
//! payload, so a document can be traversed without scanning the parts of it
//! which are not of interest.
//!
//! The module is named after SQLite rather than after the format because the
//! format is defined by what SQLite does with it. It exists to exchange data
//! with an SQLite database, and anything encoded with it inherits the
//! limitations of the JSON data model. Reach for [`descriptive`] or [`wire`]
//! for a general purpose binary format.
//!
//! [`descriptive`]: crate::descriptive
//! [`wire`]: crate::wire
//!
//! Encoding is upgrade stable in the same way that [`json`] is:
//!
//! * ✔ Can tolerate missing fields if they are annotated with
//! `#[musli(default)]`.
//! * ✔ Can skip over unknown fields.
//!
//! [Müsli]: https://github.com/udoprog/musli
//! [SQLite JSONB]: https://sqlite.org/draft/jsonb.html
//! [`json`]: crate::json
//!
//! ```
//! use musli::{Encode, Decode};
//!
//! #[derive(Debug, PartialEq, Encode, Decode)]
//! struct Version1 {
//! name: String,
//! }
//!
//! #[derive(Debug, PartialEq, Encode, Decode)]
//! struct Version2 {
//! name: String,
//! #[musli(default)]
//! age: Option<u32>,
//! }
//!
//! let version2 = musli::sqlite_jsonb::to_vec(&Version2 {
//! name: String::from("Aristotle"),
//! age: Some(61),
//! })?;
//!
//! let version1: Version1 = musli::sqlite_jsonb::from_slice(version2.as_slice())?;
//!
//! assert_eq!(version1, Version1 {
//! name: String::from("Aristotle"),
//! });
//! # Ok::<_, musli::sqlite_jsonb::Error>(())
//! ```
//!
//! <br>
//!
//! ## Interoperability
//!
//! The output is a JSONB blob as SQLite would store it, so it can be handed
//! straight to SQLite and read back with the `json` functions:
//!
//! ```
//! let blob = musli::sqlite_jsonb::to_vec(&(1u32, 2u32))?;
//! assert_eq!(blob, [0x4b, 0x13, b'1', 0x13, b'2']);
//! // SELECT json(?) with the blob above returns the text `[1,2]`.
//! # Ok::<_, musli::sqlite_jsonb::Error>(())
//! ```
//!
//! A blob goes into a column as it is, so a document can be written by this
//! encoder, queried and edited in SQL, and decoded again without ever being
//! rendered as text. The [`sqlite_jsonb` example] does all of that against an
//! in-memory database:
//!
//! ```text
//! cargo run -p musli --example sqlite_jsonb --features sqlite-jsonb
//! ```
//!
//! [`sqlite_jsonb` example]:
//! https://github.com/udoprog/musli/blob/main/crates/musli/examples/sqlite_jsonb.rs
//!
//! <br>
//!
//! ## Implementation details
//!
//! Every element starts with a header of between 1 and 9 bytes. The lower four
//! bits of the first byte are the element type, and the upper four bits either
//! hold the size of the payload directly, for payloads of up to 11 bytes, or
//! say how many bytes of big-endian payload size follow.
//!
//! Numbers are stored as ASCII text, exactly as they would appear in a JSON
//! document. Integers use the `INT` type. Floats use the `FLOAT` type, except
//! for infinities and NaN which have no canonical JSON representation and are
//! stored as the JSON5 `FLOAT5` values `Infinity`, `-Infinity` and `NaN`.
//!
//! Strings are stored without delimiters. A string which needs no escaping to
//! be rendered as JSON uses the `TEXT` type, one which does uses `TEXTRAW`,
//! which stores it verbatim. The escaped `TEXTJ` and `TEXT5` types are
//! translated when decoding, since they are what SQLite produces when it
//! converts JSON text to JSONB.
//!
//! Like [`json`], byte arrays are encoded as arrays of numbers, and variants
//! are externally tagged, so they are encoded as an object with a single entry.
/// Convenient result alias for use with `musli::sqlite_jsonb`.
pub type Result<T, E = Error> = Result;
pub use ;
pub use Encoding;
pub use to_vec;
pub use to_writer;
pub use ;
pub use Error;