serpent-serializer 0.2.0

Serialize Lua values to round-trippable Lua source with cycle and shared-reference handling
Documentation
//! Serialize Lua values to round-trippable Lua source.
//!
//! This crate turns a [`Value`] graph into Lua source code that Lua's `load`
//! reads back into an equivalent value graph. It is both a serializer and a
//! pretty printer. It preserves shared references, reconstructs cyclic
//! references, and emits arrays positionally, string keys in short notation, and
//! the special numbers as `1/0`, `-1/0`, `0/0`.
//!
//! # Entry points
//!
//! - [`dump`] produces full serialization wrapped in a `do ... return _ end`
//!   block with a self-reference section. Compact and sparse by default.
//! - [`line`] produces single-line output. It is an expression, so prepend
//!   `return ` to evaluate it.
//! - [`block`] produces multi-line indented output. Also an expression.
//! - [`serialize`] is the raw entry point with no default options.
//! - [`load`] parses serialized output back into a [`Value`].
//!
//! # Example
//!
//! ```
//! use serpent_serializer::{line, load, LoadOptions};
//! use serpent_serializer::value::{Table, Key, Value};
//!
//! let t = Table::new();
//! t.push(Value::Str(b"a".to_vec()));
//! t.push(Value::Str(b"b".to_vec()));
//! t.set(Key::Str(b"x".to_vec()), Value::Number(1.0));
//!
//! let src = line(&Value::Table(t)).unwrap();
//! let back = load(&src, &LoadOptions::default()).unwrap();
//! assert!(matches!(back, Value::Table(_)));
//! ```

#![forbid(unsafe_code)]
#![warn(missing_docs)]

pub mod load;
pub mod numfmt;
pub mod options;
pub mod quote;
pub mod serialize;
pub mod value;

pub use load::{load, LoadError, LoadOptions};
pub use options::Options;
pub use serialize::{serialize, SerError};
pub use value::{Func, Global, Ident, Key, MetaError, MetaFn, Table, TableData, Value};

/// Module name, matching serpent's `_NAME`.
pub const NAME: &str = "serpent";
/// Copyright holder, matching serpent's `_COPYRIGHT`.
pub const COPYRIGHT: &str = "Paul Kulchenko";
/// Description, matching serpent's `_DESCRIPTION`.
pub const DESCRIPTION: &str = "Lua serializer and pretty printer";
/// Version string, matching serpent's `_VERSION`.
pub const VERSION: &str = "0.303";

/// Full serialization: `name = "_"`, compact, sparse.
///
/// Output is a `do ... return _ end` block that returns the value when loaded.
///
/// # Errors
///
/// Propagates [`SerError`] from [`serialize`].
pub fn dump(t: &Value) -> Result<String, SerError> {
    serialize(t, &Options::dump())
}

/// Full serialization with extra options merged over the `dump` defaults.
///
/// # Errors
///
/// Propagates [`SerError`] from [`serialize`].
///
/// # Example
///
/// Build options over the `dump` defaults, then override what you need.
///
/// ```
/// use serpent_serializer::{dump_with, Options};
/// use serpent_serializer::value::{Table, Value};
///
/// let t = Table::new();
/// t.push(Value::Number(1.0));
/// let opts = Options { maxnum: Some(1), ..Options::dump() };
/// let src = dump_with(&Value::Table(t), opts).unwrap();
/// assert_eq!(src, "do local _={1};return _;end");
/// ```
pub fn dump_with(t: &Value, opts: Options) -> Result<String, SerError> {
    serialize(t, &opts)
}

/// Single-line pretty printing. `sortkeys` and `comment` on.
///
/// Output is an expression. Prepend `return ` to evaluate it, which [`load`]
/// does automatically.
///
/// # Errors
///
/// Propagates [`SerError`] from [`serialize`].
pub fn line(t: &Value) -> Result<String, SerError> {
    serialize(t, &Options::line())
}

/// Single-line pretty printing with caller options. Build the options over
/// [`Options::line`], then override the fields you need.
///
/// # Errors
///
/// Propagates [`SerError`] from [`serialize`].
pub fn line_with(t: &Value, opts: Options) -> Result<String, SerError> {
    serialize(t, &opts)
}

/// Multi-line indented pretty printing. Two-space `indent`, `sortkeys`,
/// `comment` on.
///
/// Output is an expression. Prepend `return ` to evaluate it.
///
/// # Errors
///
/// Propagates [`SerError`] from [`serialize`].
pub fn block(t: &Value) -> Result<String, SerError> {
    serialize(t, &Options::block())
}

/// Multi-line pretty printing with caller options. Build the options over
/// [`Options::block`], then override the fields you need.
///
/// # Errors
///
/// Propagates [`SerError`] from [`serialize`].
pub fn block_with(t: &Value, opts: Options) -> Result<String, SerError> {
    serialize(t, &opts)
}