serde_nt 0.1.12

NestedText (de)serialization for serde, powered by nt_syntax
Documentation

serde_nt

NestedText (de)serialization for serde.

NestedText is a human-friendly configuration and data format: key: value dictionaries, - item lists and > text blocks, with no quoting and no escaping, and with every leaf stored as a string. This crate maps that data model onto Rust types through serde, in both directions.

  • Parses straight into your types, borrowed (&str, Cow<'_, str>) or owned.
  • Writes back with a stable, human-readable layout (2-space indent, > blocks for multiline values, multiline keys for keys that cannot be written inline).
  • Reports errors with the same message text and line numbers as the reference NestedText implementation.
  • Passes the complete official NestedText test suite (see Conformance).

Install

cargo add serde_nt

Usage

use serde::{Deserialize, Serialize};

#[derive(Debug, PartialEq, Serialize, Deserialize)]
struct Conf {
  host: String,
  port: u16,
  debug: bool,
  tag_li: Vec<String>,
}

let text = r#"
host: example.com
port: 8080
debug: no
tag_li:
    - alpha
    - beta
"#;

let conf: Conf = serde_nt::from_str(text)?;
assert_eq!(conf.port, 8080);
assert!(!conf.debug);

let out = serde_nt::to_string(&conf)?;
assert_eq!(serde_nt::from_str::<Conf>(&out)?, conf);
# Ok::<(), serde_nt::Error>(())

Public API:

Item Purpose
from_str::<T>(&str) parse NestedText text into T
to_string(&T) serialize T into NestedText text
from_value, to_value, dumps the same two directions over an already-parsed value tree
Error, Result error type, carries the document error with its line number

Type mapping

  • Strings map to strings, and are parsed into numbers, booleans, char and other FromStr types on demand; output uses itoa / zmij.
  • Option<T>: an empty value is None, a present value is Some.
  • Lists, maps, tuples and structs map to NestedText lists and dictionaries.
  • Enums map to a string or to a single-entry dictionary, so both unit and data-carrying variants work.
  • #[serde(untagged)] and #[serde(borrow)] are supported; borrowed deserialization avoids copying strings.

Writing rules

  • Indent is 2 spaces; multiline values are written as > blocks.
  • Keys that cannot be written inline (embedded : , leading/trailing spaces, tabs, newlines) become multiline keys.
  • \r\n and bare \r are normalized to \n on write.

Errors

NestedText has no schema, so every error is a document error and is reported by line. Error messages are kept 1:1 with the reference implementation, e.g. invalid indentation., duplicate key: name., expected ‘:’, found ‘}’., extra characters after closing delimiter: ‘b]’., and the line numbers agree with the reference on all official test cases.

Conformance

The official NestedText test suite (nestedtext_tests) is part of this repository and run on every build:

  • all 148 cases: 68 invalid documents and 80 valid documents (5 of which load to null for empty or comment-only input);
  • invalid documents: the error message and the line number are compared with the reference value of every case;
  • valid documents: the parsed result is compared with the reference output, and additionally round-tripped through to_string back into from_str.
cargo test -p serde_nt

Performance

Measured against nested-text on a 200-entry nested dictionary, aarch64 (Apple M-series), release profile, time and allocations per operation:

Operation serde_nt nested-text Allocations
parse into Rust types 168 µs borrowed, 220 µs owned 728 µs 638 / 2,438 vs 17,682
serialize to text 153 µs 489 µs 4 vs 10,415

Limitations

  • Byte arrays are not supported: NestedText has no binary type.
  • Dictionary keys must serialize to strings; a list or dictionary used as a key is an error.

License

Apache-2.0.


serde_nt(中文)

NestedText 的 serde 序列化 / 反序列化。

NestedText 是面向人类的配置与数据格式:key: value 字典、- item 列表、> text 多行块,无引号无转义,叶子一律为字符串。本 crate 通过 serde 在该数据模型与 Rust 类型之间双向映射。

  • 直接解析到目标类型,支持借用(&str、Cow<'_, str>)与拥有两种模式。
  • 写回布局稳定可读:2 空格缩进、多行值写 > 块、无法单行写出的键写多行键。
  • 错误文案与行号同官方实现逐字一致。
  • 官方 NestedText 测试集全量通过(见「一致性」)。

安装

cargo add serde_nt

用法

见上方英文示例:serde_nt::from_str 解析、serde_nt::to_string 写回; 另有 from_value / to_value / dumps,在已解析的值树上做同一组双向转换。

类型映射

  • 字符串原样;数字、布尔、char 及实现了 FromStr 的类型按字符串解析, 输出用 itoa / zmij。
  • Option<T>:空值为 None,有值为 Some。
  • 列表、映射、元组、struct 对应 NT 列表与字典。
  • 枚举对应字符串或单键字典,单元变体与带数据变体都可用。
  • 支持 #[serde(untagged)] 与 #[serde(borrow)],借用反序列化零拷贝。

写回规则

  • 缩进 2 空格;多行值写 > 块。
  • 不能单行写出的键(含 : 、首尾空白、制表符、换行)改写为多行键。
  • \r\n 与裸 \r 统一归一为 \n。

错误

NestedText 无 schema,所有错误都是文档错误并按行报告。文案与官方实现逐字一致, 如 invalid indentation.、duplicate key: name.、expected ‘:’, found ‘}’.、 extra characters after closing delimiter: ‘b]’.;官方测试集覆盖的全部用例中行号也一致。

一致性

官方 NestedText 测试集 (nestedtext_tests)随仓库内置, 每次构建全量跑:

  • 148 个用例:68 个非法、80 个合法(其中 5 个空文档/纯注释输入解析为 null);
  • 非法文档:错误文案与行号逐个同官方真值比对;
  • 合法文档:解析结果同官方真值比对,并额外做写回往返(解析 → 写回 → 再解析)。
cargo test -p serde_nt

性能

与 nested-text 对比 (200 条嵌套字典,aarch64 Apple M 系列,release 构建,每次操作耗时与分配次数):

操作 serde_nt nested-text 分配次数
解析为 Rust 类型 168 µs(借用)/ 220 µs(拥有) 728 µs 638 / 2,438 vs 17,682
序列化为文本 153 µs 489 µs 4 vs 10,415

限制

  • 不支持字节数组:NestedText 没有二进制类型。
  • 字典键必须序列化为字符串;用列表或字典作键会报错。

许可

Apache-2.0。