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