swsml 0.1.0

SML (SNOWARE Markup Language) — declarative data/config format, a JSON/YAML alternative
Documentation
swsml-0.1.0 has been yanked.

swsml

SML — SNOWARE Markup Language 的 Rust 实现:声明式数据/配置格式,JSON/YAML 的替代品。

SML 源于 eclog,在其基础上演进为独立格式。

包名是 swsml 而非 sml-rs——后者已被无关项目占用 (Smart Message Language 智能电表协议解析器)。 lib 名仍为 sml,因此 use sml::{...} 不受影响。

Logo:黑花括号 {} 表示语法骨架(块的边界),蓝色雪花 表示精确的取值点。

特性

特性 说明
引号可选 裸词即字符串(state: NY
块冒号可省 address { }address: { }
数组分隔灵活 [ a b c ]、每行一个、逗号可选
片段继承 @name { } 定义,&name 引用
include 指令 拆分配置,可嵌套、可在块内注入字段
版本声明 @version v1,便于将来演进不破坏旧文档
环境变量内联 $env.VAR
类型自识别 true/false/null / 数字 / 字符串

版本声明

@version v1
app: resender
  • v1 为当前版本;未声明时默认按当前版本处理,既有文档不受影响
  • 声明了实现不支持的版本会报错,而非静默按错误语法解析
  • 允许多次声明(include 进来的文件可各自声明),但必须一致
  • version 是保留字,不可作为片段名
use sml::{parse_versioned, Version};

let (v, ver) = parse_versioned("@version v1\nname: John")?;
assert_eq!(ver, Version::V1);

// 只需数据时用 parse 即可,它会自动剥离版本声明
let v = parse("@version v1\nname: John")?;

文件版本:parse_file_versioned("app.sml")

firstName: John
age: 27
address:
{
    streetAddress: "21 2nd Street"
    state: NY
}
phoneNumbers: [ { type: home } { type: office } ]
@base { region: cn-north-1 }
server web { &base port: 8080 }

用法

[dependencies]
swsml = "0.1"

# 需要 serde 互操作时:
# swsml = { version = "0.1", features = ["serde"] }
use sml::{parse, to_sml};

let v = parse("name: John\nage: 27")?;
assert_eq!(v.get("name").and_then(|x| x.as_str()), Some("John"));
assert_eq!(v.get("age"), Some(&sml::Value::Int(27)));
println!("{}", to_sml(&v));

include 指令

# app.sml
app: resender
database {
    include "conf.d/db.sml"   # 在块内注入一组字段
    pool: 16
}
use sml::parse_file;
let v = parse_file("app.sml")?;
  • 相对路径按被包含文件自身所在目录解析(同 C 预处理器),嵌套时行为可预期
  • 语义是文本内联而非对象合并,因此可出现在块内部
  • 循环引用、文件缺失均返回错误,不静默跳过;嵌套上限 32 层
  • 引号内的 # 不会被误判为注释

parse() 是纯函数(不做 IO),include 由 parse_file() / resolve_includes() 处理。 这样在无文件系统的环境(WASM / 沙箱)中仍可安全嵌入 parse()

运行示例:

cargo run --example include_demo
cargo run --example include_demo --features serde   # 额外打印 JSON

serde 支持(可选)

启用 serde feature 后,Value 实现 Serialize/Deserialize,可与任意 serde 后端互操作:

let v = parse("name: John\nage: 27")?;
let json = serde_json::to_string(&v)?;      // {"name":"John","age":27}
let back: sml::Value = serde_json::from_str(&json)?;

采用手写实现而非 #[derive],以保证数据形状自然: Value::Int(27) 序列化为 27,而非 derive 会产生的 {"Int":27}

不启用该 feature 时,本 crate 为零依赖

多语言实现

语言 位置
Soup / Lua ../lua/lib/sml.soup
Rust 本目录(sml-rs
C ../c/sml.h
JavaScript ../js/sml.mjs

License

MulanPSL-2.0