Skip to main content

serpent_serializer/
lib.rs

1//! Serialize Lua values to round-trippable Lua source.
2//!
3//! This crate turns a [`Value`] graph into Lua source code that Lua's `load`
4//! reads back into an equivalent value graph. It is both a serializer and a
5//! pretty printer. It preserves shared references, reconstructs cyclic
6//! references, and emits arrays positionally, string keys in short notation, and
7//! the special numbers as `1/0`, `-1/0`, `0/0`.
8//!
9//! # Entry points
10//!
11//! - [`dump`] produces full serialization wrapped in a `do ... return _ end`
12//!   block with a self-reference section. Compact and sparse by default.
13//! - [`line`] produces single-line output. It is an expression, so prepend
14//!   `return ` to evaluate it.
15//! - [`block`] produces multi-line indented output. Also an expression.
16//! - [`serialize`] is the raw entry point with no default options.
17//! - [`load`] parses serialized output back into a [`Value`].
18//!
19//! # Example
20//!
21//! ```
22//! use serpent_serializer::{line, load, LoadOptions};
23//! use serpent_serializer::value::{Table, Key, Value};
24//!
25//! let t = Table::new();
26//! t.push(Value::Str(b"a".to_vec()));
27//! t.push(Value::Str(b"b".to_vec()));
28//! t.set(Key::Str(b"x".to_vec()), Value::Number(1.0));
29//!
30//! let src = line(&Value::Table(t)).unwrap();
31//! let back = load(&src, &LoadOptions::default()).unwrap();
32//! assert!(matches!(back, Value::Table(_)));
33//! ```
34
35#![forbid(unsafe_code)]
36#![warn(missing_docs)]
37
38pub mod load;
39pub mod numfmt;
40pub mod options;
41pub mod quote;
42pub mod serialize;
43pub mod value;
44
45pub use load::{load, LoadError, LoadOptions};
46pub use options::Options;
47pub use serialize::{serialize, SerError};
48pub use value::{Func, Global, Ident, Key, MetaError, MetaFn, Table, TableData, Value};
49
50/// Module name, matching serpent's `_NAME`.
51pub const NAME: &str = "serpent";
52/// Copyright holder, matching serpent's `_COPYRIGHT`.
53pub const COPYRIGHT: &str = "Paul Kulchenko";
54/// Description, matching serpent's `_DESCRIPTION`.
55pub const DESCRIPTION: &str = "Lua serializer and pretty printer";
56/// Version string, matching serpent's `_VERSION`.
57pub const VERSION: &str = "0.303";
58
59/// Full serialization: `name = "_"`, compact, sparse.
60///
61/// Output is a `do ... return _ end` block that returns the value when loaded.
62///
63/// # Errors
64///
65/// Propagates [`SerError`] from [`serialize`].
66pub fn dump(t: &Value) -> Result<String, SerError> {
67    serialize(t, &Options::dump())
68}
69
70/// Full serialization with extra options merged over the `dump` defaults.
71///
72/// # Errors
73///
74/// Propagates [`SerError`] from [`serialize`].
75///
76/// # Example
77///
78/// Build options over the `dump` defaults, then override what you need.
79///
80/// ```
81/// use serpent_serializer::{dump_with, Options};
82/// use serpent_serializer::value::{Table, Value};
83///
84/// let t = Table::new();
85/// t.push(Value::Number(1.0));
86/// let opts = Options { maxnum: Some(1), ..Options::dump() };
87/// let src = dump_with(&Value::Table(t), opts).unwrap();
88/// assert_eq!(src, "do local _={1};return _;end");
89/// ```
90pub fn dump_with(t: &Value, opts: Options) -> Result<String, SerError> {
91    serialize(t, &opts)
92}
93
94/// Single-line pretty printing. `sortkeys` and `comment` on.
95///
96/// Output is an expression. Prepend `return ` to evaluate it, which [`load`]
97/// does automatically.
98///
99/// # Errors
100///
101/// Propagates [`SerError`] from [`serialize`].
102pub fn line(t: &Value) -> Result<String, SerError> {
103    serialize(t, &Options::line())
104}
105
106/// Single-line pretty printing with caller options. Build the options over
107/// [`Options::line`], then override the fields you need.
108///
109/// # Errors
110///
111/// Propagates [`SerError`] from [`serialize`].
112pub fn line_with(t: &Value, opts: Options) -> Result<String, SerError> {
113    serialize(t, &opts)
114}
115
116/// Multi-line indented pretty printing. Two-space `indent`, `sortkeys`,
117/// `comment` on.
118///
119/// Output is an expression. Prepend `return ` to evaluate it.
120///
121/// # Errors
122///
123/// Propagates [`SerError`] from [`serialize`].
124pub fn block(t: &Value) -> Result<String, SerError> {
125    serialize(t, &Options::block())
126}
127
128/// Multi-line pretty printing with caller options. Build the options over
129/// [`Options::block`], then override the fields you need.
130///
131/// # Errors
132///
133/// Propagates [`SerError`] from [`serialize`].
134pub fn block_with(t: &Value, opts: Options) -> Result<String, SerError> {
135    serialize(t, &opts)
136}