Skip to main content

sml/
lib.rs

1// SPDX-License-Identifier: MulanPSL-2.0
2//! SML — SNOWARE Markup Language (Rust 实现, crate 名 `sml`)
3//!
4//! 声明式数据/配置格式, JSON/YAML 的替代品。语法与 Soup 生态的
5//! `lib/sml.soup` (Lua) 对齐:
6//!
7//! ```sml
8//! firstName: John
9//! age: 27
10//! address:
11//! {
12//!     streetAddress: "21 2nd Street"
13//!     state: NY
14//! }
15//! phoneNumbers: [ { type: home } { type: office } ]
16//! @base { region: cn-north-1 }
17//! server web { &base port: 8080 }
18//! ```
19//!
20//! 特性:
21//! - 引号可选 (裸词即字符串)
22//! - 块冒号可省 (`address { }` ≡ `address: { }`)
23//! - 数组分隔灵活 (逗号可选)
24//! - 片段继承 (`@name { }` 定义 / `&name` 引用)
25//! - `include "path"` 引入外部文件(见 [`parse_file`])
26//! - `$env.VAR` 环境变量内联
27//! - `#` 行注释
28//! - 类型自识别: true/false -> bool, null -> None, 数字 -> i64/f64, 其余 -> String
29//!
30//! 值模型: `Value` 枚举 (与 JSON 同构, 另加 `__type`/`__name` 裸块元数据)。
31//!
32//! # 纯解析 vs 文件解析
33//!
34//! [`parse`] 是**纯函数**(只吃字符串,不做 IO),因此不含 include 处理。
35//! 需要 include 时用 [`parse_file`],它会先展开指令再交给 `parse`。
36//! 这样设计保证了 `parse` 的可嵌入性(如 WASM / 沙箱内无文件系统)。
37//!
38//! # Cargo features
39//!
40//! - `serde`(默认关闭):`Value` 实现 `Serialize`/`Deserialize`,可与
41//!   serde_json / serde_yaml / toml 等任意 serde 后端互通;同时提供
42//!   [`serde::from_str`] / [`serde::from_value`] / [`serde::to_value`] /
43//!   [`serde::to_string`] 桥接函数,任何 `#[derive(serde::Deserialize)]`
44//!   类型都能像 toml-rs 一样一键从 SML 反序列化(无需 `SmlDeserialize`)。
45//! - `derive`(默认开启):提供 [`SmlSerialize`] / [`SmlDeserialize`]
46//!   两个 derive 宏,把自定义结构体/枚举「自然地」序列化为 SML,
47//!   无需引入 serde。
48//!
49//! ```toml
50//! sml-rs = { version = "0.2", features = ["serde"] }
51//! # 不需要宏时可关闭默认 feature,回到完全零依赖:
52//! sml-rs = { version = "0.2", default-features = false }
53//! ```
54
55use std::collections::BTreeMap;
56use std::fmt;
57use std::path::{Path, PathBuf};
58
59// ---------------------------------------------------------------------------
60// 值模型
61// ---------------------------------------------------------------------------
62
63#[derive(Debug, Clone, PartialEq)]
64pub enum Value {
65    Null,
66    Bool(bool),
67    Int(i64),
68    Float(f64),
69    Str(String),
70    Array(Vec<Value>),
71    /// 对象/块; `__type` / `__name` 裸块元数据以保留字键存放
72    Object(BTreeMap<String, Value>),
73}
74
75impl Value {
76    /// 对象字段按需取 (支持 "." 点路径)
77    pub fn get(&self, path: &str) -> Option<&Value> {
78        let mut cur = self;
79        for seg in path.split('.') {
80            match cur {
81                Value::Object(m) => cur = m.get(seg)?,
82                _ => return None,
83            }
84        }
85        Some(cur)
86    }
87    /// 字符串视图 (字符串直接返回; 其它返回 None)
88    pub fn as_str(&self) -> Option<&str> {
89        match self {
90            Value::Str(s) => Some(s),
91            _ => None,
92        }
93    }
94}
95
96impl fmt::Display for Value {
97    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
98        write!(f, "{}", to_sml(self))
99    }
100}
101
102// ---------------------------------------------------------------------------
103// 契约(Contract)—— 可选的 schema 层
104//
105// SML 本身是纯数据格式(与 JSON/YAML 同层),值模型只有 7 种类型,
106// **不具备**结构体定义、枚举、字段约束等类型系统能力。
107// 契约是在此之上的**可选校验层**,用于给块加上结构与取值约束:
108//
109// ```sml
110// @contract Server {
111//     host: str                      # 必填
112//     port: int default 8080         # 带默认值
113//     tls: bool default true
114//     tags: [str] optional           # 可选
115//     status: enum [ active retired ]
116//     ratio: num min 0 max 1
117// }
118//
119// database {
120//     @is Server                     # 应用契约
121//     host: db1.internal
122//     status: active
123// }
124// ```
125//
126// 语义:
127// - `@contract Name { ... }` 定义契约(不进主树)
128// - `@is Name` 在当前块应用契约:缺失字段用 default 填充;
129//   缺少且无默认值的必填字段、类型不符、枚举值越界、数值越 min/max 均报错
130// - 契约须在 `@is` **之前**定义(顺序依赖,与片段继承一致)
131// - 不使用契约时行为完全不变,因此**向后兼容**
132// ---------------------------------------------------------------------------
133
134/// 契约中的字段类型
135#[derive(Debug, Clone, PartialEq)]
136pub enum TypeSpec {
137    /// 任意类型
138    Any,
139    /// 引用另一个契约(**组合**)——字段值须是块,并递归按被引用契约校验。
140    /// 用组合而非继承:契约之间不共享字段,而是「字段的类型是另一个契约」。
141    /// 语法上复用裸词(写被引用的契约名),因此不引入任何新 token:
142    ///     @contract Address { city: str }
143    ///     @contract Server { address: Address }
144    ContractRef(String),
145    Str,
146    Int,
147    /// 数值:int 或 float 均可
148    Num,
149    Bool,
150    /// 数组,元素须为指定类型
151    Array(Box<TypeSpec>),
152    /// 枚举:取值须在给定列表中
153    Enum(Vec<String>),
154}
155
156impl TypeSpec {
157    fn name(&self) -> String {
158        match self {
159            TypeSpec::Any => "any".into(),
160            TypeSpec::Str => "str".into(),
161            TypeSpec::Int => "int".into(),
162            TypeSpec::Num => "num".into(),
163            TypeSpec::Bool => "bool".into(),
164            TypeSpec::Array(inner) => format!("[{}]", inner.name()),
165            TypeSpec::Enum(vals) => format!("enum [{}]", vals.join(" ")),
166            TypeSpec::ContractRef(name) => name.clone(),
167        }
168    }
169}
170
171/// 契约中的字段规格
172#[derive(Debug, Clone)]
173pub struct FieldSpec {
174    pub ty: TypeSpec,
175    /// 是否必填(默认 true)
176    pub required: bool,
177    /// 缺失时填充的默认值
178    pub default: Option<Value>,
179    /// 数值下界(含)
180    pub min: Option<f64>,
181    /// 数值上界(含)
182    pub max: Option<f64>,
183}
184
185/// 契约(schema):一组字段规格
186#[derive(Debug, Clone)]
187pub struct Contract {
188    pub name: String,
189    pub fields: BTreeMap<String, FieldSpec>,
190    /// 是否允许契约未声明的字段。
191    /// **默认 false(严格)**:额外字段一律报错,可及早发现拼写错误
192    /// (如 `prot` 误写为 `port`)。确需放宽时须**显式**写 `loose`。
193    pub allow_extra: bool,
194}
195
196/// 校验值是否符合类型规格。
197/// `contracts` 供 `ContractRef`(组合)递归查找被引用契约。
198fn check_type(
199    contract: &str,
200    field: &str,
201    spec: &FieldSpec,
202    v: &Value,
203    contracts: &BTreeMap<String, Contract>,
204) -> Result<(), String> {
205    // 组合:字段值是块,递归按被引用的契约校验(含填默认值)
206    if let TypeSpec::ContractRef(ref_name) = &spec.ty {
207        return match v {
208            Value::Object(_) => {
209                let mut sub = match v {
210                    Value::Object(m) => m.clone(),
211                    _ => unreachable!(),
212                };
213                let target = contracts.get(ref_name).ok_or_else(|| {
214                    format!(
215                        "sml: 字段 `{}` 引用了未定义的契约 `{}`(契约 `{}`)",
216                        field, ref_name, contract
217                    )
218                })?;
219                apply_contract(target, &mut sub, contracts)?;
220                Ok(())
221            }
222            _ => Err(format!(
223                "sml: 字段 `{}` 应为块并按契约 `{}` 校验,实际为 {}(契约 `{}`)",
224                field,
225                ref_name,
226                value_kind(v),
227                contract
228            )),
229        };
230    }
231
232    let ok = match (&spec.ty, v) {
233        (TypeSpec::Any, _) => true,
234        (TypeSpec::Str, Value::Str(_)) => true,
235        (TypeSpec::Int, Value::Int(_)) => true,
236        (TypeSpec::Num, Value::Int(_)) | (TypeSpec::Num, Value::Float(_)) => true,
237        (TypeSpec::Bool, Value::Bool(_)) => true,
238        (TypeSpec::Enum(vals), Value::Str(s)) => vals.iter().any(|x| x == s),
239        // 裸词数字会被 coerce 成 Int/Float,故枚举也接受被 coerce 成标量的情形
240        (TypeSpec::Enum(vals), Value::Int(i)) => vals.iter().any(|x| x == &i.to_string()),
241        (TypeSpec::Array(inner), Value::Array(items)) => items.iter().all(|it| {
242            check_type(
243                contract,
244                field,
245                &FieldSpec { ty: (**inner).clone(), required: true, default: None, min: None, max: None },
246                it,
247                contracts,
248            )
249            .is_ok()
250        }),
251        _ => false,
252    };
253    if !ok {
254        return Err(format!(
255            "sml: 字段 `{}` 类型应为 {},实际为 {}(契约 `{}`)",
256            field,
257            spec.ty.name(),
258            value_kind(v),
259            contract
260        ));
261    }
262    // 数值区间
263    if spec.min.is_some() || spec.max.is_some() {
264        let n = match v {
265            Value::Int(i) => Some(*i as f64),
266            Value::Float(f) => Some(*f),
267            _ => None,
268        };
269        if let Some(n) = n {
270            if let Some(lo) = spec.min {
271                if n < lo {
272                    return Err(format!(
273                        "sml: 字段 `{}` 值 {} 小于下界 {}(契约 `{}`)",
274                        field, n, lo, contract
275                    ));
276                }
277            }
278            if let Some(hi) = spec.max {
279                if n > hi {
280                    return Err(format!(
281                        "sml: 字段 `{}` 值 {} 大于上界 {}(契约 `{}`)",
282                        field, n, hi, contract
283                    ));
284                }
285            }
286        }
287    }
288    Ok(())
289}
290
291fn value_kind(v: &Value) -> &'static str {
292    match v {
293        Value::Null => "null",
294        Value::Bool(_) => "bool",
295        Value::Int(_) => "int",
296        Value::Float(_) => "float",
297        Value::Str(_) => "str",
298        Value::Array(_) => "array",
299        Value::Object(_) => "object",
300    }
301}
302
303/// 对块应用契约:填充默认值 + 校验 + 严格性检查。
304///
305/// **严格为默认**:契约未声明的字段会被拒绝,除非契约显式标记 `loose`。
306/// 这样拼错的字段名(如 `prot`)会立即报错,而不是被静默忽略。
307fn apply_contract(
308    c: &Contract,
309    node: &mut BTreeMap<String, Value>,
310    contracts: &BTreeMap<String, Contract>,
311) -> Result<(), String> {
312    // 1) 严格性:未声明字段一律拒绝(组合字段本身已在 fields 声明,其
313    //    内部字段由被引用契约在自己的 apply_contract 中负责校验)
314    if !c.allow_extra {
315        for k in node.keys() {
316            if !c.fields.contains_key(k) {
317                return Err(format!(
318                    "sml: 字段 `{}` 未在契约 `{}` 中声明(严格模式;如需允许额外字段请在契约名后写 `loose`)",
319                    k, c.name
320                ));
321            }
322        }
323    }
324    // 2) 逐字段:填默认值 + 类型/枚举/区间/组合校验
325    for (k, spec) in &c.fields {
326        match node.get(k) {
327            None => {
328                if let Some(d) = &spec.default {
329                    node.insert(k.clone(), d.clone());
330                } else if spec.required {
331                    return Err(format!(
332                        "sml: 字段 `{}` 必填但缺失(契约 `{}`)",
333                        k, c.name
334                    ));
335                }
336            }
337            Some(v) => {
338                // 组合会回填子块默认值,故需要可变副本
339                if matches!(spec.ty, TypeSpec::ContractRef(_)) {
340                    // 先按**原值**校验必须是块,否则会退化成
341                    // 「子字段缺失」这类误导性错误
342                    check_type(&c.name, k, spec, v, contracts)?;
343                    let mut sub = match v {
344                        Value::Object(m) => m.clone(),
345                        _ => unreachable!("check_type 已保证为块"),
346                    };
347                    check_type_contract_ref(&c.name, k, spec, &mut sub, contracts)?;
348                    node.insert(k.clone(), Value::Object(sub));
349                } else {
350                    check_type(&c.name, k, spec, v, contracts)?;
351                }
352            }
353        }
354    }
355    Ok(())
356}
357
358/// 对「组合字段」递归应用被引用契约(会回填子块默认值)
359fn check_type_contract_ref(
360    contract: &str,
361    field: &str,
362    spec: &FieldSpec,
363    sub: &mut BTreeMap<String, Value>,
364    contracts: &BTreeMap<String, Contract>,
365) -> Result<(), String> {
366    let ref_name = match &spec.ty {
367        TypeSpec::ContractRef(n) => n.clone(),
368        _ => return Ok(()),
369    };
370    let target = contracts.get(&ref_name).ok_or_else(|| {
371        format!(
372            "sml: 字段 `{}` 引用了未定义的契约 `{}`(契约 `{}`)",
373            field, ref_name, contract
374        )
375    })?;
376    // 先做基础类型校验(值须为块),再递归应用
377    check_type(contract, field, spec, &Value::Object(sub.clone()), contracts)?;
378    apply_contract(target, sub, contracts)
379}
380
381// ---------------------------------------------------------------------------
382// 解析: 词法 + 递归下降
383// ---------------------------------------------------------------------------
384
385#[derive(Debug, Clone, PartialEq)]
386enum Tok {
387    LBrace,  // {
388    RBrace,  // }
389    LBrack,  // [
390    RBrack,  // ]
391    Comma,   // ,
392    Colon,   // :
393    At,      // @
394    Str(String),   // 引号串 (已解码)
395    Word(String),  // 裸词
396}
397
398fn tokenize(text: &str) -> Result<Vec<Tok>, String> {
399    let mut toks = Vec::new();
400    let mut chars = text.chars().peekable();
401    let mut buf = String::new();
402    let mut flush = |buf: &mut String, toks: &mut Vec<Tok>| {
403        if !buf.is_empty() {
404            toks.push(Tok::Word(std::mem::take(buf)));
405        }
406    };
407    while let Some(c) = chars.next() {
408        match c {
409            '#' => {
410                // 单行注释到行尾
411                for c2 in chars.by_ref() {
412                    if c2 == '\n' {
413                        break;
414                    }
415                }
416            }
417            '-' => {
418                // `--` 单行注释到行尾;否则作为普通字符
419                if chars.peek() == Some(&'-') {
420                    chars.next(); // 吃掉第二个 -
421                    for c2 in chars.by_ref() {
422                        if c2 == '\n' {
423                            break;
424                        }
425                    }
426                } else {
427                    buf.push(c);
428                }
429            }
430            '/' => {
431                // `/*` 多行注释,直到 `*/`;否则作为普通字符
432                if chars.peek() == Some(&'*') {
433                    chars.next(); // 吃掉 *
434                    loop {
435                        match chars.next() {
436                            Some('*') => {
437                                if chars.peek() == Some(&'/') {
438                                    chars.next();
439                                    break;
440                                }
441                            }
442                            Some(_) => {}
443                            None => break,
444                        }
445                    }
446                } else {
447                    buf.push(c);
448                }
449            }
450            '_' => {
451                // `_*` 多行注释,直到 `*_`;否则作为普通字符
452                if chars.peek() == Some(&'*') {
453                    chars.next(); // 吃掉 *
454                    loop {
455                        match chars.next() {
456                            Some('*') => {
457                                if chars.peek() == Some(&'_') {
458                                    chars.next();
459                                    break;
460                                }
461                            }
462                            Some(_) => {}
463                            None => break,
464                        }
465                    }
466                } else {
467                    buf.push(c);
468                }
469            }
470            '"' => {
471                flush(&mut buf, &mut toks);
472                let mut s = String::new();
473                loop {
474                    match chars.next() {
475                        Some('"') => break,
476                        Some('\\') => {
477                            // 转义:\n \t \r \0 \" \\ \u{XXXX} \uXXXX
478                            match chars.next() {
479                                Some('n') => s.push('\n'),
480                                Some('t') => s.push('\t'),
481                                Some('r') => s.push('\r'),
482                                Some('0') => s.push('\0'),
483                                Some('"') => s.push('"'),
484                                Some('\\') => s.push('\\'),
485                                Some('u') => {
486                                    let mut hex = String::new();
487                                    // 支持 \u{XXXX} 或 \uXXXX
488                                    if chars.peek() == Some(&'{') {
489                                        chars.next();
490                                        for c2 in chars.by_ref() {
491                                            if c2 == '}' {
492                                                break;
493                                            }
494                                            hex.push(c2);
495                                        }
496                                    } else {
497                                        for _ in 0..4 {
498                                            if let Some(c2) = chars.next() {
499                                                hex.push(c2);
500                                            }
501                                        }
502                                    }
503                                    if let Ok(cp) = u32::from_str_radix(&hex, 16) {
504                                        if let Some(ch) = char::from_u32(cp) {
505                                            s.push(ch);
506                                        }
507                                    }
508                                }
509                                Some(other) => s.push(other),
510                                None => break,
511                            }
512                        }
513                        Some(other) => s.push(other),
514                        None => break,
515                    }
516                }
517                toks.push(Tok::Str(s));
518            }
519            '{' => {
520                flush(&mut buf, &mut toks);
521                toks.push(Tok::LBrace);
522            }
523            '}' => {
524                flush(&mut buf, &mut toks);
525                toks.push(Tok::RBrace);
526            }
527            '[' => {
528                flush(&mut buf, &mut toks);
529                toks.push(Tok::LBrack);
530            }
531            ']' => {
532                flush(&mut buf, &mut toks);
533                toks.push(Tok::RBrack);
534            }
535            ',' => {
536                flush(&mut buf, &mut toks);
537                toks.push(Tok::Comma);
538            }
539            ':' => {
540                flush(&mut buf, &mut toks);
541                toks.push(Tok::Colon);
542            }
543            '@' => {
544                // `@` 仅当位于**词首**时才是片段定义标记(`@base { ... }`)。
545                // 出现在词中间时(典型如邮箱 `a@b.c`)必须作为普通字符保留:
546                // 否则 `a@b.c` 会被切成 `Word("a")` + `At` + `Word("b.c")`,
547                // 后半段在解析时被丢弃,导致邮箱静默损坏为 `a`。
548                if buf.is_empty() {
549                    toks.push(Tok::At);
550                } else {
551                    buf.push(c);
552                }
553            }
554            ' ' | '\t' | '\n' | '\r' => {
555                flush(&mut buf, &mut toks);
556            }
557            _ => {
558                buf.push(c);
559            }
560        }
561    }
562    flush(&mut buf, &mut toks);
563    Ok(toks)
564}
565
566fn coerce_word(w: &str, fragments: &BTreeMap<String, Value>) -> Value {
567    match w {
568        "true" => return Value::Bool(true),
569        "false" => return Value::Bool(false),
570        "null" => return Value::Null,
571        _ => {}
572    }
573    // $env.VAR 内联
574    if let Some(ev) = w.strip_prefix("$env.") {
575        return Value::Str(std::env::var(ev).unwrap_or_default());
576    }
577    // 片段引用 &name
578    if let Some(name) = w.strip_prefix('&') {
579        if let Some(v) = fragments.get(name) {
580            return v.clone();
581        }
582        return Value::Str(w.to_string());
583    }
584    // 数字: int / float / 科学计数
585    if let Ok(i) = w.parse::<i64>() {
586        return Value::Int(i);
587    }
588    if let Ok(f) = w.parse::<f64>() {
589        return Value::Float(f);
590    }
591    Value::Str(w.to_string())
592}
593
594struct Parser {
595    toks: Vec<Tok>,
596    i: usize,
597    fragments: BTreeMap<String, Value>,
598    /// 契约表:名 -> 契约。由 `@contract Name { ... }` 填充
599    contracts: BTreeMap<String, Contract>,
600}
601
602impl Parser {
603    fn peek(&self) -> Option<&Tok> {
604        self.toks.get(self.i)
605    }
606    fn next(&mut self) -> Option<Tok> {
607        let t = self.toks.get(self.i).cloned();
608        if t.is_some() {
609            self.i += 1;
610        }
611        t
612    }
613
614    /// 解析契约体:逐条读 `field: <类型> [修饰符...]`
615    fn parse_contract_body(&mut self) -> Result<BTreeMap<String, FieldSpec>, String> {
616        let mut fields: BTreeMap<String, FieldSpec> = BTreeMap::new();
617        loop {
618            match self.peek().cloned() {
619                None | Some(Tok::RBrace) => {
620                    self.next();
621                    break;
622                }
623                Some(Tok::Comma) => {
624                    self.next();
625                }
626                _ => {
627                    let key = match self.next() {
628                        Some(Tok::Word(s)) | Some(Tok::Str(s)) => s,
629                        other => {
630                            return Err(format!("sml: 契约字段期望键, 得 {:?}", other))
631                        }
632                    };
633                    if self.peek() == Some(&Tok::Colon) {
634                        self.next();
635                    } else {
636                        return Err(format!("sml: 契约字段 `{}` 后须有冒号", key));
637                    }
638                    let spec = self.parse_field_spec()?;
639                    fields.insert(key, spec);
640                }
641            }
642        }
643        Ok(fields)
644    }
645
646    /// 解析单个字段的类型与修饰符
647    fn parse_field_spec(&mut self) -> Result<FieldSpec, String> {
648        let ty = match self.next() {
649            Some(Tok::Word(w)) => match w.as_str() {
650                "str" => TypeSpec::Str,
651                "int" => TypeSpec::Int,
652                "num" => TypeSpec::Num,
653                "bool" => TypeSpec::Bool,
654                "any" => TypeSpec::Any,
655                "enum" => {
656                    if self.peek() != Some(&Tok::LBrack) {
657                        return Err("sml: `enum` 后须为 [ ... ]".into());
658                    }
659                    self.next();
660                    let mut vals = Vec::new();
661                    loop {
662                        match self.peek().cloned() {
663                            None | Some(Tok::RBrack) => {
664                                self.next();
665                                break;
666                            }
667                            Some(Tok::Comma) => {
668                                self.next();
669                            }
670                            Some(Tok::Word(s)) | Some(Tok::Str(s)) => {
671                                vals.push(s);
672                                self.next();
673                            }
674                            _ => {
675                                self.next();
676                            }
677                        }
678                    }
679                    TypeSpec::Enum(vals)
680                }
681                // 非内置类型名 -> 视为**契约引用**(组合)。
682                // 这样「字段的类型是另一个契约」复用裸词表达,不引入新 token。
683                // 被引用的契约可在之后定义(校验发生在 @is 时,而非定义时)。
684                other => TypeSpec::ContractRef(other.to_string()),
685            },
686            Some(Tok::LBrack) => {
687                let inner = match self.next() {
688                    Some(Tok::Word(w)) => match w.as_str() {
689                        "str" => TypeSpec::Str,
690                        "int" => TypeSpec::Int,
691                        "num" => TypeSpec::Num,
692                        "bool" => TypeSpec::Bool,
693                        "any" => TypeSpec::Any,
694                        other => {
695                            return Err(format!("sml: 未知数组元素类型 `{}`", other))
696                        }
697                    },
698                    other => {
699                        return Err(format!("sml: 数组元素类型期望标识符, 得 {:?}", other))
700                    }
701                };
702                if self.peek() == Some(&Tok::RBrack) {
703                    self.next();
704                }
705                TypeSpec::Array(Box::new(inner))
706            }
707            other => return Err(format!("sml: 字段类型期望标识符, 得 {:?}", other)),
708        };
709
710        // 修饰符:required / optional / default <值> / min <数> / max <数>
711        let mut required = true;
712        let mut default = None;
713        let mut min = None;
714        let mut max = None;
715        loop {
716            // 若当前是 `标识符 :` 则视为下一个字段的开始,停止读修饰符
717            let is_next_field = matches!(self.peek(), Some(Tok::Word(_)))
718                && matches!(self.toks.get(self.i + 1), Some(Tok::Colon));
719            if is_next_field {
720                break;
721            }
722            match self.peek().cloned() {
723                Some(Tok::Word(w)) => match w.as_str() {
724                    "optional" => {
725                        required = false;
726                        self.next();
727                    }
728                    "required" => {
729                        required = true;
730                        self.next();
731                    }
732                    "default" => {
733                        self.next();
734                        default = Some(match self.next() {
735                            Some(Tok::Word(w2)) => coerce_word(&w2, &self.fragments),
736                            Some(Tok::Str(s)) => Value::Str(s),
737                            other => {
738                                return Err(format!("sml: default 期望值, 得 {:?}", other))
739                            }
740                        });
741                    }
742                    "min" => {
743                        self.next();
744                        min = Some(self.parse_spec_number()?);
745                    }
746                    "max" => {
747                        self.next();
748                        max = Some(self.parse_spec_number()?);
749                    }
750                    _ => break,
751                },
752                _ => break,
753            }
754        }
755        Ok(FieldSpec { ty, required, default, min, max })
756    }
757
758    fn parse_spec_number(&mut self) -> Result<f64, String> {
759        match self.next() {
760            Some(Tok::Word(w)) => {
761                w.parse::<f64>().map_err(|_| format!("sml: 期望数字, 得 `{}`", w))
762            }
763            other => Err(format!("sml: 期望数字, 得 {:?}", other)),
764        }
765    }
766
767    /// 解析对象/块, 直到遇到 closing (None=顶层)
768    fn parse_block(&mut self, closing: Option<Tok>) -> Result<Value, String> {
769        let mut node: BTreeMap<String, Value> = BTreeMap::new();
770        // 块内若声明了 `@is Name`,在块解析完成后应用契约
771        let mut applied_contract: Option<String> = None;
772        loop {
773            let tok = match self.peek().cloned() {
774                None => break,
775                Some(t) => t,
776            };
777            match tok {
778                Tok::RBrace | Tok::RBrack => {
779                    if let Some(cl) = &closing {
780                        if *cl == tok {
781                            self.next();
782                            break;
783                        }
784                    }
785                    // 顶层遇右括号也停
786                    break;
787                }
788                Tok::Comma => {
789                    self.next();
790                }
791                Tok::At => {
792                    // @name { ... } 片段定义 (不进主树)
793                    self.next();
794                    let fname = match self.next() {
795                        Some(Tok::Word(s)) | Some(Tok::Str(s)) => s,
796                        _ => return Err("sml: @ 后需片段名".into()),
797                    };
798                    if self.peek() == Some(&Tok::Colon) {
799                        self.next();
800                    }
801                    // —— 契约定义:`@contract Name { ... }` ——
802                    if fname == "contract" {
803                        let cname = match self.next() {
804                            Some(Tok::Word(s)) | Some(Tok::Str(s)) => s,
805                            other => {
806                                return Err(format!("sml: @contract 后须契约名, 得 {:?}", other))
807                            }
808                        };
809                        // 可选修饰符 `loose`:显式允许契约未声明的字段。
810                        // 严格是默认,放宽必须写出来(复用裸词,不引入新 token)。
811                        let mut allow_extra = false;
812                        if let Some(Tok::Word(w)) = self.peek().cloned() {
813                            if w == "loose" {
814                                allow_extra = true;
815                                self.next();
816                            }
817                        }
818                        if self.peek() != Some(&Tok::LBrace) {
819                            return Err(format!("sml: @contract {} 后须 {{ ... }}", cname));
820                        }
821                        self.next();
822                        let fields = self.parse_contract_body()?;
823                        self.contracts.insert(
824                            cname.clone(),
825                            Contract { name: cname, fields, allow_extra },
826                        );
827                        continue;
828                    }
829                    // —— 契约应用:`@is Name`(在当前块内)——
830                    if fname == "is" {
831                        let cname = match self.next() {
832                            Some(Tok::Word(s)) | Some(Tok::Str(s)) => s,
833                            other => {
834                                return Err(format!("sml: @is 后须契约名, 得 {:?}", other))
835                            }
836                        };
837                        applied_contract = Some(cname);
838                        continue;
839                    }
840                    // 可选 type [name] 参数
841                    let mut ftype: Option<String> = None;
842                    let mut farg: Option<String> = None;
843                    if let Some(Tok::Word(s)) = self.peek().cloned() {
844                        if *self.peek().unwrap() != Tok::LBrace {
845                            self.next();
846                            ftype = Some(s);
847                            if let Some(Tok::Word(s2)) = self.peek().cloned() {
848                                if *self.peek().unwrap() != Tok::LBrace {
849                                    self.next();
850                                    farg = Some(s2);
851                                }
852                            }
853                        }
854                    }
855                    if self.peek() == Some(&Tok::LBrace) {
856                        self.next();
857                        let mut sub = match self.parse_block(Some(Tok::RBrace))? {
858                            Value::Object(m) => m,
859                            other => {
860                                let mut m = BTreeMap::new();
861                                m.insert("_value".into(), other);
862                                m
863                            }
864                        };
865                        if let Some(t) = ftype {
866                            sub.insert("__type".into(), Value::Str(t));
867                        }
868                        if let Some(a) = farg {
869                            sub.insert("__name".into(), Value::Str(a));
870                        }
871                        self.fragments.insert(fname, Value::Object(sub));
872                    }
873                }
874                _ => {
875                    // key
876                    let key = match self.next() {
877                        Some(Tok::Word(s)) | Some(Tok::Str(s)) => s,
878                        other => return Err(format!("sml: 期望键, 得 {:?}", other)),
879                    };
880                    let colon = self.peek() == Some(&Tok::Colon);
881                    if colon {
882                        self.next();
883                    }
884                    let val = self.parse_value(&key, colon)?;
885                    // 同名冲突 -> 提升为数组
886                    if let Some(existing) = node.get_mut(&key) {
887                        match existing {
888                            Value::Array(a) => a.push(val),
889                            _ => {
890                                let old = node.remove(&key).unwrap();
891                                node.insert(key, Value::Array(vec![old, val]));
892                            }
893                        }
894                    } else {
895                        node.insert(key, val);
896                    }
897                }
898            }
899        }
900        // 块结束:若声明了 `@is`,应用契约(填默认值 + 校验 + 严格性检查)
901        if let Some(cname) = applied_contract {
902            let c = self
903                .contracts
904                .get(&cname)
905                .cloned()
906                .ok_or_else(|| format!("sml: 未定义的契约 `{}`", cname))?;
907            apply_contract(&c, &mut node, &self.contracts)?;
908        }
909        Ok(Value::Object(node))
910    }
911
912    /// 解析一个值 (在 key 之后)
913    fn parse_value(&mut self, key: &str, colon: bool) -> Result<Value, String> {
914        // 无冒号且后继是裸词: 可能是裸块 `type [name] { }`
915        if !colon && matches!(self.peek(), Some(Tok::Word(_))) {
916            // 预扫描: 收集参数直到 { / 结束; 若发现 { 则按裸块处理
917            let mut probe = self.i;
918            let mut found_block = false;
919            while probe < self.toks.len() {
920                match &self.toks[probe] {
921                    Tok::Word(_) | Tok::Str(_) => probe += 1,
922                    Tok::LBrace => {
923                        found_block = true;
924                        break;
925                    }
926                    _ => break,
927                }
928            }
929            if found_block {
930                // 裸块: key 为类型, 参数在 { 前
931                let mut args: Vec<Value> = Vec::new();
932                while let Some(t) = self.peek().cloned() {
933                    match t {
934                        Tok::Word(w) => {
935                            args.push(coerce_word(&w, &self.fragments));
936                            self.next();
937                        }
938                        Tok::Str(_) => {
939                            if let Some(Tok::Str(s)) = self.next() {
940                                args.push(Value::Str(s));
941                            }
942                        }
943                        _ => break,
944                    }
945                }
946                if self.peek() == Some(&Tok::LBrace) {
947                    self.next();
948                    let mut sub = self.parse_block(Some(Tok::RBrace))?;
949                    if let Value::Object(m) = &mut sub {
950                        m.insert("__type".into(), Value::Str(key.to_string()));
951                        if args.len() == 1 {
952                            m.insert("__name".into(), args.remove(0));
953                        }
954                    }
955                    return Ok(sub);
956                }
957            }
958        }
959        match self.peek().cloned() {
960            Some(Tok::LBrace) => {
961                self.next();
962                self.parse_block(Some(Tok::RBrace))
963            }
964            Some(Tok::LBrack) => {
965                self.next();
966                self.parse_array()
967            }
968            Some(tok @ (Tok::Word(_) | Tok::Str(_))) => {
969                let v = match tok {
970                    Tok::Word(w) => coerce_word(&w, &self.fragments),
971                    Tok::Str(s) => {
972                        let ev = s.strip_prefix("$env.");
973                        match ev {
974                            Some(name) => Value::Str(std::env::var(name).unwrap_or_default()),
975                            None => Value::Str(s),
976                        }
977                    }
978                    _ => unreachable!(),
979                };
980                self.next();
981                Ok(v)
982            }
983            // 键后无值: `key }` / `key ]` / `key ,` / 行尾 —— key 本身即值 (片段引用/裸词)
984            Some(Tok::RBrace) | Some(Tok::RBrack) | Some(Tok::Comma) | None => {
985                if colon {
986                    // 有冒号但无值: 空值
987                    Ok(Value::Null)
988                } else {
989                    Ok(coerce_word(key, &self.fragments))
990                }
991            }
992            _ => Err("sml: 语法错误".into()),
993        }
994    }
995
996    fn parse_array(&mut self) -> Result<Value, String> {
997        let mut arr = Vec::new();
998        loop {
999            match self.peek().cloned() {
1000                None => break,
1001                Some(Tok::RBrack) => {
1002                    self.next();
1003                    break;
1004                }
1005                Some(Tok::Comma) => {
1006                    self.next();
1007                }
1008                Some(Tok::LBrace) => {
1009                    self.next();
1010                    arr.push(self.parse_block(Some(Tok::RBrace))?);
1011                }
1012                Some(Tok::Word(w)) => {
1013                    arr.push(coerce_word(&w, &self.fragments));
1014                    self.next();
1015                }
1016                Some(Tok::Str(_)) => {
1017                    if let Some(Tok::Str(s)) = self.next() {
1018                        arr.push(Value::Str(s));
1019                    }
1020                }
1021                _ => break,
1022            }
1023        }
1024        Ok(Value::Array(arr))
1025    }
1026}
1027
1028/// SML 语法版本
1029///
1030/// SML 源于 eclog,演进中通过 `@version` 声明文档遵循的语法版本,
1031/// 使解析器能在将来引入 v2 不兼容语法时仍正确读取旧文档。
1032#[derive(Debug, Clone, Copy, PartialEq, Eq)]
1033pub enum Version {
1034    /// v1:初始公开版本
1035    V1,
1036}
1037
1038impl Version {
1039    /// 当前实现支持的最新版本
1040    pub const CURRENT: Version = Version::V1;
1041
1042    /// 解析版本字面量(`v1` / `1`)
1043    fn from_word(w: &str) -> Option<Version> {
1044        match w {
1045            "v1" | "1" => Some(Version::V1),
1046            _ => None,
1047        }
1048    }
1049
1050    /// 版本名(用于错误信息与序列化回显)
1051    pub fn name(self) -> &'static str {
1052        match self {
1053            Version::V1 => "v1",
1054        }
1055    }
1056}
1057
1058impl fmt::Display for Version {
1059    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1060        f.write_str(self.name())
1061    }
1062}
1063
1064/// 若该行是 `@version` 声明,返回版本字面量;否则返回 None。
1065///
1066/// `version` 是保留字:不允许作为片段名(`@version { }`)使用。
1067fn version_directive(line: &str) -> Result<Option<String>, String> {
1068    let content = strip_line_comment(line).trim();
1069    // 词法失败的行(如未闭合引号)不是版本声明,交由主解析器报更准确的错
1070    let toks = match tokenize(content) {
1071        Ok(t) => t,
1072        Err(_) => return Ok(None),
1073    };
1074    match toks.as_slice() {
1075        [Tok::At, Tok::Word(w), Tok::Word(v)] if w == "version" => Ok(Some(v.clone())),
1076        [Tok::At, Tok::Word(w), Tok::Str(v)] if w == "version" => Ok(Some(v.clone())),
1077        [Tok::At, Tok::Word(w), ..] if w == "version" => Err(
1078            "`@version` 是版本声明指令,须写作 `@version v1`;`version` 不可作为片段名".into(),
1079        ),
1080        _ => Ok(None),
1081    }
1082}
1083
1084/// 剥离 `@version` 声明行,返回剩余文本与声明的版本(未声明则为 None)。
1085///
1086/// 允许多次声明(include 进来的文件可各自声明),但必须一致;
1087/// 声明了实现不支持的版本时报错,避免静默按错误语法解析。
1088fn strip_version(text: &str) -> Result<(String, Option<Version>), String> {
1089    let mut declared: Option<Version> = None;
1090    let mut rest = String::new();
1091    for line in text.lines() {
1092        if let Some(lit) = version_directive(line)? {
1093            let v = Version::from_word(&lit).ok_or_else(|| {
1094                format!(
1095                    "不支持的 SML 版本 `{lit}`(本实现支持 {})",
1096                    Version::CURRENT.name()
1097                )
1098            })?;
1099            match declared {
1100                None => declared = Some(v),
1101                Some(prev) if prev != v => {
1102                    return Err(format!("@version 冲突:{} 与 {}", prev.name(), v.name()))
1103                }
1104                Some(_) => {}
1105            }
1106            continue;
1107        }
1108        rest.push_str(line);
1109        rest.push('\n');
1110    }
1111    Ok((rest, declared))
1112}
1113
1114/// 解析 SML 文本,并返回其声明的语法版本。
1115///
1116/// 未声明版本时按 `Version::CURRENT`(v1)处理,**既有文档不受影响**。
1117pub fn parse_versioned(text: &str) -> Result<(Value, Version), String> {
1118    let (rest, declared) = strip_version(text)?;
1119    Ok((parse_impl(&rest)?, declared.unwrap_or(Version::CURRENT)))
1120}
1121
1122/// 解析 SML 文件:展开 include,并返回其声明的语法版本
1123pub fn parse_file_versioned(path: impl AsRef<Path>) -> Result<(Value, Version), String> {
1124    let path = path.as_ref();
1125    let text =
1126        std::fs::read_to_string(path).map_err(|e| format!("读取失败 {}: {e}", path.display()))?;
1127    let base = path
1128        .parent()
1129        .map(|p| p.to_path_buf())
1130        .unwrap_or_else(|| PathBuf::from("."));
1131    let expanded = resolve_includes(&text, &base)?;
1132    parse_versioned(&expanded)
1133}
1134
1135/// 解析 SML 文本
1136///
1137/// 会自动识别并剥离 `@version` 声明(需要版本信息时用 [`parse_versioned`])。
1138pub fn parse(text: &str) -> Result<Value, String> {
1139    let (rest, _) = strip_version(text)?;
1140    parse_impl(&rest)
1141}
1142
1143/// 不含版本处理的底层解析
1144fn parse_impl(text: &str) -> Result<Value, String> {
1145    let toks = tokenize(text)?;
1146    let mut p = Parser {
1147        toks,
1148        i: 0,
1149        fragments: BTreeMap::new(),
1150        contracts: BTreeMap::new(),
1151    };
1152    // 顶层支持三种形态,与 `to_sml` 的输出对称:
1153    //   - `[ ... ]` 数组:to_sml 对非对象走 dump_inline,会输出顶层数组
1154    //     (如「历史记录」这类对象数组)。此前 parse 只认键值块,导致
1155    //     能序列化却读不回("期望键, 得 LBrack"),是不对称缺陷。
1156    //   - `{ ... }` 顶层对象块
1157    //   - 键值块(传统形态)
1158    // 注:顶层**标量**仍不可往返(SML 顶层需为容器),这是格式固有限制。
1159    match p.peek() {
1160        Some(Tok::LBrack) => {
1161            p.next();
1162            p.parse_array()
1163        }
1164        Some(Tok::LBrace) => {
1165            p.next();
1166            p.parse_block(Some(Tok::RBrace))
1167        }
1168        _ => p.parse_block(None),
1169    }
1170}
1171
1172// ---------------------------------------------------------------------------
1173// include 指令:把外部 .sml 文件内联进来
1174//
1175// 语法:`include "path.sml"` 或 `@include "path.sml"`(两种等价)
1176// 语义:**文本内联**(类似 C 的 #include),而非对象合并。
1177//   这样 include 可以出现在块内部引入一组字段,例如:
1178//       server web { &base include "common/port.sml" }
1179//   若做成对象合并就无法表达「注入若干字段到当前块」。
1180//
1181// 相对路径按**被包含文件自身所在目录**解析(与 C 预处理器一致),
1182// 而非进程工作目录,因此嵌套 include 时路径行为可预期。
1183// ---------------------------------------------------------------------------
1184
1185/// 嵌套深度上限:既防栈溢出,也让异常深层的引用尽早失败
1186const MAX_INCLUDE_DEPTH: usize = 32;
1187
1188/// 剥离行尾注释,正确跳过引号内的 `#`(如 `key: "a#b"` 中的 # 不是注释起点)
1189fn strip_line_comment(line: &str) -> &str {
1190    let bytes = line.as_bytes();
1191    let mut i = 0;
1192    let mut in_quote = false;
1193    while i < bytes.len() {
1194        match bytes[i] {
1195            b'"' => in_quote = !in_quote,
1196            // 引号内的反斜杠会转义下一个字符,需整体跳过
1197            b'\\' if in_quote => i += 1,
1198            b'#' if !in_quote => return &line[..i],
1199            _ => {}
1200        }
1201        i += 1;
1202    }
1203    line
1204}
1205
1206/// 若该行是 include 指令,返回目标路径;否则返回 None
1207fn include_target(line: &str) -> Option<String> {
1208    let content = strip_line_comment(line).trim();
1209    let content = content.strip_prefix('@').unwrap_or(content).trim_start();
1210    // 复用词法器处理路径,使含空格的路径(引号串)能被正确识别
1211    let toks = tokenize(content).ok()?;
1212    match toks.as_slice() {
1213        [Tok::Word(w), Tok::Str(p)] if w == "include" => Some(p.clone()),
1214        [Tok::Word(w), Tok::Word(p)] if w == "include" => Some(p.clone()),
1215        _ => None,
1216    }
1217}
1218
1219/// 把 text 中的 include 指令递归展开为不含指令的纯 SML 文本。
1220///
1221/// `base` 为相对路径的解析基准目录(通常是当前文件所在目录)。
1222/// 循环引用与缺失文件都会返回错误,不会静默跳过。
1223pub fn resolve_includes(text: &str, base: &Path) -> Result<String, String> {
1224    let mut out = String::new();
1225    let mut stack: Vec<PathBuf> = Vec::new();
1226    expand_includes(text, base, &mut out, &mut stack)?;
1227    Ok(out)
1228}
1229
1230fn expand_includes(
1231    text: &str,
1232    base: &Path,
1233    out: &mut String,
1234    stack: &mut Vec<PathBuf>,
1235) -> Result<(), String> {
1236    if stack.len() >= MAX_INCLUDE_DEPTH {
1237        return Err(format!("include 嵌套超过 {MAX_INCLUDE_DEPTH} 层"));
1238    }
1239    for line in text.lines() {
1240        match include_target(line) {
1241            Some(rel) => {
1242                let path = base.join(&rel);
1243                let canon = path
1244                    .canonicalize()
1245                    .map_err(|e| format!("include 无法定位 {}: {e}", path.display()))?;
1246                // stack 是「当前正在展开的文件链」,命中即成环
1247                if stack.iter().any(|p| p == &canon) {
1248                    return Err(format!("include 循环引用: {}", canon.display()));
1249                }
1250                let content = std::fs::read_to_string(&canon)
1251                    .map_err(|e| format!("include 读取失败 {}: {e}", canon.display()))?;
1252                let child_base = canon
1253                    .parent()
1254                    .map(|p| p.to_path_buf())
1255                    .unwrap_or_else(|| PathBuf::from("."));
1256                stack.push(canon);
1257                expand_includes(&content, &child_base, out, stack)?;
1258                stack.pop();
1259            }
1260            None => {
1261                out.push_str(line);
1262                out.push('\n');
1263            }
1264        }
1265    }
1266    Ok(())
1267}
1268
1269/// 解析 SML 文件,并展开其中的 include 指令。
1270///
1271/// 相对路径以**该文件所在目录**为基准。
1272pub fn parse_file(path: impl AsRef<Path>) -> Result<Value, String> {
1273    let path = path.as_ref();
1274    let text = std::fs::read_to_string(path)
1275        .map_err(|e| format!("读取失败 {}: {e}", path.display()))?;
1276    let base = path
1277        .parent()
1278        .map(|p| p.to_path_buf())
1279        .unwrap_or_else(|| PathBuf::from("."));
1280    let expanded = resolve_includes(&text, &base)?;
1281    parse(&expanded)
1282}
1283
1284/// 解析到对象 (失败抛 `ParseError`)
1285pub fn loads(text: &str) -> Result<Value, ParseError> {
1286    parse(text).map_err(ParseError)
1287}
1288
1289#[derive(Debug)]
1290pub struct ParseError(pub String);
1291
1292impl fmt::Display for ParseError {
1293    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1294        write!(f, "sml parse error: {}", self.0)
1295    }
1296}
1297
1298impl std::error::Error for ParseError {}
1299
1300// ---------------------------------------------------------------------------
1301// 序列化
1302// ---------------------------------------------------------------------------
1303
1304fn quote_if_needed(s: &str) -> String {
1305    if s.is_empty() || s.contains([' ', '\t', '\n', '\r', ':', '#', '{', '}']) {
1306        format!("\"{}\"", s.replace('\\', "\\\\").replace('"', "\\\""))
1307    } else {
1308        s.to_string()
1309    }
1310}
1311
1312/// 输出一个块。含 `__type` / `__name` 的块也按普通块原样输出所有键,
1313/// 保证元数据(枚举带数据变体的 `__type` 标记等)可完整往返。
1314/// SML 的裸块 `type [name] { ... }` 解析后正是 `__type` / `__name` 键。
1315fn dump_block(m: &BTreeMap<String, Value>, indent: usize, out: &mut String) {
1316    if m.is_empty() {
1317        out.push_str("{}");
1318        return;
1319    }
1320    out.push_str(&format!("\n{}{{", "  ".repeat(indent)));
1321    for (k, val) in m {
1322        out.push_str(&format!("\n{}{}: ", "  ".repeat(indent + 1), k));
1323        dump_value(val, indent + 1, out);
1324    }
1325    out.push_str(&format!("\n{}}}", "  ".repeat(indent)));
1326}
1327
1328fn dump_value(v: &Value, indent: usize, out: &mut String) {
1329    let pad = "  ".repeat(indent);
1330    match v {
1331        Value::Null => out.push_str("null"),
1332        Value::Bool(b) => out.push_str(if *b { "true" } else { "false" }),
1333        Value::Int(i) => out.push_str(&i.to_string()),
1334        Value::Float(f) => out.push_str(&format!("{}", f)),
1335        Value::Str(s) => out.push_str(&quote_if_needed(s)),
1336        Value::Array(a) => {
1337            if a.is_empty() {
1338                out.push_str("[]");
1339            } else {
1340                out.push('[');
1341                for e in a {
1342                    out.push('\n');
1343                    out.push_str(&format!("{}{}", "  ".repeat(indent + 1), dump_inline(e)));
1344                }
1345                out.push_str(&format!("\n{}]", pad));
1346            }
1347        }
1348        Value::Object(m) => dump_block(m, indent, out),
1349    }
1350}
1351
1352fn dump_scalar(v: &Value) -> String {
1353    match v {
1354        Value::Null => "null".into(),
1355        Value::Bool(b) => b.to_string(),
1356        Value::Int(i) => i.to_string(),
1357        Value::Float(f) => f.to_string(),
1358        Value::Str(s) => quote_if_needed(s),
1359        _ => "".into(),
1360    }
1361}
1362
1363fn dump_inline(v: &Value) -> String {
1364    match v {
1365        Value::Object(m) => {
1366            // 含 __type/__name 的块原样输出所有键,保证元数据可往返
1367            let parts: Vec<String> = m
1368                .iter()
1369                .map(|(k, val)| format!("{}: {}", k, dump_inline(val)))
1370                .collect();
1371            format!("{{ {} }}", parts.join(", "))
1372        }
1373        Value::Array(a) => {
1374            let parts: Vec<String> = a.iter().map(dump_inline).collect();
1375            format!("[ {} ]", parts.join(", "))
1376        }
1377        other => dump_scalar(other),
1378    }
1379}
1380
1381/// 序列化回 SML 文本 (round-trip)
1382///
1383/// 含 `__type` / `__name` 的块(如枚举带数据变体序列化的结果)
1384/// 会原样输出所有键,保证元数据可完整往返。
1385pub fn to_sml(v: &Value) -> String {
1386    let mut out = String::new();
1387    if let Value::Object(m) = v {
1388        if m.contains_key("__type") {
1389            dump_block(m, 0, &mut out);
1390        } else {
1391            for (k, val) in m {
1392                out.push_str(&format!("{}: ", k));
1393                dump_value(val, 0, &mut out);
1394                out.push('\n');
1395            }
1396        }
1397    } else {
1398        out.push_str(&dump_inline(v));
1399    }
1400    out
1401}
1402
1403// ---------------------------------------------------------------------------
1404// C-ABI (cdylib, 供 C / 其它语言调用)
1405// ---------------------------------------------------------------------------
1406
1407use std::os::raw::{c_char, c_int};
1408use std::ptr;
1409
1410fn cstr(s: &str) -> *mut c_char {
1411    let c = std::ffi::CString::new(s).unwrap_or_default();
1412    c.into_raw()
1413}
1414
1415/// sml_parse(text) -> 返回 JSON 字符串 (调用方 sml_free 释放); 失败返回 NULL
1416#[unsafe(no_mangle)]
1417pub extern "C" fn sml_parse(text: *const c_char) -> *mut c_char {
1418    if text.is_null() {
1419        return ptr::null_mut();
1420    }
1421    let t = unsafe { std::ffi::CStr::from_ptr(text) }.to_string_lossy().into_owned();
1422    match parse(&t) {
1423        Ok(v) => cstr(&jsonify(&v)),
1424        Err(_) => ptr::null_mut(),
1425    }
1426}
1427
1428/// sml_dump(json) -> 接受 JSON 字符串, 序列化为 SML; 调用方 sml_free
1429#[unsafe(no_mangle)]
1430pub extern "C" fn sml_dump(json: *const c_char) -> *mut c_char {
1431    if json.is_null() {
1432        return ptr::null_mut();
1433    }
1434    let j = unsafe { std::ffi::CStr::from_ptr(json) }.to_string_lossy().into_owned();
1435    match json_to_value(&j) {
1436        Some(v) => cstr(&to_sml(&v)),
1437        None => ptr::null_mut(),
1438    }
1439}
1440
1441/// sml_free(p): 释放由 sml_parse / sml_dump 返回的字符串
1442#[unsafe(no_mangle)]
1443pub unsafe extern "C" fn sml_free(p: *mut c_char) {
1444    if !p.is_null() {
1445        drop(unsafe { std::ffi::CString::from_raw(p) });
1446    }
1447}
1448
1449/// sml_version() -> 版本字符串 (调用方 sml_free)
1450#[unsafe(no_mangle)]
1451pub extern "C" fn sml_version() -> *mut c_char {
1452    cstr(concat!("sml ", env!("CARGO_PKG_VERSION")))
1453}
1454
1455// ---------------------------------------------------------------------------
1456// 内部: JSON <-> Value (供 C-ABI 便捷桥)
1457// ---------------------------------------------------------------------------
1458
1459fn jsonify(v: &Value) -> String {
1460    fn esc(s: &str) -> String {
1461        s.replace('\\', "\\\\").replace('"', "\\\"")
1462    }
1463    match v {
1464        Value::Null => "null".into(),
1465        Value::Bool(b) => b.to_string(),
1466        Value::Int(i) => i.to_string(),
1467        Value::Float(f) => f.to_string(),
1468        Value::Str(s) => format!("\"{}\"", esc(s)),
1469        Value::Array(a) => {
1470            let parts: Vec<String> = a.iter().map(jsonify).collect();
1471            format!("[{}]", parts.join(","))
1472        }
1473        Value::Object(m) => {
1474            let parts: Vec<String> = m
1475                .iter()
1476                .map(|(k, val)| format!("\"{}\":{}", esc(k), jsonify(val)))
1477                .collect();
1478            format!("{{{}}}", parts.join(","))
1479        }
1480    }
1481}
1482
1483fn json_to_value(s: &str) -> Option<Value> {
1484    let bytes = s.as_bytes();
1485    let mut i = 0;
1486    let _n = bytes.len();
1487    let mut skip_ws = |b: &[u8], i: &mut usize| {
1488        while *i < b.len() && matches!(b[*i], b' ' | b'\t' | b'\n' | b'\r') {
1489            *i += 1;
1490        }
1491    };
1492    let mut parse_str = |b: &[u8], i: &mut usize| -> Option<String> {
1493        skip_ws(b, i);
1494        if *i >= b.len() || b[*i] != b'"' {
1495            return None;
1496        }
1497        *i += 1;
1498        let mut out = String::new();
1499        while *i < b.len() {
1500            let c = b[*i];
1501            if c == b'"' {
1502                *i += 1;
1503                return Some(out);
1504            }
1505            if c == b'\\' && *i + 1 < b.len() {
1506                *i += 1;
1507                let e = b[*i];
1508                out.push(match e {
1509                    b'n' => '\n',
1510                    b't' => '\t',
1511                    b'r' => '\r',
1512                    b'"' => '"',
1513                    b'\\' => '\\',
1514                    _ => e as char,
1515                });
1516            } else {
1517                out.push(c as char);
1518            }
1519            *i += 1;
1520        }
1521        None
1522    };
1523    fn parse_val_impl(
1524        b: &[u8],
1525        i: &mut usize,
1526        s: &str,
1527        parse_str: &dyn Fn(&[u8], &mut usize) -> Option<String>,
1528    ) -> Option<Value> {
1529        let mut skip_ws = |b: &[u8], i: &mut usize| {
1530            while *i < b.len() && matches!(b[*i], b' ' | b'\t' | b'\n' | b'\r') {
1531                *i += 1;
1532            }
1533        };
1534        skip_ws(b, i);
1535        if *i >= b.len() {
1536            return None;
1537        }
1538        match b[*i] {
1539            b'{' => {
1540                *i += 1;
1541                let mut m = BTreeMap::new();
1542                skip_ws(b, i);
1543                if *i < b.len() && b[*i] == b'}' {
1544                    *i += 1;
1545                    return Some(Value::Object(m));
1546                }
1547                loop {
1548                    skip_ws(b, i);
1549                    let k = parse_str(b, i)?;
1550                    skip_ws(b, i);
1551                    if *i < b.len() && b[*i] == b':' {
1552                        *i += 1;
1553                    }
1554                    let v = parse_val_impl(b, i, s, parse_str)?;
1555                    m.insert(k, v);
1556                    skip_ws(b, i);
1557                    if *i < b.len() && b[*i] == b',' {
1558                        *i += 1;
1559                    } else if *i < b.len() && b[*i] == b'}' {
1560                        *i += 1;
1561                        break;
1562                    }
1563                }
1564                Some(Value::Object(m))
1565            }
1566            b'[' => {
1567                *i += 1;
1568                let mut a = Vec::new();
1569                skip_ws(b, i);
1570                if *i < b.len() && b[*i] == b']' {
1571                    *i += 1;
1572                    return Some(Value::Array(a));
1573                }
1574                loop {
1575                    a.push(parse_val_impl(b, i, s, parse_str)?);
1576                    skip_ws(b, i);
1577                    if *i < b.len() && b[*i] == b',' {
1578                        *i += 1;
1579                    } else if *i < b.len() && b[*i] == b']' {
1580                        *i += 1;
1581                        break;
1582                    }
1583                }
1584                Some(Value::Array(a))
1585            }
1586            b'"' => parse_str(b, i).map(Value::Str),
1587            b't' => {
1588                if s[*i..].starts_with("true") {
1589                    *i += 4;
1590                    Some(Value::Bool(true))
1591                } else {
1592                    None
1593                }
1594            }
1595            b'f' => {
1596                if s[*i..].starts_with("false") {
1597                    *i += 5;
1598                    Some(Value::Bool(false))
1599                } else {
1600                    None
1601                }
1602            }
1603            b'n' => {
1604                if s[*i..].starts_with("null") {
1605                    *i += 4;
1606                    Some(Value::Null)
1607                } else {
1608                    None
1609                }
1610            }
1611            _ => {
1612                let start = *i;
1613                while *i < b.len()
1614                    && (b[*i].is_ascii_digit()
1615                        || matches!(b[*i], b'-' | b'+' | b'.' | b'e' | b'E'))
1616                {
1617                    *i += 1;
1618                }
1619                let tok = s[start..*i].to_string();
1620                if let Ok(iv) = tok.parse::<i64>() {
1621                    Some(Value::Int(iv))
1622                } else if let Ok(fv) = tok.parse::<f64>() {
1623                    Some(Value::Float(fv))
1624                } else {
1625                    None
1626                }
1627            }
1628        }
1629    }
1630    parse_val_impl(bytes, &mut i, s, &parse_str)
1631}
1632
1633// ---------------------------------------------------------------------------
1634// serde 支持(可选 feature:`serde`)
1635//
1636// 1) `Value` 实现 `Serialize`/`Deserialize`(手写而非 `#[derive]`:derive 会把
1637//    枚举表示为外部标签形式 Value::Int(5) -> {"Int":5},而配置场景要自然形状
1638//    5)。手写后 SML 的 Value 与 JSON/TOML/YAML 数据形状一致,可经任意 serde
1639//    后端进出。
1640// 2) `sml::serde::{from_str, from_value, to_value, to_string}`:serde 桥。
1641//    任何 `#[derive(serde::Serialize / Deserialize)]` 类型都能像 toml-rs 一样
1642//    一键从 SML 文本反序列化 / 序列化为 SML(枚举沿用 `__type` 约定)。
1643//
1644// 不启用该 feature 时 crate 保持零依赖。
1645// ---------------------------------------------------------------------------
1646
1647#[cfg(feature = "serde")]
1648pub mod serde {
1649    use super::Value;
1650    use ::serde::de::{self, MapAccess, SeqAccess, Visitor};
1651    use ::serde::ser::{
1652        SerializeMap, SerializeSeq, SerializeStruct, SerializeStructVariant,
1653        SerializeTuple, SerializeTupleStruct, SerializeTupleVariant,
1654    };
1655    use ::serde::{Deserialize, Deserializer, Serialize, Serializer};
1656    use ::std::collections::BTreeMap;
1657    use ::std::fmt;
1658
1659    /// serde 错误类型(自定义消息,实现 ser/de 两个 Error trait)
1660    type Error = ::serde::de::value::Error;
1661
1662    fn type_err(v: &Value, expected: &str) -> Error {
1663        de::Error::custom(format!(
1664            "期望 {expected},实际为 {}",
1665            super::__private::describe_value(v)
1666        ))
1667    }
1668
1669    impl Serialize for Value {
1670        fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
1671        where
1672            S: Serializer,
1673        {
1674            match self {
1675                Value::Null => serializer.serialize_unit(),
1676                Value::Bool(b) => serializer.serialize_bool(*b),
1677                Value::Int(i) => serializer.serialize_i64(*i),
1678                Value::Float(f) => serializer.serialize_f64(*f),
1679                Value::Str(s) => serializer.serialize_str(s),
1680                // Vec<Value> / 逐项委托,递归依赖 Value 自身的 impl
1681                Value::Array(a) => a.serialize(serializer),
1682                Value::Object(m) => {
1683                    let mut map = serializer.serialize_map(Some(m.len()))?;
1684                    for (k, v) in m {
1685                        map.serialize_entry(k, v)?;
1686                    }
1687                    map.end()
1688                }
1689            }
1690        }
1691    }
1692
1693    impl<'de> Deserialize<'de> for Value {
1694        fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
1695        where
1696            D: Deserializer<'de>,
1697        {
1698            // 交给格式自行判断类型(JSON 的数字/字符串/数组/对象都能落到对应变体)
1699            deserializer.deserialize_any(ValueVisitor)
1700        }
1701    }
1702
1703    struct ValueVisitor;
1704
1705    impl<'de> Visitor<'de> for ValueVisitor {
1706        type Value = Value;
1707
1708        fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
1709            f.write_str("any valid SML/JSON value")
1710        }
1711
1712        fn visit_unit<E: de::Error>(self) -> Result<Value, E> {
1713            Ok(Value::Null)
1714        }
1715        fn visit_none<E: de::Error>(self) -> Result<Value, E> {
1716            Ok(Value::Null)
1717        }
1718        fn visit_some<D>(self, d: D) -> Result<Value, D::Error>
1719        where
1720            D: Deserializer<'de>,
1721        {
1722            Deserialize::deserialize(d)
1723        }
1724        fn visit_bool<E: de::Error>(self, v: bool) -> Result<Value, E> {
1725            Ok(Value::Bool(v))
1726        }
1727        fn visit_i64<E: de::Error>(self, v: i64) -> Result<Value, E> {
1728            Ok(Value::Int(v))
1729        }
1730        // 超出 i64 的大整数退化为 Float,避免直接报错丢失数据
1731        fn visit_u64<E: de::Error>(self, v: u64) -> Result<Value, E> {
1732            Ok(i64::try_from(v)
1733                .map(Value::Int)
1734                .unwrap_or_else(|_| Value::Float(v as f64)))
1735        }
1736        fn visit_f64<E: de::Error>(self, v: f64) -> Result<Value, E> {
1737            Ok(Value::Float(v))
1738        }
1739        fn visit_str<E: de::Error>(self, v: &str) -> Result<Value, E> {
1740            Ok(Value::Str(v.to_string()))
1741        }
1742        fn visit_string<E: de::Error>(self, v: String) -> Result<Value, E> {
1743            Ok(Value::Str(v))
1744        }
1745        fn visit_seq<A>(self, mut seq: A) -> Result<Value, A::Error>
1746        where
1747            A: SeqAccess<'de>,
1748        {
1749            let mut v = Vec::new();
1750            while let Some(x) = seq.next_element()? {
1751                v.push(x);
1752            }
1753            Ok(Value::Array(v))
1754        }
1755        fn visit_map<A>(self, mut map: A) -> Result<Value, A::Error>
1756        where
1757            A: MapAccess<'de>,
1758        {
1759            let mut m = BTreeMap::new();
1760            while let Some((k, v)) = map.next_entry::<String, Value>()? {
1761                m.insert(k, v);
1762            }
1763            Ok(Value::Object(m))
1764        }
1765    }
1766
1767    // -----------------------------------------------------------------------
1768    // serde 桥:任意 `serde::Serialize / Deserialize` 类型 <-> SML
1769    // -----------------------------------------------------------------------
1770
1771    /// 解析 SML 文本并一键反序列化到任意 serde 类型(等价于 `toml::from_str`)。
1772    ///
1773    /// ```rust
1774    /// # use serde::Deserialize;
1775    /// # #[derive(Deserialize, Debug)]
1776    /// # struct Server { host: String, port: i32 }
1777    /// let s: Server = sml::serde::from_str("host: web.example\nport: 8080\n").unwrap();
1778    /// assert_eq!(s.host, "web.example");
1779    /// ```
1780    pub fn from_str<T: de::DeserializeOwned>(text: &str) -> Result<T, String> {
1781        let value = crate::parse(text)?;
1782        from_value(value)
1783    }
1784
1785    /// 从任意 [`Value`] 反序列化到任意 serde 类型。
1786    pub fn from_value<T: de::DeserializeOwned>(value: Value) -> Result<T, String> {
1787        T::deserialize(ValueDeserializer(value)).map_err(|e| e.to_string())
1788    }
1789
1790    /// 任意 serde 类型序列化为 [`Value`](等价于 `serde_json::to_value`)。
1791    pub fn to_value<T: Serialize + ?Sized>(value: &T) -> Result<Value, String> {
1792        value.serialize(ValueSerializer).map_err(|e| e.to_string())
1793    }
1794
1795    /// 任意 serde 类型序列化为 SML 文本(等价于 `toml::to_string`)。
1796    pub fn to_string<T: Serialize + ?Sized>(value: &T) -> Result<String, String> {
1797        Ok(crate::to_sml(&to_value(value)?))
1798    }
1799
1800    // ---- Serializer: T: Serialize -> Value ----
1801
1802    struct ValueSerializer;
1803
1804    impl Serializer for ValueSerializer {
1805        type Ok = Value;
1806        type Error = Error;
1807        type SerializeSeq = SeqSerializer;
1808        type SerializeTuple = SeqSerializer;
1809        type SerializeTupleStruct = SeqSerializer;
1810        type SerializeTupleVariant = TupleVariantSerializer;
1811        type SerializeMap = MapSerializer;
1812        type SerializeStruct = MapSerializer;
1813        type SerializeStructVariant = StructVariantSerializer;
1814
1815        fn serialize_bool(self, v: bool) -> Result<Value, Error> {
1816            Ok(Value::Bool(v))
1817        }
1818        fn serialize_i8(self, v: i8) -> Result<Value, Error> {
1819            Ok(Value::Int(v as i64))
1820        }
1821        fn serialize_i16(self, v: i16) -> Result<Value, Error> {
1822            Ok(Value::Int(v as i64))
1823        }
1824        fn serialize_i32(self, v: i32) -> Result<Value, Error> {
1825            Ok(Value::Int(v as i64))
1826        }
1827        fn serialize_i64(self, v: i64) -> Result<Value, Error> {
1828            Ok(Value::Int(v))
1829        }
1830        fn serialize_u8(self, v: u8) -> Result<Value, Error> {
1831            Ok(Value::Int(v as i64))
1832        }
1833        fn serialize_u16(self, v: u16) -> Result<Value, Error> {
1834            Ok(Value::Int(v as i64))
1835        }
1836        fn serialize_u32(self, v: u32) -> Result<Value, Error> {
1837            Ok(Value::Int(v as i64))
1838        }
1839        fn serialize_u64(self, v: u64) -> Result<Value, Error> {
1840            Ok(i64::try_from(v)
1841                .map(Value::Int)
1842                .unwrap_or_else(|_| Value::Float(v as f64)))
1843        }
1844        fn serialize_f32(self, v: f32) -> Result<Value, Error> {
1845            Ok(Value::Float(v as f64))
1846        }
1847        fn serialize_f64(self, v: f64) -> Result<Value, Error> {
1848            Ok(Value::Float(v))
1849        }
1850        fn serialize_char(self, v: char) -> Result<Value, Error> {
1851            Ok(Value::Str(v.to_string()))
1852        }
1853        fn serialize_str(self, v: &str) -> Result<Value, Error> {
1854            Ok(Value::Str(v.to_string()))
1855        }
1856        fn serialize_bytes(self, v: &[u8]) -> Result<Value, Error> {
1857            Ok(Value::Array(v.iter().map(|&b| Value::Int(b as i64)).collect()))
1858        }
1859        fn serialize_none(self) -> Result<Value, Error> {
1860            Ok(Value::Null)
1861        }
1862        fn serialize_some<T: Serialize + ?Sized>(self, v: &T) -> Result<Value, Error> {
1863            v.serialize(ValueSerializer)
1864        }
1865        fn serialize_unit(self) -> Result<Value, Error> {
1866            Ok(Value::Null)
1867        }
1868        fn serialize_unit_struct(self, _name: &'static str) -> Result<Value, Error> {
1869            Ok(Value::Null)
1870        }
1871        fn serialize_unit_variant(
1872            self,
1873            _name: &'static str,
1874            _idx: u32,
1875            variant: &'static str,
1876        ) -> Result<Value, Error> {
1877            Ok(Value::Str(variant.to_string()))
1878        }
1879        fn serialize_newtype_struct<T: Serialize + ?Sized>(
1880            self,
1881            _name: &'static str,
1882            v: &T,
1883        ) -> Result<Value, Error> {
1884            v.serialize(ValueSerializer)
1885        }
1886        fn serialize_newtype_variant<T: Serialize + ?Sized>(
1887            self,
1888            _name: &'static str,
1889            _idx: u32,
1890            variant: &'static str,
1891            value: &T,
1892        ) -> Result<Value, Error> {
1893            Ok(Value::Object(BTreeMap::from([
1894                ("__type".into(), Value::Str(variant.to_string())),
1895                ("_value".into(), value.serialize(ValueSerializer)?),
1896            ])))
1897        }
1898        fn serialize_seq(self, _len: Option<usize>) -> Result<Self::SerializeSeq, Error> {
1899            Ok(SeqSerializer(Vec::new()))
1900        }
1901        fn serialize_tuple(self, len: usize) -> Result<Self::SerializeTuple, Error> {
1902            self.serialize_seq(Some(len))
1903        }
1904        fn serialize_tuple_struct(
1905            self,
1906            _name: &'static str,
1907            len: usize,
1908        ) -> Result<Self::SerializeTupleStruct, Error> {
1909            self.serialize_seq(Some(len))
1910        }
1911        fn serialize_tuple_variant(
1912            self,
1913            _name: &'static str,
1914            _idx: u32,
1915            variant: &'static str,
1916            _len: usize,
1917        ) -> Result<Self::SerializeTupleVariant, Error> {
1918            Ok(TupleVariantSerializer {
1919                variant: variant.to_string(),
1920                values: Vec::new(),
1921            })
1922        }
1923        fn serialize_map(self, _len: Option<usize>) -> Result<Self::SerializeMap, Error> {
1924            Ok(MapSerializer {
1925                map: BTreeMap::new(),
1926                key: None,
1927            })
1928        }
1929        fn serialize_struct(self, _name: &'static str, len: usize) -> Result<Self::SerializeStruct, Error> {
1930            self.serialize_map(Some(len))
1931        }
1932        fn serialize_struct_variant(
1933            self,
1934            _name: &'static str,
1935            _idx: u32,
1936            variant: &'static str,
1937            _len: usize,
1938        ) -> Result<Self::SerializeStructVariant, Error> {
1939            Ok(StructVariantSerializer {
1940                variant: variant.to_string(),
1941                map: BTreeMap::new(),
1942            })
1943        }
1944    }
1945
1946    struct SeqSerializer(Vec<Value>);
1947
1948    impl SerializeSeq for SeqSerializer {
1949        type Ok = Value;
1950        type Error = Error;
1951        fn serialize_element<T: Serialize + ?Sized>(&mut self, value: &T) -> Result<(), Error> {
1952            self.0.push(value.serialize(ValueSerializer)?);
1953            Ok(())
1954        }
1955        fn end(self) -> Result<Value, Error> {
1956            Ok(Value::Array(self.0))
1957        }
1958    }
1959    impl SerializeTuple for SeqSerializer {
1960        type Ok = Value;
1961        type Error = Error;
1962        fn serialize_element<T: Serialize + ?Sized>(&mut self, value: &T) -> Result<(), Error> {
1963            SerializeSeq::serialize_element(self, value)
1964        }
1965        fn end(self) -> Result<Value, Error> {
1966            SerializeSeq::end(self)
1967        }
1968    }
1969    impl SerializeTupleStruct for SeqSerializer {
1970        type Ok = Value;
1971        type Error = Error;
1972        fn serialize_field<T: Serialize + ?Sized>(&mut self, value: &T) -> Result<(), Error> {
1973            SerializeSeq::serialize_element(self, value)
1974        }
1975        fn end(self) -> Result<Value, Error> {
1976            SerializeSeq::end(self)
1977        }
1978    }
1979
1980    struct MapSerializer {
1981        map: BTreeMap<String, Value>,
1982        key: Option<String>,
1983    }
1984
1985    impl SerializeMap for MapSerializer {
1986        type Ok = Value;
1987        type Error = Error;
1988        fn serialize_key<T: Serialize + ?Sized>(&mut self, key: &T) -> Result<(), Error> {
1989            self.key = Some(key.serialize(KeySerializer)?);
1990            Ok(())
1991        }
1992        fn serialize_value<T: Serialize + ?Sized>(&mut self, value: &T) -> Result<(), Error> {
1993            let k = self
1994                .key
1995                .take()
1996                .ok_or_else(|| de::Error::custom("serialize_value 前需先 serialize_key"))?;
1997            self.map.insert(k, value.serialize(ValueSerializer)?);
1998            Ok(())
1999        }
2000        fn end(self) -> Result<Value, Error> {
2001            Ok(Value::Object(self.map))
2002        }
2003    }
2004
2005    impl SerializeStruct for MapSerializer {
2006        type Ok = Value;
2007        type Error = Error;
2008        fn serialize_field<T: Serialize + ?Sized>(
2009            &mut self,
2010            key: &'static str,
2011            value: &T,
2012        ) -> Result<(), Error> {
2013            self.map
2014                .insert(key.to_string(), value.serialize(ValueSerializer)?);
2015            Ok(())
2016        }
2017        fn end(self) -> Result<Value, Error> {
2018            Ok(Value::Object(self.map))
2019        }
2020    }
2021
2022    /// 对象键必须能转成字符串(SML 的键是裸词/字符串)
2023    struct KeySerializer;
2024
2025    macro_rules! key_unsupported {
2026        ($(fn $m:ident($($a:ident : $t:ty),*) -> Result<String, Error>;)*) => {
2027            $(
2028                fn $m(self, $($a: $t),*) -> Result<String, Error> {
2029                    Err(de::Error::custom("SML 对象的键必须是字符串"))
2030                }
2031            )*
2032        };
2033    }
2034
2035    impl Serializer for KeySerializer {
2036        type Ok = String;
2037        type Error = Error;
2038        type SerializeSeq = ::serde::ser::Impossible<String, Error>;
2039        type SerializeTuple = ::serde::ser::Impossible<String, Error>;
2040        type SerializeTupleStruct = ::serde::ser::Impossible<String, Error>;
2041        type SerializeTupleVariant = ::serde::ser::Impossible<String, Error>;
2042        type SerializeMap = ::serde::ser::Impossible<String, Error>;
2043        type SerializeStruct = ::serde::ser::Impossible<String, Error>;
2044        type SerializeStructVariant = ::serde::ser::Impossible<String, Error>;
2045
2046        fn serialize_str(self, v: &str) -> Result<String, Error> {
2047            Ok(v.to_string())
2048        }
2049        fn serialize_char(self, v: char) -> Result<String, Error> {
2050            Ok(v.to_string())
2051        }
2052        key_unsupported! {
2053            fn serialize_bool(_v: bool) -> Result<String, Error>;
2054            fn serialize_i8(_v: i8) -> Result<String, Error>;
2055            fn serialize_i16(_v: i16) -> Result<String, Error>;
2056            fn serialize_i32(_v: i32) -> Result<String, Error>;
2057            fn serialize_i64(_v: i64) -> Result<String, Error>;
2058            fn serialize_u8(_v: u8) -> Result<String, Error>;
2059            fn serialize_u16(_v: u16) -> Result<String, Error>;
2060            fn serialize_u32(_v: u32) -> Result<String, Error>;
2061            fn serialize_u64(_v: u64) -> Result<String, Error>;
2062            fn serialize_f32(_v: f32) -> Result<String, Error>;
2063            fn serialize_f64(_v: f64) -> Result<String, Error>;
2064            fn serialize_bytes(_v: &[u8]) -> Result<String, Error>;
2065            fn serialize_none() -> Result<String, Error>;
2066            fn serialize_unit() -> Result<String, Error>;
2067            fn serialize_unit_struct(_n: &'static str) -> Result<String, Error>;
2068            fn serialize_unit_variant(_n: &'static str, _i: u32, _v: &'static str) -> Result<String, Error>;
2069        }
2070        fn serialize_some<T: Serialize + ?Sized>(self, _v: &T) -> Result<String, Error> {
2071            Err(de::Error::custom("SML 对象的键必须是字符串"))
2072        }
2073        fn serialize_newtype_struct<T: Serialize + ?Sized>(
2074            self,
2075            _n: &'static str,
2076            _v: &T,
2077        ) -> Result<String, Error> {
2078            Err(de::Error::custom("SML 对象的键必须是字符串"))
2079        }
2080        fn serialize_newtype_variant<T: Serialize + ?Sized>(
2081            self,
2082            _n: &'static str,
2083            _i: u32,
2084            _v: &'static str,
2085            _x: &T,
2086        ) -> Result<String, Error> {
2087            Err(de::Error::custom("SML 对象的键必须是字符串"))
2088        }
2089        // 以下方法返回关联类型(Impossible),一律报错——SML 键只能是字符串
2090        fn serialize_seq(self, _l: Option<usize>) -> Result<Self::SerializeSeq, Error> {
2091            Err(de::Error::custom("SML 对象的键必须是字符串"))
2092        }
2093        fn serialize_tuple(self, _l: usize) -> Result<Self::SerializeTuple, Error> {
2094            Err(de::Error::custom("SML 对象的键必须是字符串"))
2095        }
2096        fn serialize_tuple_struct(
2097            self,
2098            _n: &'static str,
2099            _l: usize,
2100        ) -> Result<Self::SerializeTupleStruct, Error> {
2101            Err(de::Error::custom("SML 对象的键必须是字符串"))
2102        }
2103        fn serialize_tuple_variant(
2104            self,
2105            _n: &'static str,
2106            _i: u32,
2107            _v: &'static str,
2108            _l: usize,
2109        ) -> Result<Self::SerializeTupleVariant, Error> {
2110            Err(de::Error::custom("SML 对象的键必须是字符串"))
2111        }
2112        fn serialize_map(self, _l: Option<usize>) -> Result<Self::SerializeMap, Error> {
2113            Err(de::Error::custom("SML 对象的键必须是字符串"))
2114        }
2115        fn serialize_struct(self, _n: &'static str, _l: usize) -> Result<Self::SerializeStruct, Error> {
2116            Err(de::Error::custom("SML 对象的键必须是字符串"))
2117        }
2118        fn serialize_struct_variant(
2119            self,
2120            _n: &'static str,
2121            _i: u32,
2122            _v: &'static str,
2123            _l: usize,
2124        ) -> Result<Self::SerializeStructVariant, Error> {
2125            Err(de::Error::custom("SML 对象的键必须是字符串"))
2126        }
2127    }
2128
2129    struct TupleVariantSerializer {
2130        variant: String,
2131        values: Vec<Value>,
2132    }
2133
2134    impl SerializeTupleVariant for TupleVariantSerializer {
2135        type Ok = Value;
2136        type Error = Error;
2137        fn serialize_field<T: Serialize + ?Sized>(&mut self, value: &T) -> Result<(), Error> {
2138            self.values.push(value.serialize(ValueSerializer)?);
2139            Ok(())
2140        }
2141        fn end(self) -> Result<Value, Error> {
2142            Ok(Value::Object(BTreeMap::from([
2143                ("__type".into(), Value::Str(self.variant)),
2144                ("_value".into(), Value::Array(self.values)),
2145            ])))
2146        }
2147    }
2148
2149    struct StructVariantSerializer {
2150        variant: String,
2151        map: BTreeMap<String, Value>,
2152    }
2153
2154    impl SerializeStructVariant for StructVariantSerializer {
2155        type Ok = Value;
2156        type Error = Error;
2157        fn serialize_field<T: Serialize + ?Sized>(
2158            &mut self,
2159            key: &'static str,
2160            value: &T,
2161        ) -> Result<(), Error> {
2162            self.map
2163                .insert(key.to_string(), value.serialize(ValueSerializer)?);
2164            Ok(())
2165        }
2166        fn end(self) -> Result<Value, Error> {
2167            let mut m = BTreeMap::new();
2168            m.insert("__type".into(), Value::Str(self.variant));
2169            m.extend(self.map);
2170            Ok(Value::Object(m))
2171        }
2172    }
2173
2174    // ---- Deserializer: Value -> T: Deserialize ----
2175
2176    macro_rules! deser_int {
2177        ($(fn $m:ident($v:ident, $call:ident);)*) => {
2178            $(
2179                fn $m<V>(self, $v: V) -> Result<V::Value, Self::Error>
2180                where V: Visitor<'de> {
2181                    match self.0 {
2182                        Value::Int(i) => $v.$call(i as _),
2183                        Value::Float(f)
2184                            if f.fract() == 0.0
2185                                && f >= i64::MIN as f64
2186                                && f <= i64::MAX as f64 =>
2187                        {
2188                            $v.$call(f as _)
2189                        }
2190                        other => Err(type_err(&other, stringify!($m).trim_start_matches("deserialize_"))),
2191                    }
2192                }
2193            )*
2194        };
2195    }
2196
2197    struct ValueDeserializer(Value);
2198
2199    impl<'de> Deserializer<'de> for ValueDeserializer {
2200        type Error = Error;
2201
2202        fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Error>
2203        where
2204            V: Visitor<'de>,
2205        {
2206            match self.0 {
2207                Value::Null => visitor.visit_unit(),
2208                Value::Bool(b) => visitor.visit_bool(b),
2209                Value::Int(i) => visitor.visit_i64(i),
2210                Value::Float(f) => visitor.visit_f64(f),
2211                Value::Str(s) => visitor.visit_string(s),
2212                Value::Array(a) => visitor.visit_seq(SeqDeserializer { items: a, idx: 0 }),
2213                Value::Object(m) => visitor.visit_map(MapDeserializer { map: m, pending: None }),
2214            }
2215        }
2216
2217        fn deserialize_bool<V>(self, visitor: V) -> Result<V::Value, Error>
2218        where
2219            V: Visitor<'de>,
2220        {
2221            match self.0 {
2222                Value::Bool(b) => visitor.visit_bool(b),
2223                other => Err(type_err(&other, "布尔")),
2224            }
2225        }
2226
2227        deser_int! {
2228            fn deserialize_i8(v, visit_i8);
2229            fn deserialize_i16(v, visit_i16);
2230            fn deserialize_i32(v, visit_i32);
2231            fn deserialize_i64(v, visit_i64);
2232            fn deserialize_u8(v, visit_u8);
2233            fn deserialize_u16(v, visit_u16);
2234            fn deserialize_u32(v, visit_u32);
2235        }
2236
2237        fn deserialize_u64<V>(self, visitor: V) -> Result<V::Value, Error>
2238        where
2239            V: Visitor<'de>,
2240        {
2241            match self.0 {
2242                Value::Int(i) if i >= 0 => visitor.visit_u64(i as u64),
2243                Value::Float(f)
2244                    if f.fract() == 0.0 && f >= 0.0 && f <= u64::MAX as f64 =>
2245                {
2246                    visitor.visit_u64(f as u64)
2247                }
2248                other => Err(type_err(&other, "u64")),
2249            }
2250        }
2251
2252        fn deserialize_f32<V>(self, visitor: V) -> Result<V::Value, Error>
2253        where
2254            V: Visitor<'de>,
2255        {
2256            match self.0 {
2257                Value::Int(i) => visitor.visit_f32(i as f32),
2258                Value::Float(f) => visitor.visit_f32(f as f32),
2259                other => Err(type_err(&other, "f32")),
2260            }
2261        }
2262        fn deserialize_f64<V>(self, visitor: V) -> Result<V::Value, Error>
2263        where
2264            V: Visitor<'de>,
2265        {
2266            match self.0 {
2267                Value::Int(i) => visitor.visit_f64(i as f64),
2268                Value::Float(f) => visitor.visit_f64(f),
2269                other => Err(type_err(&other, "f64")),
2270            }
2271        }
2272
2273        fn deserialize_char<V>(self, visitor: V) -> Result<V::Value, Error>
2274        where
2275            V: Visitor<'de>,
2276        {
2277            match self.0 {
2278                Value::Str(s) if s.chars().count() == 1 => {
2279                    visitor.visit_char(s.chars().next().unwrap())
2280                }
2281                other => Err(type_err(&other, "字符")),
2282            }
2283        }
2284
2285        fn deserialize_str<V>(self, visitor: V) -> Result<V::Value, Error>
2286        where
2287            V: Visitor<'de>,
2288        {
2289            match self.0 {
2290                Value::Str(s) => visitor.visit_string(s),
2291                other => Err(type_err(&other, "字符串")),
2292            }
2293        }
2294        fn deserialize_string<V>(self, visitor: V) -> Result<V::Value, Error>
2295        where
2296            V: Visitor<'de>,
2297        {
2298            self.deserialize_str(visitor)
2299        }
2300
2301        fn deserialize_bytes<V>(self, visitor: V) -> Result<V::Value, Error>
2302        where
2303            V: Visitor<'de>,
2304        {
2305            match self.0 {
2306                Value::Array(items) => {
2307                    let mut buf = Vec::with_capacity(items.len());
2308                    for it in items {
2309                        match it {
2310                            Value::Int(i) if (0..=255).contains(&i) => buf.push(i as u8),
2311                            other => return Err(type_err(&other, "字节")),
2312                        }
2313                    }
2314                    visitor.visit_byte_buf(buf)
2315                }
2316                other => Err(type_err(&other, "字节数组")),
2317            }
2318        }
2319        fn deserialize_byte_buf<V>(self, visitor: V) -> Result<V::Value, Error>
2320        where
2321            V: Visitor<'de>,
2322        {
2323            self.deserialize_bytes(visitor)
2324        }
2325
2326        fn deserialize_option<V>(self, visitor: V) -> Result<V::Value, Error>
2327        where
2328            V: Visitor<'de>,
2329        {
2330            match self.0 {
2331                Value::Null => visitor.visit_none(),
2332                other => visitor.visit_some(ValueDeserializer(other)),
2333            }
2334        }
2335
2336        fn deserialize_unit<V>(self, visitor: V) -> Result<V::Value, Error>
2337        where
2338            V: Visitor<'de>,
2339        {
2340            match self.0 {
2341                Value::Null => visitor.visit_unit(),
2342                other => Err(type_err(&other, "unit")),
2343            }
2344        }
2345        fn deserialize_unit_struct<V>(
2346            self,
2347            _name: &'static str,
2348            visitor: V,
2349        ) -> Result<V::Value, Error>
2350        where
2351            V: Visitor<'de>,
2352        {
2353            self.deserialize_unit(visitor)
2354        }
2355        fn deserialize_newtype_struct<V>(
2356            self,
2357            _name: &'static str,
2358            visitor: V,
2359        ) -> Result<V::Value, Error>
2360        where
2361            V: Visitor<'de>,
2362        {
2363            self.deserialize_any(visitor)
2364        }
2365
2366        fn deserialize_seq<V>(self, visitor: V) -> Result<V::Value, Error>
2367        where
2368            V: Visitor<'de>,
2369        {
2370            match self.0 {
2371                Value::Array(a) => visitor.visit_seq(SeqDeserializer { items: a, idx: 0 }),
2372                other => Err(type_err(&other, "数组")),
2373            }
2374        }
2375        fn deserialize_tuple<V>(self, _len: usize, visitor: V) -> Result<V::Value, Error>
2376        where
2377            V: Visitor<'de>,
2378        {
2379            self.deserialize_seq(visitor)
2380        }
2381        fn deserialize_tuple_struct<V>(
2382            self,
2383            _name: &'static str,
2384            _len: usize,
2385            visitor: V,
2386        ) -> Result<V::Value, Error>
2387        where
2388            V: Visitor<'de>,
2389        {
2390            self.deserialize_seq(visitor)
2391        }
2392
2393        fn deserialize_map<V>(self, visitor: V) -> Result<V::Value, Error>
2394        where
2395            V: Visitor<'de>,
2396        {
2397            match self.0 {
2398                Value::Object(m) => visitor.visit_map(MapDeserializer { map: m, pending: None }),
2399                other => Err(type_err(&other, "块/对象")),
2400            }
2401        }
2402        fn deserialize_struct<V>(
2403            self,
2404            _name: &'static str,
2405            _fields: &'static [&'static str],
2406            visitor: V,
2407        ) -> Result<V::Value, Error>
2408        where
2409            V: Visitor<'de>,
2410        {
2411            self.deserialize_map(visitor)
2412        }
2413
2414        fn deserialize_enum<V>(
2415            self,
2416            _name: &'static str,
2417            _variants: &'static [&'static str],
2418            visitor: V,
2419        ) -> Result<V::Value, Error>
2420        where
2421            V: Visitor<'de>,
2422        {
2423            match self.0 {
2424                Value::Str(s) => visitor.visit_enum(EnumDeserializer {
2425                    variant: s,
2426                    kind: EnumKind::Unit,
2427                }),
2428                Value::Object(mut m) => {
2429                    // 1) SML 专有约定:`__type` 键(与 SmlSerialize 输出一致)
2430                    if let Some(ty) = m.remove("__type") {
2431                        let variant = match ty {
2432                            Value::Str(s) => s,
2433                            _ => return Err(de::Error::custom("`__type` 的值必须是字符串")),
2434                        };
2435                        let kind = match m.remove("_value") {
2436                            Some(Value::Array(items)) => EnumKind::Tuple(items),
2437                            Some(other) => EnumKind::Newtype(other),
2438                            None if m.is_empty() => EnumKind::Unit,
2439                            None => EnumKind::Struct(m),
2440                        };
2441                        return visitor.visit_enum(EnumDeserializer { variant, kind });
2442                    }
2443                    // 2) serde 外部标签(含 SML 裸词包裹形态):
2444                    //    {"in-maintenance": "in-maintenance"} -> 单元变体
2445                    //    {"Circle": 3}                        -> 单值变体
2446                    if m.len() == 1 {
2447                        let (k, v) = m.pop_first().expect("len==1 必有键");
2448                        let kind = match v {
2449                            Value::Str(s) if s == k => EnumKind::Unit,
2450                            other => EnumKind::Newtype(other),
2451                        };
2452                        return visitor.visit_enum(EnumDeserializer { variant: k, kind });
2453                    }
2454                    Err(de::Error::custom(
2455                        "枚举块需要 `__type` 键(SML 约定)或单键外部标签 `{ VariantName: ... }`",
2456                    ))
2457                }
2458                other => Err(type_err(&other, "枚举")),
2459            }
2460        }
2461
2462        fn deserialize_identifier<V>(self, visitor: V) -> Result<V::Value, Error>
2463        where
2464            V: Visitor<'de>,
2465        {
2466            self.deserialize_str(visitor)
2467        }
2468        fn deserialize_ignored_any<V>(self, visitor: V) -> Result<V::Value, Error>
2469        where
2470            V: Visitor<'de>,
2471        {
2472            self.deserialize_any(visitor)
2473        }
2474    }
2475
2476    struct SeqDeserializer {
2477        items: Vec<Value>,
2478        idx: usize,
2479    }
2480
2481    impl<'de> SeqAccess<'de> for SeqDeserializer {
2482        type Error = Error;
2483        fn next_element_seed<T: de::DeserializeSeed<'de>>(
2484            &mut self,
2485            seed: T,
2486        ) -> Result<Option<T::Value>, Error> {
2487            if self.idx >= self.items.len() {
2488                return Ok(None);
2489            }
2490            let item = self.items[self.idx].clone();
2491            self.idx += 1;
2492            seed.deserialize(ValueDeserializer(item)).map(Some)
2493        }
2494    }
2495
2496    struct MapDeserializer {
2497        map: BTreeMap<String, Value>,
2498        pending: Option<Value>,
2499    }
2500
2501    impl<'de> MapAccess<'de> for MapDeserializer {
2502        type Error = Error;
2503        fn next_key_seed<K: de::DeserializeSeed<'de>>(
2504            &mut self,
2505            seed: K,
2506        ) -> Result<Option<K::Value>, Error> {
2507            let Some((k, v)) = self.map.pop_first() else {
2508                return Ok(None);
2509            };
2510            self.pending = Some(v);
2511            seed.deserialize(KeyDeserializer(&k)).map(Some)
2512        }
2513        fn next_value_seed<V: de::DeserializeSeed<'de>>(
2514            &mut self,
2515            seed: V,
2516        ) -> Result<V::Value, Error> {
2517            let v = self.pending.take().ok_or_else(|| {
2518                de::Error::custom("value 缺失:需先调用 next_key_seed")
2519            })?;
2520            seed.deserialize(ValueDeserializer(v))
2521        }
2522    }
2523
2524    /// 字段名 / 变体名的轻量反序列化器(只认字符串)
2525    struct KeyDeserializer<'a>(&'a str);
2526
2527    macro_rules! key_delegate {
2528        ($($m:ident),* $(,)?) => {
2529            $(
2530                fn $m<V>(self, visitor: V) -> Result<V::Value, Error>
2531                where V: Visitor<'de> {
2532                    self.deserialize_any(visitor)
2533                }
2534            )*
2535        };
2536    }
2537
2538    impl<'de, 'a> Deserializer<'de> for KeyDeserializer<'a> {
2539        type Error = Error;
2540
2541        fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Error>
2542        where
2543            V: Visitor<'de>,
2544        {
2545            visitor.visit_str(self.0)
2546        }
2547        fn deserialize_str<V>(self, visitor: V) -> Result<V::Value, Error>
2548        where
2549            V: Visitor<'de>,
2550        {
2551            visitor.visit_str(self.0)
2552        }
2553        fn deserialize_string<V>(self, visitor: V) -> Result<V::Value, Error>
2554        where
2555            V: Visitor<'de>,
2556        {
2557            visitor.visit_str(self.0)
2558        }
2559        fn deserialize_identifier<V>(self, visitor: V) -> Result<V::Value, Error>
2560        where
2561            V: Visitor<'de>,
2562        {
2563            visitor.visit_str(self.0)
2564        }
2565        fn deserialize_enum<V>(
2566            self,
2567            _name: &'static str,
2568            _variants: &'static [&'static str],
2569            visitor: V,
2570        ) -> Result<V::Value, Error>
2571        where
2572            V: Visitor<'de>,
2573        {
2574            visitor.visit_enum(EnumDeserializer {
2575                variant: self.0.to_string(),
2576                kind: EnumKind::Unit,
2577            })
2578        }
2579        fn deserialize_option<V>(self, visitor: V) -> Result<V::Value, Error>
2580        where
2581            V: Visitor<'de>,
2582        {
2583            visitor.visit_some(self)
2584        }
2585        fn deserialize_unit_struct<V>(
2586            self,
2587            _name: &'static str,
2588            visitor: V,
2589        ) -> Result<V::Value, Error>
2590        where
2591            V: Visitor<'de>,
2592        {
2593            self.deserialize_unit(visitor)
2594        }
2595        fn deserialize_newtype_struct<V>(
2596            self,
2597            _name: &'static str,
2598            visitor: V,
2599        ) -> Result<V::Value, Error>
2600        where
2601            V: Visitor<'de>,
2602        {
2603            self.deserialize_any(visitor)
2604        }
2605        fn deserialize_tuple<V>(self, _len: usize, visitor: V) -> Result<V::Value, Error>
2606        where
2607            V: Visitor<'de>,
2608        {
2609            self.deserialize_seq(visitor)
2610        }
2611        fn deserialize_tuple_struct<V>(
2612            self,
2613            _name: &'static str,
2614            _len: usize,
2615            visitor: V,
2616        ) -> Result<V::Value, Error>
2617        where
2618            V: Visitor<'de>,
2619        {
2620            self.deserialize_seq(visitor)
2621        }
2622        fn deserialize_struct<V>(
2623            self,
2624            _name: &'static str,
2625            _fields: &'static [&'static str],
2626            visitor: V,
2627        ) -> Result<V::Value, Error>
2628        where
2629            V: Visitor<'de>,
2630        {
2631            self.deserialize_map(visitor)
2632        }
2633        fn deserialize_ignored_any<V>(self, visitor: V) -> Result<V::Value, Error>
2634        where
2635            V: Visitor<'de>,
2636        {
2637            self.deserialize_any(visitor)
2638        }
2639        key_delegate! {
2640            deserialize_bool, deserialize_i8, deserialize_i16, deserialize_i32,
2641            deserialize_i64, deserialize_u8, deserialize_u16, deserialize_u32,
2642            deserialize_u64, deserialize_f32, deserialize_f64, deserialize_char,
2643            deserialize_bytes, deserialize_byte_buf, deserialize_unit,
2644            deserialize_seq, deserialize_map,
2645        }
2646    }
2647
2648    // ---- 枚举(SML `__type` 约定,与 SmlDeserialize 一致)----
2649
2650    #[derive(Debug)]
2651    enum EnumKind {
2652        Unit,
2653        Newtype(Value),
2654        Tuple(Vec<Value>),
2655        Struct(BTreeMap<String, Value>),
2656    }
2657
2658    struct EnumDeserializer {
2659        variant: String,
2660        kind: EnumKind,
2661    }
2662
2663    impl<'de> de::EnumAccess<'de> for EnumDeserializer {
2664        type Error = Error;
2665        type Variant = VariantAccess;
2666        fn variant_seed<V: de::DeserializeSeed<'de>>(
2667            self,
2668            seed: V,
2669        ) -> Result<(V::Value, Self::Variant), Error> {
2670            let variant = seed.deserialize(KeyDeserializer(&self.variant))?;
2671            Ok((variant, VariantAccess { kind: self.kind }))
2672        }
2673    }
2674
2675    struct VariantAccess {
2676        kind: EnumKind,
2677    }
2678
2679    impl<'de> de::VariantAccess<'de> for VariantAccess {
2680        type Error = Error;
2681        fn unit_variant(self) -> Result<(), Error> {
2682            match self.kind {
2683                EnumKind::Unit => Ok(()),
2684                _ => Err(de::Error::custom("该变体携带数据,不能按单元变体解析")),
2685            }
2686        }
2687        fn newtype_variant_seed<T: de::DeserializeSeed<'de>>(
2688            self,
2689            seed: T,
2690        ) -> Result<T::Value, Error> {
2691            match self.kind {
2692                EnumKind::Newtype(v) => seed.deserialize(ValueDeserializer(v)),
2693                EnumKind::Tuple(items) => {
2694                    seed.deserialize(ValueDeserializer(Value::Array(items)))
2695                }
2696                _ => Err(de::Error::custom("该变体没有单值数据")),
2697            }
2698        }
2699        fn tuple_variant<V>(self, _len: usize, visitor: V) -> Result<V::Value, Error>
2700        where
2701            V: Visitor<'de>,
2702        {
2703            match self.kind {
2704                EnumKind::Tuple(items) => {
2705                    visitor.visit_seq(SeqDeserializer { items, idx: 0 })
2706                }
2707                _ => Err(de::Error::custom("该变体不是元组形态")),
2708            }
2709        }
2710        fn struct_variant<V>(
2711            self,
2712            _fields: &'static [&'static str],
2713            visitor: V,
2714        ) -> Result<V::Value, Error>
2715        where
2716            V: Visitor<'de>,
2717        {
2718            match self.kind {
2719                EnumKind::Struct(m) => {
2720                    visitor.visit_map(MapDeserializer { map: m, pending: None })
2721                }
2722                _ => Err(de::Error::custom("该变体不是结构体形态")),
2723            }
2724        }
2725    }
2726}
2727
2728// ---------------------------------------------------------------------------
2729// 自然序列化宏(derive)支持
2730// ---------------------------------------------------------------------------
2731
2732/// 把一个类型「自然地」序列化为 SML 值:
2733/// 结构体 → 块、newtype → 透明、单元结构体 → 裸词、
2734/// 枚举单元变体 → 裸词、带数据变体 → `__type` 块。
2735///
2736/// 通常用 `#[derive(SmlSerialize)]` 自动实现(`derive` feature 默认开启),
2737/// 也可手动实现。支持的 `#[sml(...)]` 属性见 `swsml-derive` 的文档。
2738pub trait SmlSerialize {
2739    fn to_sml_value(&self) -> Value;
2740
2741    /// 序列化为 SML 文本(等价于 [`to_sml`] 作用于本类型生成的值)。
2742    fn to_sml(&self) -> String {
2743        crate::to_sml(&self.to_sml_value())
2744    }
2745}
2746
2747/// 从 SML 值反序列化(`#[derive(SmlDeserialize)]` 自动实现)。
2748pub trait SmlDeserialize: Sized {
2749    fn from_sml_value(v: &Value) -> Result<Self, String>;
2750
2751    /// 解析 SML 文本并反序列化。
2752    fn from_sml(text: &str) -> Result<Self, String> {
2753        let v = crate::parse(text).map_err(|e| format!("SML 解析失败: {e}"))?;
2754        Self::from_sml_value(&v)
2755    }
2756}
2757
2758#[cfg(feature = "derive")]
2759pub use swsml_derive::{SmlDeserialize, SmlSerialize};
2760
2761/// 序列化为 SML 文本 —— toml-rs 风格的顶层函数(等价于 [`SmlSerialize::to_sml`])。
2762///
2763/// 用法与 `toml::to_string` 一致(序列化不会失败,故直接返回 `String`):
2764///
2765/// ```rust
2766/// # use sml::{SmlSerialize, SmlDeserialize};
2767/// # #[derive(SmlSerialize, SmlDeserialize, Debug, PartialEq)]
2768/// # struct Server { host: String, port: i32 }
2769/// # let cfg = Server { host: "web.example".into(), port: 8080 };
2770/// let text = sml::to_string(&cfg);
2771/// assert_eq!(text, "host: web.example\nport: 8080\n");
2772/// ```
2773pub fn to_string<T: SmlSerialize + ?Sized>(value: &T) -> String {
2774    crate::to_sml(&value.to_sml_value())
2775}
2776
2777/// 解析 SML 文本并反序列化 —— toml-rs 风格的顶层函数(等价于 [`SmlDeserialize::from_sml`])。
2778///
2779/// ```rust
2780/// # use sml::{SmlSerialize, SmlDeserialize};
2781/// # #[derive(SmlSerialize, SmlDeserialize, Debug, PartialEq)]
2782/// # struct Server { host: String, port: i32 }
2783/// let back: Server = sml::from_str("host: web.example\nport: 8080\n").unwrap();
2784/// assert_eq!(back.host, "web.example");
2785/// assert_eq!(back.port, 8080);
2786/// ```
2787pub fn from_str<T: SmlDeserialize>(text: &str) -> Result<T, String> {
2788    T::from_sml(text)
2789}
2790
2791/// 宏生成代码引用的内部辅助(请勿直接使用)。
2792#[doc(hidden)]
2793pub mod __private {
2794    use super::{SmlDeserialize, SmlSerialize, Value};
2795    use std::collections::{BTreeMap, HashMap};
2796
2797    /// 描述值的类型,用于错误信息。
2798    pub fn describe_value(v: &Value) -> String {
2799        match v {
2800            Value::Null => "null".to_string(),
2801            Value::Bool(b) => b.to_string(),
2802            Value::Int(i) => i.to_string(),
2803            Value::Float(f) => f.to_string(),
2804            Value::Str(s) => format!("字符串 `{s}`"),
2805            Value::Array(a) => format!("数组({} 个元素)", a.len()),
2806            Value::Object(o) => format!("块({} 个键)", o.len()),
2807        }
2808    }
2809
2810    /// 取出 `_value` 键(枚举单值变体)。
2811    pub fn take_value(m: &BTreeMap<String, Value>) -> Result<Value, String> {
2812        m.get("_value")
2813            .cloned()
2814            .ok_or_else(|| "缺少 _value 键".to_string())
2815    }
2816
2817    /// 取出 `_value` 键并断言为数组(枚举 tuple 变体)。
2818    pub fn take_array(m: &BTreeMap<String, Value>) -> Result<Vec<Value>, String> {
2819        match m.get("_value") {
2820            Some(Value::Array(a)) => Ok(a.clone()),
2821            Some(other) => Err(format!("_value 期望数组,实际为 {}", describe_value(other))),
2822            None => Err("缺少 _value 键".to_string()),
2823        }
2824    }
2825
2826    /// `#[sml(flatten)]` 反序列化:把整个块交给子类型。
2827    pub fn flatten_from<T: SmlDeserialize>(m: &BTreeMap<String, Value>) -> Result<T, String> {
2828        T::from_sml_value(&Value::Object(m.clone()))
2829    }
2830
2831    // ---- 基础类型 ----
2832
2833    impl SmlSerialize for bool {
2834        #[inline]
2835        fn to_sml_value(&self) -> Value {
2836            Value::Bool(*self)
2837        }
2838    }
2839    impl SmlDeserialize for bool {
2840        #[inline]
2841        fn from_sml_value(v: &Value) -> Result<Self, String> {
2842            match v {
2843                Value::Bool(b) => Ok(*b),
2844                other => Err(format!("期望布尔,实际为 {}", describe_value(other))),
2845            }
2846        }
2847    }
2848
2849    macro_rules! impl_int {
2850        ($($t:ty),* $(,)?) => {$(
2851            impl SmlSerialize for $t {
2852                #[inline]
2853                fn to_sml_value(&self) -> Value { Value::Int(*self as i64) }
2854            }
2855            impl SmlDeserialize for $t {
2856                #[inline]
2857                fn from_sml_value(v: &Value) -> Result<Self, String> {
2858                    match v {
2859                        Value::Int(i) => <$t>::try_from(*i)
2860                            .map_err(|_| format!("整数 {i} 超出 {} 范围", stringify!($t))),
2861                        Value::Float(f)
2862                            if f.fract() == 0.0
2863                                && *f >= <$t>::MIN as f64
2864                                && *f <= <$t>::MAX as f64 => Ok(*f as $t),
2865                        Value::Float(f) => Err(format!("期望整数,实际为小数 {f}")),
2866                        other => Err(format!("期望整数,实际为 {}", describe_value(other))),
2867                    }
2868                }
2869            }
2870        )*};
2871    }
2872    impl_int!(i8, i16, i32, i64, isize, u8, u16, u32, usize);
2873
2874    impl SmlSerialize for u64 {
2875        #[inline]
2876        fn to_sml_value(&self) -> Value {
2877            i64::try_from(*self).map(Value::Int).unwrap_or_else(|_| Value::Float(*self as f64))
2878        }
2879    }
2880    impl SmlDeserialize for u64 {
2881        #[inline]
2882        fn from_sml_value(v: &Value) -> Result<Self, String> {
2883            match v {
2884                Value::Int(i) => u64::try_from(*i).map_err(|_| format!("整数 {i} 为负数,超出 u64 范围")),
2885                Value::Float(f) if f.fract() == 0.0 && *f >= 0.0 => Ok(*f as u64),
2886                Value::Float(f) => Err(format!("期望非负整数,实际为 {f}")),
2887                other => Err(format!("期望整数,实际为 {}", describe_value(other))),
2888            }
2889        }
2890    }
2891
2892    macro_rules! impl_big {
2893        ($($t:ty),* $(,)?) => {$(
2894            impl SmlSerialize for $t {
2895                #[inline]
2896                fn to_sml_value(&self) -> Value {
2897                    i64::try_from(*self).map(Value::Int).unwrap_or_else(|_| Value::Float(*self as f64))
2898                }
2899            }
2900            impl SmlDeserialize for $t {
2901                #[inline]
2902                fn from_sml_value(v: &Value) -> Result<Self, String> {
2903                    match v {
2904                        Value::Int(i) => Ok(*i as $t),
2905                        Value::Float(f) if f.fract() == 0.0 => Ok(*f as $t),
2906                        Value::Float(f) => Err(format!("期望整数,实际为小数 {f}")),
2907                        other => Err(format!("期望整数,实际为 {}", describe_value(other))),
2908                    }
2909                }
2910            }
2911        )*};
2912    }
2913    impl_big!(i128, u128);
2914
2915    macro_rules! impl_float {
2916        ($($t:ty),* $(,)?) => {$(
2917            impl SmlSerialize for $t {
2918                #[inline]
2919                fn to_sml_value(&self) -> Value { Value::Float(*self as f64) }
2920            }
2921            impl SmlDeserialize for $t {
2922                #[inline]
2923                fn from_sml_value(v: &Value) -> Result<Self, String> {
2924                    match v {
2925                        Value::Int(i) => Ok(*i as $t),
2926                        Value::Float(f) => Ok(*f as $t),
2927                        other => Err(format!("期望数字,实际为 {}", describe_value(other))),
2928                    }
2929                }
2930            }
2931        )*};
2932    }
2933    impl_float!(f32, f64);
2934
2935    impl SmlSerialize for char {
2936        #[inline]
2937        fn to_sml_value(&self) -> Value {
2938            Value::Str(self.to_string())
2939        }
2940    }
2941    impl SmlDeserialize for char {
2942        #[inline]
2943        fn from_sml_value(v: &Value) -> Result<Self, String> {
2944            match v {
2945                Value::Str(s) => {
2946                    let mut it = s.chars();
2947                    match (it.next(), it.next()) {
2948                        (Some(c), None) => Ok(c),
2949                        _ => Err(format!("期望单个字符,实际为 `{s}`")),
2950                    }
2951                }
2952                other => Err(format!("期望字符串,实际为 {}", describe_value(other))),
2953            }
2954        }
2955    }
2956
2957    impl SmlSerialize for String {
2958        #[inline]
2959        fn to_sml_value(&self) -> Value {
2960            Value::Str(self.clone())
2961        }
2962    }
2963    impl SmlDeserialize for String {
2964        #[inline]
2965        fn from_sml_value(v: &Value) -> Result<Self, String> {
2966            match v {
2967                Value::Str(s) => Ok(s.clone()),
2968                other => Err(format!("期望字符串,实际为 {}", describe_value(other))),
2969            }
2970        }
2971    }
2972
2973    impl SmlSerialize for str {
2974        #[inline]
2975        fn to_sml_value(&self) -> Value {
2976            Value::Str(self.to_string())
2977        }
2978    }
2979
2980    impl SmlSerialize for &str {
2981        #[inline]
2982        fn to_sml_value(&self) -> Value {
2983            Value::Str(self.to_string())
2984        }
2985    }
2986
2987    impl SmlSerialize for () {
2988        #[inline]
2989        fn to_sml_value(&self) -> Value {
2990            Value::Null
2991        }
2992    }
2993    impl SmlDeserialize for () {
2994        #[inline]
2995        fn from_sml_value(v: &Value) -> Result<Self, String> {
2996            match v {
2997                Value::Null => Ok(()),
2998                other => Err(format!("期望 null,实际为 {}", describe_value(other))),
2999            }
3000        }
3001    }
3002
3003    impl SmlSerialize for Value {
3004        #[inline]
3005        fn to_sml_value(&self) -> Value {
3006            self.clone()
3007        }
3008    }
3009    impl SmlDeserialize for Value {
3010        #[inline]
3011        fn from_sml_value(v: &Value) -> Result<Self, String> {
3012            Ok(v.clone())
3013        }
3014    }
3015
3016    impl<T: SmlSerialize> SmlSerialize for Option<T> {
3017        #[inline]
3018        fn to_sml_value(&self) -> Value {
3019            match self {
3020                Some(v) => v.to_sml_value(),
3021                None => Value::Null,
3022            }
3023        }
3024    }
3025    impl<T: SmlDeserialize> SmlDeserialize for Option<T> {
3026        #[inline]
3027        fn from_sml_value(v: &Value) -> Result<Self, String> {
3028            match v {
3029                Value::Null => Ok(None),
3030                other => Ok(Some(T::from_sml_value(other)?)),
3031            }
3032        }
3033    }
3034
3035    impl<T: SmlSerialize> SmlSerialize for Vec<T> {
3036        #[inline]
3037        fn to_sml_value(&self) -> Value {
3038            Value::Array(self.iter().map(SmlSerialize::to_sml_value).collect())
3039        }
3040    }
3041    impl<T: SmlDeserialize> SmlDeserialize for Vec<T> {
3042        #[inline]
3043        fn from_sml_value(v: &Value) -> Result<Self, String> {
3044            match v {
3045                Value::Array(a) => a.iter().map(SmlDeserialize::from_sml_value).collect(),
3046                other => Err(format!("期望数组,实际为 {}", describe_value(other))),
3047            }
3048        }
3049    }
3050
3051    impl<T: SmlSerialize> SmlSerialize for Box<T> {
3052        #[inline]
3053        fn to_sml_value(&self) -> Value {
3054            (**self).to_sml_value()
3055        }
3056    }
3057    impl<T: SmlDeserialize> SmlDeserialize for Box<T> {
3058        #[inline]
3059        fn from_sml_value(v: &Value) -> Result<Self, String> {
3060            Ok(Box::new(T::from_sml_value(v)?))
3061        }
3062    }
3063
3064    impl<V: SmlSerialize> SmlSerialize for BTreeMap<String, V> {
3065        #[inline]
3066        fn to_sml_value(&self) -> Value {
3067            Value::Object(
3068                self.iter()
3069                    .map(|(k, v)| (k.clone(), v.to_sml_value()))
3070                    .collect(),
3071            )
3072        }
3073    }
3074    impl<V: SmlDeserialize> SmlDeserialize for BTreeMap<String, V> {
3075        #[inline]
3076        fn from_sml_value(v: &Value) -> Result<Self, String> {
3077            match v {
3078                Value::Object(m) => {
3079                    let mut out = BTreeMap::new();
3080                    for (k, val) in m {
3081                        out.insert(k.clone(), V::from_sml_value(val)?);
3082                    }
3083                    Ok(out)
3084                }
3085                other => Err(format!("期望块(object),实际为 {}", describe_value(other))),
3086            }
3087        }
3088    }
3089
3090    impl<V: SmlSerialize> SmlSerialize for HashMap<String, V> {
3091        #[inline]
3092        fn to_sml_value(&self) -> Value {
3093            Value::Object(
3094                self.iter()
3095                    .map(|(k, v)| (k.clone(), v.to_sml_value()))
3096                    .collect(),
3097            )
3098        }
3099    }
3100    impl<V: SmlDeserialize> SmlDeserialize for HashMap<String, V> {
3101        #[inline]
3102        fn from_sml_value(v: &Value) -> Result<Self, String> {
3103            match v {
3104                Value::Object(m) => {
3105                    let mut out = HashMap::new();
3106                    for (k, val) in m {
3107                        out.insert(k.clone(), V::from_sml_value(val)?);
3108                    }
3109                    Ok(out)
3110                }
3111                other => Err(format!("期望块(object),实际为 {}", describe_value(other))),
3112            }
3113        }
3114    }
3115}
3116
3117// ---------------------------------------------------------------------------
3118// 测试
3119// ---------------------------------------------------------------------------
3120
3121#[cfg(test)]
3122mod tests {
3123    use super::*;
3124
3125    // ---------------- version ----------------
3126
3127    #[test]
3128    fn version_defaults_to_current_when_absent() {
3129        // 既有文档没有版本声明,必须仍能解析且默认为当前版本
3130        let (v, ver) = parse_versioned("a: 1\n").unwrap();
3131        assert_eq!(ver, Version::CURRENT);
3132        assert_eq!(v.get("a"), Some(&Value::Int(1)));
3133    }
3134
3135    #[test]
3136    fn version_declared_as_v1() {
3137        let (v, ver) = parse_versioned("@version v1\na: 1\n").unwrap();
3138        assert_eq!(ver, Version::V1);
3139        assert_eq!(v.get("a"), Some(&Value::Int(1)));
3140    }
3141
3142    #[test]
3143    fn version_declaration_is_stripped_not_parsed_as_content() {
3144        // 若未剥离,`@version v1` 会被当成片段定义而解析异常
3145        let v = parse("@version v1\na: 1\n").unwrap();
3146        assert_eq!(v.get("a"), Some(&Value::Int(1)));
3147        assert!(v.get("version").is_none(), "@version 不应进入数据");
3148    }
3149
3150    #[test]
3151    fn unsupported_version_is_rejected() {
3152        let err = parse_versioned("@version v99\na: 1\n").unwrap_err();
3153        assert!(err.contains("不支持"), "应拒绝不支持的版本,got: {err}");
3154        assert!(err.contains("v99"), "错误应含版本号,got: {err}");
3155    }
3156
3157    #[test]
3158    fn conflicting_version_is_rejected() {
3159        let err = parse_versioned("@version v1\n@version v2\n").unwrap_err();
3160        // v2 尚未定义,优先报「不支持」
3161        assert!(!err.is_empty());
3162        // 两个都支持但不一致时的路径:v1 与 v1 不冲突
3163        let (_, ver) = parse_versioned("@version v1\n@version v1\n").unwrap();
3164        assert_eq!(ver, Version::V1, "重复但一致的声明应被接受");
3165    }
3166
3167    #[test]
3168    fn version_is_reserved_as_fragment_name() {
3169        let err = parse("@version { x: 1 }\n").unwrap_err();
3170        assert!(err.contains("保留") || err.contains("版本声明"), "got: {err}");
3171    }
3172
3173    #[test]
3174    fn version_works_with_include() {
3175        let d = tmpdir("version");
3176        std::fs::write(d.join("p.sml"), "@version v1\nb: 2\n").unwrap();
3177        std::fs::write(d.join("main.sml"), "@version v1\ninclude \"p.sml\"\n").unwrap();
3178        let (v, ver) = parse_file_versioned(d.join("main.sml")).unwrap();
3179        assert_eq!(ver, Version::V1);
3180        assert_eq!(v.get("b"), Some(&Value::Int(2)), "版本与 include 应协同");
3181        let _ = std::fs::remove_dir_all(&d);
3182    }
3183
3184    #[test]
3185    fn version_display_matches_name() {
3186        assert_eq!(Version::V1.name(), "v1");
3187        assert_eq!(format!("{}", Version::V1), "v1");
3188    }
3189
3190    // ---------------- include ----------------
3191
3192    /// 在临时目录下建文件,返回目录句柄(drop 时自动清理)
3193    fn tmpdir(tag: &str) -> std::path::PathBuf {
3194        let mut d = std::env::temp_dir();
3195        d.push(format!("sml_test_{tag}_{}", std::process::id()));
3196        let _ = std::fs::remove_dir_all(&d);
3197        std::fs::create_dir_all(&d).expect("create tmpdir");
3198        d
3199    }
3200
3201    #[test]
3202    fn include_inlines_external_file() {
3203        let d = tmpdir("inline");
3204        std::fs::write(d.join("part.sml"), "port: 8080\n").unwrap();
3205        std::fs::write(d.join("main.sml"), "host: local\ninclude \"part.sml\"\n").unwrap();
3206
3207        let v = parse_file(d.join("main.sml")).unwrap();
3208        assert_eq!(v.get("host").unwrap().as_str(), Some("local"));
3209        assert_eq!(v.get("port"), Some(&Value::Int(8080)));
3210        let _ = std::fs::remove_dir_all(&d);
3211    }
3212
3213    #[test]
3214    fn include_at_prefix_is_equivalent() {
3215        let d = tmpdir("at");
3216        std::fs::write(d.join("p.sml"), "b: 2\n").unwrap();
3217        std::fs::write(d.join("m.sml"), "@include \"p.sml\"\n").unwrap();
3218        let v = parse_file(d.join("m.sml")).unwrap();
3219        assert_eq!(v.get("b"), Some(&Value::Int(2)));
3220        let _ = std::fs::remove_dir_all(&d);
3221    }
3222
3223    #[test]
3224    fn include_resolves_relative_to_including_file() {
3225        // 关键:相对路径按「被包含文件自身目录」解析,而非进程工作目录
3226        let d = tmpdir("nested");
3227        std::fs::create_dir_all(d.join("sub")).unwrap();
3228        std::fs::write(d.join("sub/leaf.sml"), "leaf: yes\n").unwrap();
3229        // mid 在根,include sub/mid2;mid2 在 sub 内,include leaf.sml(相对 sub)
3230        std::fs::write(d.join("sub/mid2.sml"), "include \"leaf.sml\"\n").unwrap();
3231        std::fs::write(d.join("main.sml"), "include \"sub/mid2.sml\"\n").unwrap();
3232
3233        let v = parse_file(d.join("main.sml")).unwrap();
3234        assert_eq!(
3235            v.get("leaf").unwrap().as_str(),
3236            Some("yes"),
3237            "嵌套 include 的路径应相对各自所在目录解析"
3238        );
3239        let _ = std::fs::remove_dir_all(&d);
3240    }
3241
3242    #[test]
3243    fn include_inside_block_injects_fields() {
3244        // 文本内联语义:可在块内注入一组字段
3245        let d = tmpdir("block");
3246        std::fs::write(d.join("fields.sml"), "region: cn-north-1\nzone: a\n").unwrap();
3247        std::fs::write(d.join("main.sml"), "server web {\ninclude \"fields.sml\"\nport: 8080\n}\n").unwrap();
3248
3249        let v = parse_file(d.join("main.sml")).unwrap();
3250        let server = v.get("server").expect("应有 server 块");
3251        assert_eq!(server.get("region").unwrap().as_str(), Some("cn-north-1"));
3252        assert_eq!(server.get("zone").unwrap().as_str(), Some("a"));
3253        assert_eq!(server.get("port"), Some(&Value::Int(8080)));
3254        let _ = std::fs::remove_dir_all(&d);
3255    }
3256
3257    #[test]
3258    fn include_detects_cycles() {
3259        let d = tmpdir("cycle");
3260        std::fs::write(d.join("a.sml"), "include \"b.sml\"\n").unwrap();
3261        std::fs::write(d.join("b.sml"), "include \"a.sml\"\n").unwrap();
3262        let err = parse_file(d.join("a.sml")).unwrap_err();
3263        assert!(err.contains("循环引用"), "应报循环引用,got: {err}");
3264        let _ = std::fs::remove_dir_all(&d);
3265    }
3266
3267    #[test]
3268    fn include_missing_file_is_error() {
3269        let d = tmpdir("missing");
3270        std::fs::write(d.join("m.sml"), "include \"nope.sml\"\n").unwrap();
3271        let err = parse_file(d.join("m.sml")).unwrap_err();
3272        assert!(err.contains("nope.sml"), "错误应含缺失文件名,got: {err}");
3273        let _ = std::fs::remove_dir_all(&d);
3274    }
3275
3276    #[test]
3277    fn hash_in_quoted_string_is_not_a_comment() {
3278        // 引号内的 # 不应被当成注释,否则 `include "a#b.sml"` 会被截断
3279        assert_eq!(strip_line_comment("k: \"a#b\""), "k: \"a#b\"");
3280        assert_eq!(strip_line_comment("k: v # comment"), "k: v ");
3281    }
3282
3283    #[test]
3284    fn include_line_is_not_confused_with_key_named_include() {
3285        // `key: include` 是指令吗?不是——前面有 key 与冒号
3286        assert_eq!(include_target("key: include"), None);
3287        assert_eq!(include_target("include \"a.sml\""), Some("a.sml".into()));
3288        assert_eq!(include_target("@include \"a.sml\""), Some("a.sml".into()));
3289        assert_eq!(include_target("# include \"a.sml\""), None, "注释行不生效");
3290    }
3291
3292    // ---------------- 邮箱 / 裸词中的 @ ----------------
3293
3294    #[test]
3295    fn email_in_bare_word_survives() {
3296        // 回归:裸词中的 `@` 曾被切成 At token,导致邮箱被截断为 `a`
3297        let v = parse("to: a@b.c\nfrom: \"sal <sal@mail.swebase.cn>\"\n").unwrap();
3298        assert_eq!(v.get("to").unwrap().as_str(), Some("a@b.c"), "got: {v:?}");
3299        assert_eq!(
3300            v.get("from").unwrap().as_str(),
3301            Some("sal <sal@mail.swebase.cn>"),
3302            "got: {v:?}"
3303        );
3304    }
3305
3306    #[test]
3307    fn email_roundtrips_through_to_sml() {
3308        let v = Value::Object(BTreeMap::from([(
3309            "to".to_string(),
3310            Value::Str("SALflake@qq.com".into()),
3311        )]));
3312        let back = parse(&to_sml(&v)).unwrap();
3313        assert_eq!(back, v, "邮箱必须能往返,got:\n{}", to_sml(&v));
3314    }
3315
3316    #[test]
3317    fn fragment_definition_still_works() {
3318        // 词首的 `@` 仍是片段定义标记,不能被上面的修改破坏。
3319        // 注:SML 的片段继承用法是「定义后作为值引用」(`k: &base`);
3320        // 块内裸写 `&base` 会被当作键,不属于本用例覆盖范围。
3321        let v = parse("@base { region: cn }\nregion: &base\n").unwrap();
3322        assert_eq!(
3323            v.get("region").unwrap().get("region").unwrap().as_str(),
3324            Some("cn"),
3325            "片段引用应展开为定义的内容,got: {v:?}"
3326        );
3327    }
3328
3329    // ---------------- 顶层数组 / 对象(与 to_sml 对称)----------------
3330
3331    #[test]
3332    fn toplevel_array_roundtrips() {
3333        // 回归:to_sml 能输出顶层数组,但 parse 曾只认键值块,
3334        // 导致「能写不能读」("期望键, 得 LBrack")。
3335        let v = Value::Array(vec![
3336            Value::Object(BTreeMap::from([
3337                ("ts".to_string(), Value::Str("2026-01-01".into())),
3338                ("to".to_string(), Value::Str("a@b.c".into())),
3339            ])),
3340            Value::Object(BTreeMap::from([
3341                ("ts".to_string(), Value::Str("2026-01-02".into())),
3342                ("to".to_string(), Value::Str("x@y.z".into())),
3343            ])),
3344        ]);
3345        let text = to_sml(&v);
3346        let back = parse(&text).unwrap();
3347        assert_eq!(back, v, "顶层对象数组必须能往返,got text:\n{text}");
3348    }
3349
3350    #[test]
3351    fn toplevel_array_of_scalars_roundtrips() {
3352        let v = Value::Array(vec![
3353            Value::Int(1),
3354            Value::Str("two".into()),
3355            Value::Bool(true),
3356        ]);
3357        let back = parse(&to_sml(&v)).unwrap();
3358        assert_eq!(back, v, "顶层标量数组必须能往返");
3359    }
3360
3361    #[test]
3362    fn toplevel_object_block_roundtrips() {
3363        let mut m = BTreeMap::new();
3364        m.insert("k".to_string(), Value::Int(1));
3365        let v = Value::Object(m);
3366        let back = parse(&to_sml(&v)).unwrap();
3367        assert_eq!(back, v, "顶层对象块必须能往返");
3368    }
3369
3370    #[test]
3371    fn toplevel_empty_array_roundtrips() {
3372        let v = Value::Array(vec![]);
3373        let back = parse(&to_sml(&v)).unwrap();
3374        assert_eq!(back, v, "空数组必须能往返");
3375    }
3376
3377    // ---------------- serde ----------------
3378
3379    #[cfg(feature = "serde")]
3380    #[test]
3381    fn serde_roundtrip_preserves_shape() {
3382        let v = parse("name: John\nage: 27\ntags: [a b]\nnested { k: v }\n").unwrap();
3383        let json = serde_json::to_string(&v).unwrap();
3384        // 自然形状:字符串就是字符串,数字就是数字,而非 {"Int":27}
3385        assert!(json.contains("\"name\":\"John\""), "got: {json}");
3386        assert!(json.contains("\"age\":27"), "got: {json}");
3387        assert!(json.contains("\"tags\":[\"a\",\"b\"]"), "got: {json}");
3388        assert!(json.contains("\"nested\":{\"k\":\"v\"}"), "got: {json}");
3389
3390        let back: Value = serde_json::from_str(&json).unwrap();
3391        assert_eq!(back, v, "serde 往返应还原原值");
3392    }
3393
3394    #[cfg(feature = "serde")]
3395    #[test]
3396    fn serde_deserializes_json_into_value() {
3397        let v: Value = serde_json::from_str(r#"{"s":"x","i":5,"f":1.5,"b":true,"n":null,"a":[1,2]}"#).unwrap();
3398        assert_eq!(v.get("s").unwrap().as_str(), Some("x"));
3399        assert_eq!(v.get("i"), Some(&Value::Int(5)));
3400        assert_eq!(v.get("f"), Some(&Value::Float(1.5)));
3401        assert_eq!(v.get("b"), Some(&Value::Bool(true)));
3402        assert_eq!(v.get("n"), Some(&Value::Null));
3403        assert!(matches!(v.get("a"), Some(Value::Array(a)) if a.len() == 2));
3404    }
3405
3406    #[test]
3407    fn nested_array_inside_object_inside_array_survives_roundtrip() {
3408        // 回归测试:数组元素是对象、对象里又有数组(如配置的条目列表)。
3409        // dump_inline 曾把嵌套数组缩略成 [..],导致 chunks 丢成 [".."]。
3410        let mut item = BTreeMap::new();
3411        item.insert("path".to_string(), Value::Str("a.txt".into()));
3412        item.insert(
3413            "chunks".to_string(),
3414            Value::Array(vec![
3415                Value::Str("c1".into()),
3416                Value::Str("c2".into()),
3417            ]),
3418        );
3419        let mut root = BTreeMap::new();
3420        root.insert(
3421            "entries".to_string(),
3422            Value::Array(vec![Value::Object(item)]),
3423        );
3424        let text = to_sml(&Value::Object(root));
3425        assert!(!text.contains("[..]"), "嵌套数组不得被缩略: {text}");
3426
3427        let back = parse(&text).unwrap();
3428        let chunks = back.get("entries").and_then(|e| match e {
3429            Value::Array(a) => a.first(),
3430            _ => None,
3431        });
3432        let chunks = match chunks {
3433            Some(Value::Object(m)) => m.get("chunks"),
3434            _ => None,
3435        };
3436        match chunks {
3437            Some(Value::Array(a)) => {
3438                assert_eq!(a.len(), 2, "两个块都应保留: {text}");
3439                assert_eq!(
3440                    a.iter().filter_map(|c| c.as_str()).collect::<Vec<_>>(),
3441                    vec!["c1", "c2"]
3442                );
3443            }
3444            other => panic!("chunks 应解析为数组,实际 {other:?}"),
3445        }
3446    }
3447
3448    #[test]
3449    fn utf8_in_quoted_string_survives_roundtrip() {
3450        // 回归测试:tokenizer 曾按字节 `as char` 逐个处理,
3451        // 把 UTF-8 多字节字符拆成 Latin-1 字符,导致
3452        // `"修复若干问题"` 解析后变成双编码乱码。
3453        let v = parse(r#"note: "修复若干问题""#).unwrap();
3454        assert_eq!(
3455            v.get("note").and_then(|x| x.as_str()),
3456            Some("修复若干问题"),
3457            "引号串中的中文不应被破坏"
3458        );
3459        // 裸词中文同样不能破坏
3460        let v2 = parse("region: 华北").unwrap();
3461        assert_eq!(v2.get("region").and_then(|x| x.as_str()), Some("华北"));
3462        // 转义 \u 序列
3463        let v3 = parse(r#"k: "\u{4fee}\u{590d}""#).unwrap();
3464        assert_eq!(v3.get("k").and_then(|x| x.as_str()), Some("修复"));
3465    }
3466
3467    #[test]
3468    fn parse_basic() {
3469        let text = "firstName: John\nage: 27\nisAlive: true\nspouse: null\n";
3470        let v = parse(text).unwrap();
3471        assert_eq!(v.get("firstName"), Some(&Value::Str("John".into())));
3472        assert_eq!(v.get("age"), Some(&Value::Int(27)));
3473        assert_eq!(v.get("isAlive"), Some(&Value::Bool(true)));
3474        assert_eq!(v.get("spouse"), Some(&Value::Null));
3475    }
3476
3477    #[test]
3478    fn parse_nested() {
3479        let text = "address:\n{\n    streetAddress: \"21 2nd Street\"\n    state: NY\n}\n";
3480        let v = parse(text).unwrap();
3481        assert_eq!(
3482            v.get("address.streetAddress"),
3483            Some(&Value::Str("21 2nd Street".into()))
3484        );
3485        assert_eq!(v.get("address.state"), Some(&Value::Str("NY".into())));
3486    }
3487
3488    #[test]
3489    fn parse_array() {
3490        let text = "phoneNumbers:\n[\n    { type: home }\n    { type: office }\n]\n";
3491        let v = parse(text).unwrap();
3492        if let Some(Value::Array(a)) = v.get("phoneNumbers") {
3493            assert_eq!(a.len(), 2);
3494            assert_eq!(a[0].get("type"), Some(&Value::Str("home".into())));
3495        } else {
3496            panic!("not array");
3497        }
3498    }
3499
3500    #[test]
3501    fn parse_fragment() {
3502        let text = "@base { region: cn-north-1 }\nserver web { &base }\n";
3503        let v = parse(text).unwrap();
3504        // &base 展开为字段 (键名 "&base", 值=片段对象), 与 Lua 实现一致
3505        assert_eq!(
3506            v.get("server.&base.region"),
3507            Some(&Value::Str("cn-north-1".into()))
3508        );
3509        assert_eq!(v.get("server.__type"), Some(&Value::Str("server".into())));
3510        assert_eq!(v.get("server.__name"), Some(&Value::Str("web".into())));
3511    }
3512
3513    #[test]
3514    fn roundtrip() {
3515        let text = "name: myapp\nport: 8080\nflags: [ a b c ]\n";
3516        let v = parse(text).unwrap();
3517        let out = to_sml(&v);
3518        let v2 = parse(&out).unwrap();
3519        assert_eq!(v, v2);
3520    }
3521
3522    #[test]
3523    fn env_inline() {
3524        // Rust 2024 edition 下 set_var 为 unsafe(1.85+)
3525        unsafe { std::env::set_var("SML_TEST_VAR", "hello") };
3526        let text = "greeting: $env.SML_TEST_VAR\n";
3527        let v = parse(text).unwrap();
3528        assert_eq!(v.get("greeting"), Some(&Value::Str("hello".into())));
3529    }
3530
3531    #[test]
3532    fn c_abi_json_bridge() {
3533        let text = "name: John\nage: 27\n";
3534        let v = parse(text).unwrap();
3535        let j = jsonify(&v);
3536        assert!(j.contains("\"name\":\"John\""));
3537        let back = json_to_value(&j).unwrap();
3538        assert_eq!(back, v);
3539    }
3540}