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#[cfg_attr(edge2024, unsafe(no_mangle))]
1428#[cfg_attr(not(edge2024), no_mangle)]
1429pub extern "C" fn sml_parse(text: *const c_char) -> *mut c_char {
1430    if text.is_null() {
1431        return ptr::null_mut();
1432    }
1433    let t = unsafe { std::ffi::CStr::from_ptr(text) }.to_string_lossy().into_owned();
1434    match parse(&t) {
1435        Ok(v) => cstr(&jsonify(&v)),
1436        Err(_) => ptr::null_mut(),
1437    }
1438}
1439
1440/// sml_dump(json) -> 接受 JSON 字符串, 序列化为 SML; 调用方 sml_free
1441#[cfg_attr(edge2024, unsafe(no_mangle))]
1442#[cfg_attr(not(edge2024), no_mangle)]
1443pub extern "C" fn sml_dump(json: *const c_char) -> *mut c_char {
1444    if json.is_null() {
1445        return ptr::null_mut();
1446    }
1447    let j = unsafe { std::ffi::CStr::from_ptr(json) }.to_string_lossy().into_owned();
1448    match json_to_value(&j) {
1449        Some(v) => cstr(&to_sml(&v)),
1450        None => ptr::null_mut(),
1451    }
1452}
1453
1454/// sml_free(p): 释放由 sml_parse / sml_dump 返回的字符串
1455#[cfg_attr(edge2024, unsafe(no_mangle))]
1456#[cfg_attr(not(edge2024), no_mangle)]
1457pub unsafe extern "C" fn sml_free(p: *mut c_char) {
1458    if !p.is_null() {
1459        drop(unsafe { std::ffi::CString::from_raw(p) });
1460    }
1461}
1462
1463/// sml_version() -> 版本字符串 (调用方 sml_free)
1464#[cfg_attr(edge2024, unsafe(no_mangle))]
1465#[cfg_attr(not(edge2024), no_mangle)]
1466pub extern "C" fn sml_version() -> *mut c_char {
1467    cstr(concat!("sml ", env!("CARGO_PKG_VERSION")))
1468}
1469
1470// ---------------------------------------------------------------------------
1471// 内部: JSON <-> Value (供 C-ABI 便捷桥)
1472// ---------------------------------------------------------------------------
1473
1474fn jsonify(v: &Value) -> String {
1475    fn esc(s: &str) -> String {
1476        s.replace('\\', "\\\\").replace('"', "\\\"")
1477    }
1478    match v {
1479        Value::Null => "null".into(),
1480        Value::Bool(b) => b.to_string(),
1481        Value::Int(i) => i.to_string(),
1482        Value::Float(f) => f.to_string(),
1483        Value::Str(s) => format!("\"{}\"", esc(s)),
1484        Value::Array(a) => {
1485            let parts: Vec<String> = a.iter().map(jsonify).collect();
1486            format!("[{}]", parts.join(","))
1487        }
1488        Value::Object(m) => {
1489            let parts: Vec<String> = m
1490                .iter()
1491                .map(|(k, val)| format!("\"{}\":{}", esc(k), jsonify(val)))
1492                .collect();
1493            format!("{{{}}}", parts.join(","))
1494        }
1495    }
1496}
1497
1498fn json_to_value(s: &str) -> Option<Value> {
1499    let bytes = s.as_bytes();
1500    let mut i = 0;
1501    let _n = bytes.len();
1502    let mut skip_ws = |b: &[u8], i: &mut usize| {
1503        while *i < b.len() && matches!(b[*i], b' ' | b'\t' | b'\n' | b'\r') {
1504            *i += 1;
1505        }
1506    };
1507    let mut parse_str = |b: &[u8], i: &mut usize| -> Option<String> {
1508        skip_ws(b, i);
1509        if *i >= b.len() || b[*i] != b'"' {
1510            return None;
1511        }
1512        *i += 1;
1513        let mut out = String::new();
1514        while *i < b.len() {
1515            let c = b[*i];
1516            if c == b'"' {
1517                *i += 1;
1518                return Some(out);
1519            }
1520            if c == b'\\' && *i + 1 < b.len() {
1521                *i += 1;
1522                let e = b[*i];
1523                out.push(match e {
1524                    b'n' => '\n',
1525                    b't' => '\t',
1526                    b'r' => '\r',
1527                    b'"' => '"',
1528                    b'\\' => '\\',
1529                    _ => e as char,
1530                });
1531            } else {
1532                out.push(c as char);
1533            }
1534            *i += 1;
1535        }
1536        None
1537    };
1538    fn parse_val_impl(
1539        b: &[u8],
1540        i: &mut usize,
1541        s: &str,
1542        parse_str: &dyn Fn(&[u8], &mut usize) -> Option<String>,
1543    ) -> Option<Value> {
1544        let mut skip_ws = |b: &[u8], i: &mut usize| {
1545            while *i < b.len() && matches!(b[*i], b' ' | b'\t' | b'\n' | b'\r') {
1546                *i += 1;
1547            }
1548        };
1549        skip_ws(b, i);
1550        if *i >= b.len() {
1551            return None;
1552        }
1553        match b[*i] {
1554            b'{' => {
1555                *i += 1;
1556                let mut m = BTreeMap::new();
1557                skip_ws(b, i);
1558                if *i < b.len() && b[*i] == b'}' {
1559                    *i += 1;
1560                    return Some(Value::Object(m));
1561                }
1562                loop {
1563                    skip_ws(b, i);
1564                    let k = parse_str(b, i)?;
1565                    skip_ws(b, i);
1566                    if *i < b.len() && b[*i] == b':' {
1567                        *i += 1;
1568                    }
1569                    let v = parse_val_impl(b, i, s, parse_str)?;
1570                    m.insert(k, v);
1571                    skip_ws(b, i);
1572                    if *i < b.len() && b[*i] == b',' {
1573                        *i += 1;
1574                    } else if *i < b.len() && b[*i] == b'}' {
1575                        *i += 1;
1576                        break;
1577                    }
1578                }
1579                Some(Value::Object(m))
1580            }
1581            b'[' => {
1582                *i += 1;
1583                let mut a = Vec::new();
1584                skip_ws(b, i);
1585                if *i < b.len() && b[*i] == b']' {
1586                    *i += 1;
1587                    return Some(Value::Array(a));
1588                }
1589                loop {
1590                    a.push(parse_val_impl(b, i, s, parse_str)?);
1591                    skip_ws(b, i);
1592                    if *i < b.len() && b[*i] == b',' {
1593                        *i += 1;
1594                    } else if *i < b.len() && b[*i] == b']' {
1595                        *i += 1;
1596                        break;
1597                    }
1598                }
1599                Some(Value::Array(a))
1600            }
1601            b'"' => parse_str(b, i).map(Value::Str),
1602            b't' => {
1603                if s[*i..].starts_with("true") {
1604                    *i += 4;
1605                    Some(Value::Bool(true))
1606                } else {
1607                    None
1608                }
1609            }
1610            b'f' => {
1611                if s[*i..].starts_with("false") {
1612                    *i += 5;
1613                    Some(Value::Bool(false))
1614                } else {
1615                    None
1616                }
1617            }
1618            b'n' => {
1619                if s[*i..].starts_with("null") {
1620                    *i += 4;
1621                    Some(Value::Null)
1622                } else {
1623                    None
1624                }
1625            }
1626            _ => {
1627                let start = *i;
1628                while *i < b.len()
1629                    && (b[*i].is_ascii_digit()
1630                        || matches!(b[*i], b'-' | b'+' | b'.' | b'e' | b'E'))
1631                {
1632                    *i += 1;
1633                }
1634                let tok = s[start..*i].to_string();
1635                if let Ok(iv) = tok.parse::<i64>() {
1636                    Some(Value::Int(iv))
1637                } else if let Ok(fv) = tok.parse::<f64>() {
1638                    Some(Value::Float(fv))
1639                } else {
1640                    None
1641                }
1642            }
1643        }
1644    }
1645    parse_val_impl(bytes, &mut i, s, &parse_str)
1646}
1647
1648// ---------------------------------------------------------------------------
1649// serde 支持(可选 feature:`serde`)
1650//
1651// 1) `Value` 实现 `Serialize`/`Deserialize`(手写而非 `#[derive]`:derive 会把
1652//    枚举表示为外部标签形式 Value::Int(5) -> {"Int":5},而配置场景要自然形状
1653//    5)。手写后 SML 的 Value 与 JSON/TOML/YAML 数据形状一致,可经任意 serde
1654//    后端进出。
1655// 2) `sml::serde::{from_str, from_value, to_value, to_string}`:serde 桥。
1656//    任何 `#[derive(serde::Serialize / Deserialize)]` 类型都能像 toml-rs 一样
1657//    一键从 SML 文本反序列化 / 序列化为 SML(枚举沿用 `__type` 约定)。
1658//
1659// 不启用该 feature 时 crate 保持零依赖。
1660// ---------------------------------------------------------------------------
1661
1662#[cfg(feature = "serde")]
1663pub mod serde {
1664    use super::Value;
1665    use ::serde::de::{self, MapAccess, SeqAccess, Visitor};
1666    use ::serde::ser::{
1667        SerializeMap, SerializeSeq, SerializeStruct, SerializeStructVariant,
1668        SerializeTuple, SerializeTupleStruct, SerializeTupleVariant,
1669    };
1670    use ::serde::{Deserialize, Deserializer, Serialize, Serializer};
1671    use ::std::collections::BTreeMap;
1672    use ::std::fmt;
1673
1674    /// serde 错误类型(自定义消息,实现 ser/de 两个 Error trait)
1675    type Error = ::serde::de::value::Error;
1676
1677    fn type_err(v: &Value, expected: &str) -> Error {
1678        de::Error::custom(format!(
1679            "期望 {expected},实际为 {}",
1680            super::__private::describe_value(v)
1681        ))
1682    }
1683
1684    impl Serialize for Value {
1685        fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
1686        where
1687            S: Serializer,
1688        {
1689            match self {
1690                Value::Null => serializer.serialize_unit(),
1691                Value::Bool(b) => serializer.serialize_bool(*b),
1692                Value::Int(i) => serializer.serialize_i64(*i),
1693                Value::Float(f) => serializer.serialize_f64(*f),
1694                Value::Str(s) => serializer.serialize_str(s),
1695                // Vec<Value> / 逐项委托,递归依赖 Value 自身的 impl
1696                Value::Array(a) => a.serialize(serializer),
1697                Value::Object(m) => {
1698                    let mut map = serializer.serialize_map(Some(m.len()))?;
1699                    for (k, v) in m {
1700                        map.serialize_entry(k, v)?;
1701                    }
1702                    map.end()
1703                }
1704            }
1705        }
1706    }
1707
1708    impl<'de> Deserialize<'de> for Value {
1709        fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
1710        where
1711            D: Deserializer<'de>,
1712        {
1713            // 交给格式自行判断类型(JSON 的数字/字符串/数组/对象都能落到对应变体)
1714            deserializer.deserialize_any(ValueVisitor)
1715        }
1716    }
1717
1718    struct ValueVisitor;
1719
1720    impl<'de> Visitor<'de> for ValueVisitor {
1721        type Value = Value;
1722
1723        fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
1724            f.write_str("any valid SML/JSON value")
1725        }
1726
1727        fn visit_unit<E: de::Error>(self) -> Result<Value, E> {
1728            Ok(Value::Null)
1729        }
1730        fn visit_none<E: de::Error>(self) -> Result<Value, E> {
1731            Ok(Value::Null)
1732        }
1733        fn visit_some<D>(self, d: D) -> Result<Value, D::Error>
1734        where
1735            D: Deserializer<'de>,
1736        {
1737            Deserialize::deserialize(d)
1738        }
1739        fn visit_bool<E: de::Error>(self, v: bool) -> Result<Value, E> {
1740            Ok(Value::Bool(v))
1741        }
1742        fn visit_i64<E: de::Error>(self, v: i64) -> Result<Value, E> {
1743            Ok(Value::Int(v))
1744        }
1745        // 超出 i64 的大整数退化为 Float,避免直接报错丢失数据
1746        fn visit_u64<E: de::Error>(self, v: u64) -> Result<Value, E> {
1747            Ok(i64::try_from(v)
1748                .map(Value::Int)
1749                .unwrap_or_else(|_| Value::Float(v as f64)))
1750        }
1751        fn visit_f64<E: de::Error>(self, v: f64) -> Result<Value, E> {
1752            Ok(Value::Float(v))
1753        }
1754        fn visit_str<E: de::Error>(self, v: &str) -> Result<Value, E> {
1755            Ok(Value::Str(v.to_string()))
1756        }
1757        fn visit_string<E: de::Error>(self, v: String) -> Result<Value, E> {
1758            Ok(Value::Str(v))
1759        }
1760        fn visit_seq<A>(self, mut seq: A) -> Result<Value, A::Error>
1761        where
1762            A: SeqAccess<'de>,
1763        {
1764            let mut v = Vec::new();
1765            while let Some(x) = seq.next_element()? {
1766                v.push(x);
1767            }
1768            Ok(Value::Array(v))
1769        }
1770        fn visit_map<A>(self, mut map: A) -> Result<Value, A::Error>
1771        where
1772            A: MapAccess<'de>,
1773        {
1774            let mut m = BTreeMap::new();
1775            while let Some((k, v)) = map.next_entry::<String, Value>()? {
1776                m.insert(k, v);
1777            }
1778            Ok(Value::Object(m))
1779        }
1780    }
1781
1782    // -----------------------------------------------------------------------
1783    // serde 桥:任意 `serde::Serialize / Deserialize` 类型 <-> SML
1784    // -----------------------------------------------------------------------
1785
1786    /// 解析 SML 文本并一键反序列化到任意 serde 类型(等价于 `toml::from_str`)。
1787    ///
1788    /// ```rust
1789    /// # use serde::Deserialize;
1790    /// # #[derive(Deserialize, Debug)]
1791    /// # struct Server { host: String, port: i32 }
1792    /// let s: Server = sml::serde::from_str("host: web.example\nport: 8080\n").unwrap();
1793    /// assert_eq!(s.host, "web.example");
1794    /// ```
1795    pub fn from_str<T: de::DeserializeOwned>(text: &str) -> Result<T, String> {
1796        let value = crate::parse(text)?;
1797        from_value(value)
1798    }
1799
1800    /// 从任意 [`Value`] 反序列化到任意 serde 类型。
1801    pub fn from_value<T: de::DeserializeOwned>(value: Value) -> Result<T, String> {
1802        T::deserialize(ValueDeserializer(value)).map_err(|e| e.to_string())
1803    }
1804
1805    /// 任意 serde 类型序列化为 [`Value`](等价于 `serde_json::to_value`)。
1806    pub fn to_value<T: Serialize + ?Sized>(value: &T) -> Result<Value, String> {
1807        value.serialize(ValueSerializer).map_err(|e| e.to_string())
1808    }
1809
1810    /// 任意 serde 类型序列化为 SML 文本(等价于 `toml::to_string`)。
1811    pub fn to_string<T: Serialize + ?Sized>(value: &T) -> Result<String, String> {
1812        Ok(crate::to_sml(&to_value(value)?))
1813    }
1814
1815    // ---- Serializer: T: Serialize -> Value ----
1816
1817    struct ValueSerializer;
1818
1819    impl Serializer for ValueSerializer {
1820        type Ok = Value;
1821        type Error = Error;
1822        type SerializeSeq = SeqSerializer;
1823        type SerializeTuple = SeqSerializer;
1824        type SerializeTupleStruct = SeqSerializer;
1825        type SerializeTupleVariant = TupleVariantSerializer;
1826        type SerializeMap = MapSerializer;
1827        type SerializeStruct = MapSerializer;
1828        type SerializeStructVariant = StructVariantSerializer;
1829
1830        fn serialize_bool(self, v: bool) -> Result<Value, Error> {
1831            Ok(Value::Bool(v))
1832        }
1833        fn serialize_i8(self, v: i8) -> Result<Value, Error> {
1834            Ok(Value::Int(v as i64))
1835        }
1836        fn serialize_i16(self, v: i16) -> Result<Value, Error> {
1837            Ok(Value::Int(v as i64))
1838        }
1839        fn serialize_i32(self, v: i32) -> Result<Value, Error> {
1840            Ok(Value::Int(v as i64))
1841        }
1842        fn serialize_i64(self, v: i64) -> Result<Value, Error> {
1843            Ok(Value::Int(v))
1844        }
1845        fn serialize_u8(self, v: u8) -> Result<Value, Error> {
1846            Ok(Value::Int(v as i64))
1847        }
1848        fn serialize_u16(self, v: u16) -> Result<Value, Error> {
1849            Ok(Value::Int(v as i64))
1850        }
1851        fn serialize_u32(self, v: u32) -> Result<Value, Error> {
1852            Ok(Value::Int(v as i64))
1853        }
1854        fn serialize_u64(self, v: u64) -> Result<Value, Error> {
1855            Ok(i64::try_from(v)
1856                .map(Value::Int)
1857                .unwrap_or_else(|_| Value::Float(v as f64)))
1858        }
1859        fn serialize_f32(self, v: f32) -> Result<Value, Error> {
1860            Ok(Value::Float(v as f64))
1861        }
1862        fn serialize_f64(self, v: f64) -> Result<Value, Error> {
1863            Ok(Value::Float(v))
1864        }
1865        fn serialize_char(self, v: char) -> Result<Value, Error> {
1866            Ok(Value::Str(v.to_string()))
1867        }
1868        fn serialize_str(self, v: &str) -> Result<Value, Error> {
1869            Ok(Value::Str(v.to_string()))
1870        }
1871        fn serialize_bytes(self, v: &[u8]) -> Result<Value, Error> {
1872            Ok(Value::Array(v.iter().map(|&b| Value::Int(b as i64)).collect()))
1873        }
1874        fn serialize_none(self) -> Result<Value, Error> {
1875            Ok(Value::Null)
1876        }
1877        fn serialize_some<T: Serialize + ?Sized>(self, v: &T) -> Result<Value, Error> {
1878            v.serialize(ValueSerializer)
1879        }
1880        fn serialize_unit(self) -> Result<Value, Error> {
1881            Ok(Value::Null)
1882        }
1883        fn serialize_unit_struct(self, _name: &'static str) -> Result<Value, Error> {
1884            Ok(Value::Null)
1885        }
1886        fn serialize_unit_variant(
1887            self,
1888            _name: &'static str,
1889            _idx: u32,
1890            variant: &'static str,
1891        ) -> Result<Value, Error> {
1892            Ok(Value::Str(variant.to_string()))
1893        }
1894        fn serialize_newtype_struct<T: Serialize + ?Sized>(
1895            self,
1896            _name: &'static str,
1897            v: &T,
1898        ) -> Result<Value, Error> {
1899            v.serialize(ValueSerializer)
1900        }
1901        fn serialize_newtype_variant<T: Serialize + ?Sized>(
1902            self,
1903            _name: &'static str,
1904            _idx: u32,
1905            variant: &'static str,
1906            value: &T,
1907        ) -> Result<Value, Error> {
1908            Ok(Value::Object(BTreeMap::from([
1909                ("__type".into(), Value::Str(variant.to_string())),
1910                ("_value".into(), value.serialize(ValueSerializer)?),
1911            ])))
1912        }
1913        fn serialize_seq(self, _len: Option<usize>) -> Result<Self::SerializeSeq, Error> {
1914            Ok(SeqSerializer(Vec::new()))
1915        }
1916        fn serialize_tuple(self, len: usize) -> Result<Self::SerializeTuple, Error> {
1917            self.serialize_seq(Some(len))
1918        }
1919        fn serialize_tuple_struct(
1920            self,
1921            _name: &'static str,
1922            len: usize,
1923        ) -> Result<Self::SerializeTupleStruct, Error> {
1924            self.serialize_seq(Some(len))
1925        }
1926        fn serialize_tuple_variant(
1927            self,
1928            _name: &'static str,
1929            _idx: u32,
1930            variant: &'static str,
1931            _len: usize,
1932        ) -> Result<Self::SerializeTupleVariant, Error> {
1933            Ok(TupleVariantSerializer {
1934                variant: variant.to_string(),
1935                values: Vec::new(),
1936            })
1937        }
1938        fn serialize_map(self, _len: Option<usize>) -> Result<Self::SerializeMap, Error> {
1939            Ok(MapSerializer {
1940                map: BTreeMap::new(),
1941                key: None,
1942            })
1943        }
1944        fn serialize_struct(self, _name: &'static str, len: usize) -> Result<Self::SerializeStruct, Error> {
1945            self.serialize_map(Some(len))
1946        }
1947        fn serialize_struct_variant(
1948            self,
1949            _name: &'static str,
1950            _idx: u32,
1951            variant: &'static str,
1952            _len: usize,
1953        ) -> Result<Self::SerializeStructVariant, Error> {
1954            Ok(StructVariantSerializer {
1955                variant: variant.to_string(),
1956                map: BTreeMap::new(),
1957            })
1958        }
1959    }
1960
1961    struct SeqSerializer(Vec<Value>);
1962
1963    impl SerializeSeq for SeqSerializer {
1964        type Ok = Value;
1965        type Error = Error;
1966        fn serialize_element<T: Serialize + ?Sized>(&mut self, value: &T) -> Result<(), Error> {
1967            self.0.push(value.serialize(ValueSerializer)?);
1968            Ok(())
1969        }
1970        fn end(self) -> Result<Value, Error> {
1971            Ok(Value::Array(self.0))
1972        }
1973    }
1974    impl SerializeTuple for SeqSerializer {
1975        type Ok = Value;
1976        type Error = Error;
1977        fn serialize_element<T: Serialize + ?Sized>(&mut self, value: &T) -> Result<(), Error> {
1978            SerializeSeq::serialize_element(self, value)
1979        }
1980        fn end(self) -> Result<Value, Error> {
1981            SerializeSeq::end(self)
1982        }
1983    }
1984    impl SerializeTupleStruct for SeqSerializer {
1985        type Ok = Value;
1986        type Error = Error;
1987        fn serialize_field<T: Serialize + ?Sized>(&mut self, value: &T) -> Result<(), Error> {
1988            SerializeSeq::serialize_element(self, value)
1989        }
1990        fn end(self) -> Result<Value, Error> {
1991            SerializeSeq::end(self)
1992        }
1993    }
1994
1995    struct MapSerializer {
1996        map: BTreeMap<String, Value>,
1997        key: Option<String>,
1998    }
1999
2000    impl SerializeMap for MapSerializer {
2001        type Ok = Value;
2002        type Error = Error;
2003        fn serialize_key<T: Serialize + ?Sized>(&mut self, key: &T) -> Result<(), Error> {
2004            self.key = Some(key.serialize(KeySerializer)?);
2005            Ok(())
2006        }
2007        fn serialize_value<T: Serialize + ?Sized>(&mut self, value: &T) -> Result<(), Error> {
2008            let k = self
2009                .key
2010                .take()
2011                .ok_or_else(|| de::Error::custom("serialize_value 前需先 serialize_key"))?;
2012            self.map.insert(k, value.serialize(ValueSerializer)?);
2013            Ok(())
2014        }
2015        fn end(self) -> Result<Value, Error> {
2016            Ok(Value::Object(self.map))
2017        }
2018    }
2019
2020    impl SerializeStruct for MapSerializer {
2021        type Ok = Value;
2022        type Error = Error;
2023        fn serialize_field<T: Serialize + ?Sized>(
2024            &mut self,
2025            key: &'static str,
2026            value: &T,
2027        ) -> Result<(), Error> {
2028            self.map
2029                .insert(key.to_string(), value.serialize(ValueSerializer)?);
2030            Ok(())
2031        }
2032        fn end(self) -> Result<Value, Error> {
2033            Ok(Value::Object(self.map))
2034        }
2035    }
2036
2037    /// 对象键必须能转成字符串(SML 的键是裸词/字符串)
2038    struct KeySerializer;
2039
2040    macro_rules! key_unsupported {
2041        ($(fn $m:ident($($a:ident : $t:ty),*) -> Result<String, Error>;)*) => {
2042            $(
2043                fn $m(self, $($a: $t),*) -> Result<String, Error> {
2044                    Err(de::Error::custom("SML 对象的键必须是字符串"))
2045                }
2046            )*
2047        };
2048    }
2049
2050    impl Serializer for KeySerializer {
2051        type Ok = String;
2052        type Error = Error;
2053        type SerializeSeq = ::serde::ser::Impossible<String, Error>;
2054        type SerializeTuple = ::serde::ser::Impossible<String, Error>;
2055        type SerializeTupleStruct = ::serde::ser::Impossible<String, Error>;
2056        type SerializeTupleVariant = ::serde::ser::Impossible<String, Error>;
2057        type SerializeMap = ::serde::ser::Impossible<String, Error>;
2058        type SerializeStruct = ::serde::ser::Impossible<String, Error>;
2059        type SerializeStructVariant = ::serde::ser::Impossible<String, Error>;
2060
2061        fn serialize_str(self, v: &str) -> Result<String, Error> {
2062            Ok(v.to_string())
2063        }
2064        fn serialize_char(self, v: char) -> Result<String, Error> {
2065            Ok(v.to_string())
2066        }
2067        key_unsupported! {
2068            fn serialize_bool(_v: bool) -> Result<String, Error>;
2069            fn serialize_i8(_v: i8) -> Result<String, Error>;
2070            fn serialize_i16(_v: i16) -> Result<String, Error>;
2071            fn serialize_i32(_v: i32) -> Result<String, Error>;
2072            fn serialize_i64(_v: i64) -> Result<String, Error>;
2073            fn serialize_u8(_v: u8) -> Result<String, Error>;
2074            fn serialize_u16(_v: u16) -> Result<String, Error>;
2075            fn serialize_u32(_v: u32) -> Result<String, Error>;
2076            fn serialize_u64(_v: u64) -> Result<String, Error>;
2077            fn serialize_f32(_v: f32) -> Result<String, Error>;
2078            fn serialize_f64(_v: f64) -> Result<String, Error>;
2079            fn serialize_bytes(_v: &[u8]) -> Result<String, Error>;
2080            fn serialize_none() -> Result<String, Error>;
2081            fn serialize_unit() -> Result<String, Error>;
2082            fn serialize_unit_struct(_n: &'static str) -> Result<String, Error>;
2083            fn serialize_unit_variant(_n: &'static str, _i: u32, _v: &'static str) -> Result<String, Error>;
2084        }
2085        fn serialize_some<T: Serialize + ?Sized>(self, _v: &T) -> Result<String, Error> {
2086            Err(de::Error::custom("SML 对象的键必须是字符串"))
2087        }
2088        fn serialize_newtype_struct<T: Serialize + ?Sized>(
2089            self,
2090            _n: &'static str,
2091            _v: &T,
2092        ) -> Result<String, Error> {
2093            Err(de::Error::custom("SML 对象的键必须是字符串"))
2094        }
2095        fn serialize_newtype_variant<T: Serialize + ?Sized>(
2096            self,
2097            _n: &'static str,
2098            _i: u32,
2099            _v: &'static str,
2100            _x: &T,
2101        ) -> Result<String, Error> {
2102            Err(de::Error::custom("SML 对象的键必须是字符串"))
2103        }
2104        // 以下方法返回关联类型(Impossible),一律报错——SML 键只能是字符串
2105        fn serialize_seq(self, _l: Option<usize>) -> Result<Self::SerializeSeq, Error> {
2106            Err(de::Error::custom("SML 对象的键必须是字符串"))
2107        }
2108        fn serialize_tuple(self, _l: usize) -> Result<Self::SerializeTuple, Error> {
2109            Err(de::Error::custom("SML 对象的键必须是字符串"))
2110        }
2111        fn serialize_tuple_struct(
2112            self,
2113            _n: &'static str,
2114            _l: usize,
2115        ) -> Result<Self::SerializeTupleStruct, Error> {
2116            Err(de::Error::custom("SML 对象的键必须是字符串"))
2117        }
2118        fn serialize_tuple_variant(
2119            self,
2120            _n: &'static str,
2121            _i: u32,
2122            _v: &'static str,
2123            _l: usize,
2124        ) -> Result<Self::SerializeTupleVariant, Error> {
2125            Err(de::Error::custom("SML 对象的键必须是字符串"))
2126        }
2127        fn serialize_map(self, _l: Option<usize>) -> Result<Self::SerializeMap, Error> {
2128            Err(de::Error::custom("SML 对象的键必须是字符串"))
2129        }
2130        fn serialize_struct(self, _n: &'static str, _l: usize) -> Result<Self::SerializeStruct, Error> {
2131            Err(de::Error::custom("SML 对象的键必须是字符串"))
2132        }
2133        fn serialize_struct_variant(
2134            self,
2135            _n: &'static str,
2136            _i: u32,
2137            _v: &'static str,
2138            _l: usize,
2139        ) -> Result<Self::SerializeStructVariant, Error> {
2140            Err(de::Error::custom("SML 对象的键必须是字符串"))
2141        }
2142    }
2143
2144    struct TupleVariantSerializer {
2145        variant: String,
2146        values: Vec<Value>,
2147    }
2148
2149    impl SerializeTupleVariant for TupleVariantSerializer {
2150        type Ok = Value;
2151        type Error = Error;
2152        fn serialize_field<T: Serialize + ?Sized>(&mut self, value: &T) -> Result<(), Error> {
2153            self.values.push(value.serialize(ValueSerializer)?);
2154            Ok(())
2155        }
2156        fn end(self) -> Result<Value, Error> {
2157            Ok(Value::Object(BTreeMap::from([
2158                ("__type".into(), Value::Str(self.variant)),
2159                ("_value".into(), Value::Array(self.values)),
2160            ])))
2161        }
2162    }
2163
2164    struct StructVariantSerializer {
2165        variant: String,
2166        map: BTreeMap<String, Value>,
2167    }
2168
2169    impl SerializeStructVariant for StructVariantSerializer {
2170        type Ok = Value;
2171        type Error = Error;
2172        fn serialize_field<T: Serialize + ?Sized>(
2173            &mut self,
2174            key: &'static str,
2175            value: &T,
2176        ) -> Result<(), Error> {
2177            self.map
2178                .insert(key.to_string(), value.serialize(ValueSerializer)?);
2179            Ok(())
2180        }
2181        fn end(self) -> Result<Value, Error> {
2182            let mut m = BTreeMap::new();
2183            m.insert("__type".into(), Value::Str(self.variant));
2184            m.extend(self.map);
2185            Ok(Value::Object(m))
2186        }
2187    }
2188
2189    // ---- Deserializer: Value -> T: Deserialize ----
2190
2191    macro_rules! deser_int {
2192        ($(fn $m:ident($v:ident, $call:ident);)*) => {
2193            $(
2194                fn $m<V>(self, $v: V) -> Result<V::Value, Self::Error>
2195                where V: Visitor<'de> {
2196                    match self.0 {
2197                        Value::Int(i) => $v.$call(i as _),
2198                        Value::Float(f)
2199                            if f.fract() == 0.0
2200                                && f >= i64::MIN as f64
2201                                && f <= i64::MAX as f64 =>
2202                        {
2203                            $v.$call(f as _)
2204                        }
2205                        other => Err(type_err(&other, stringify!($m).trim_start_matches("deserialize_"))),
2206                    }
2207                }
2208            )*
2209        };
2210    }
2211
2212    struct ValueDeserializer(Value);
2213
2214    impl<'de> Deserializer<'de> for ValueDeserializer {
2215        type Error = Error;
2216
2217        fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Error>
2218        where
2219            V: Visitor<'de>,
2220        {
2221            match self.0 {
2222                Value::Null => visitor.visit_unit(),
2223                Value::Bool(b) => visitor.visit_bool(b),
2224                Value::Int(i) => visitor.visit_i64(i),
2225                Value::Float(f) => visitor.visit_f64(f),
2226                Value::Str(s) => visitor.visit_string(s),
2227                Value::Array(a) => visitor.visit_seq(SeqDeserializer { items: a, idx: 0 }),
2228                Value::Object(m) => visitor.visit_map(MapDeserializer { map: m, pending: None }),
2229            }
2230        }
2231
2232        fn deserialize_bool<V>(self, visitor: V) -> Result<V::Value, Error>
2233        where
2234            V: Visitor<'de>,
2235        {
2236            match self.0 {
2237                Value::Bool(b) => visitor.visit_bool(b),
2238                other => Err(type_err(&other, "布尔")),
2239            }
2240        }
2241
2242        deser_int! {
2243            fn deserialize_i8(v, visit_i8);
2244            fn deserialize_i16(v, visit_i16);
2245            fn deserialize_i32(v, visit_i32);
2246            fn deserialize_i64(v, visit_i64);
2247            fn deserialize_u8(v, visit_u8);
2248            fn deserialize_u16(v, visit_u16);
2249            fn deserialize_u32(v, visit_u32);
2250        }
2251
2252        fn deserialize_u64<V>(self, visitor: V) -> Result<V::Value, Error>
2253        where
2254            V: Visitor<'de>,
2255        {
2256            match self.0 {
2257                Value::Int(i) if i >= 0 => visitor.visit_u64(i as u64),
2258                Value::Float(f)
2259                    if f.fract() == 0.0 && f >= 0.0 && f <= u64::MAX as f64 =>
2260                {
2261                    visitor.visit_u64(f as u64)
2262                }
2263                other => Err(type_err(&other, "u64")),
2264            }
2265        }
2266
2267        fn deserialize_f32<V>(self, visitor: V) -> Result<V::Value, Error>
2268        where
2269            V: Visitor<'de>,
2270        {
2271            match self.0 {
2272                Value::Int(i) => visitor.visit_f32(i as f32),
2273                Value::Float(f) => visitor.visit_f32(f as f32),
2274                other => Err(type_err(&other, "f32")),
2275            }
2276        }
2277        fn deserialize_f64<V>(self, visitor: V) -> Result<V::Value, Error>
2278        where
2279            V: Visitor<'de>,
2280        {
2281            match self.0 {
2282                Value::Int(i) => visitor.visit_f64(i as f64),
2283                Value::Float(f) => visitor.visit_f64(f),
2284                other => Err(type_err(&other, "f64")),
2285            }
2286        }
2287
2288        fn deserialize_char<V>(self, visitor: V) -> Result<V::Value, Error>
2289        where
2290            V: Visitor<'de>,
2291        {
2292            match self.0 {
2293                Value::Str(s) if s.chars().count() == 1 => {
2294                    visitor.visit_char(s.chars().next().unwrap())
2295                }
2296                other => Err(type_err(&other, "字符")),
2297            }
2298        }
2299
2300        fn deserialize_str<V>(self, visitor: V) -> Result<V::Value, Error>
2301        where
2302            V: Visitor<'de>,
2303        {
2304            match self.0 {
2305                Value::Str(s) => visitor.visit_string(s),
2306                other => Err(type_err(&other, "字符串")),
2307            }
2308        }
2309        fn deserialize_string<V>(self, visitor: V) -> Result<V::Value, Error>
2310        where
2311            V: Visitor<'de>,
2312        {
2313            self.deserialize_str(visitor)
2314        }
2315
2316        fn deserialize_bytes<V>(self, visitor: V) -> Result<V::Value, Error>
2317        where
2318            V: Visitor<'de>,
2319        {
2320            match self.0 {
2321                Value::Array(items) => {
2322                    let mut buf = Vec::with_capacity(items.len());
2323                    for it in items {
2324                        match it {
2325                            Value::Int(i) if (0..=255).contains(&i) => buf.push(i as u8),
2326                            other => return Err(type_err(&other, "字节")),
2327                        }
2328                    }
2329                    visitor.visit_byte_buf(buf)
2330                }
2331                other => Err(type_err(&other, "字节数组")),
2332            }
2333        }
2334        fn deserialize_byte_buf<V>(self, visitor: V) -> Result<V::Value, Error>
2335        where
2336            V: Visitor<'de>,
2337        {
2338            self.deserialize_bytes(visitor)
2339        }
2340
2341        fn deserialize_option<V>(self, visitor: V) -> Result<V::Value, Error>
2342        where
2343            V: Visitor<'de>,
2344        {
2345            match self.0 {
2346                Value::Null => visitor.visit_none(),
2347                other => visitor.visit_some(ValueDeserializer(other)),
2348            }
2349        }
2350
2351        fn deserialize_unit<V>(self, visitor: V) -> Result<V::Value, Error>
2352        where
2353            V: Visitor<'de>,
2354        {
2355            match self.0 {
2356                Value::Null => visitor.visit_unit(),
2357                other => Err(type_err(&other, "unit")),
2358            }
2359        }
2360        fn deserialize_unit_struct<V>(
2361            self,
2362            _name: &'static str,
2363            visitor: V,
2364        ) -> Result<V::Value, Error>
2365        where
2366            V: Visitor<'de>,
2367        {
2368            self.deserialize_unit(visitor)
2369        }
2370        fn deserialize_newtype_struct<V>(
2371            self,
2372            _name: &'static str,
2373            visitor: V,
2374        ) -> Result<V::Value, Error>
2375        where
2376            V: Visitor<'de>,
2377        {
2378            self.deserialize_any(visitor)
2379        }
2380
2381        fn deserialize_seq<V>(self, visitor: V) -> Result<V::Value, Error>
2382        where
2383            V: Visitor<'de>,
2384        {
2385            match self.0 {
2386                Value::Array(a) => visitor.visit_seq(SeqDeserializer { items: a, idx: 0 }),
2387                other => Err(type_err(&other, "数组")),
2388            }
2389        }
2390        fn deserialize_tuple<V>(self, _len: usize, visitor: V) -> Result<V::Value, Error>
2391        where
2392            V: Visitor<'de>,
2393        {
2394            self.deserialize_seq(visitor)
2395        }
2396        fn deserialize_tuple_struct<V>(
2397            self,
2398            _name: &'static str,
2399            _len: usize,
2400            visitor: V,
2401        ) -> Result<V::Value, Error>
2402        where
2403            V: Visitor<'de>,
2404        {
2405            self.deserialize_seq(visitor)
2406        }
2407
2408        fn deserialize_map<V>(self, visitor: V) -> Result<V::Value, Error>
2409        where
2410            V: Visitor<'de>,
2411        {
2412            match self.0 {
2413                Value::Object(m) => visitor.visit_map(MapDeserializer { map: m, pending: None }),
2414                other => Err(type_err(&other, "块/对象")),
2415            }
2416        }
2417        fn deserialize_struct<V>(
2418            self,
2419            _name: &'static str,
2420            _fields: &'static [&'static str],
2421            visitor: V,
2422        ) -> Result<V::Value, Error>
2423        where
2424            V: Visitor<'de>,
2425        {
2426            self.deserialize_map(visitor)
2427        }
2428
2429        fn deserialize_enum<V>(
2430            self,
2431            _name: &'static str,
2432            _variants: &'static [&'static str],
2433            visitor: V,
2434        ) -> Result<V::Value, Error>
2435        where
2436            V: Visitor<'de>,
2437        {
2438            match self.0 {
2439                Value::Str(s) => visitor.visit_enum(EnumDeserializer {
2440                    variant: s,
2441                    kind: EnumKind::Unit,
2442                }),
2443                Value::Object(mut m) => {
2444                    // 1) SML 专有约定:`__type` 键(与 SmlSerialize 输出一致)
2445                    if let Some(ty) = m.remove("__type") {
2446                        let variant = match ty {
2447                            Value::Str(s) => s,
2448                            _ => return Err(de::Error::custom("`__type` 的值必须是字符串")),
2449                        };
2450                        let kind = match m.remove("_value") {
2451                            Some(Value::Array(items)) => EnumKind::Tuple(items),
2452                            Some(other) => EnumKind::Newtype(other),
2453                            None if m.is_empty() => EnumKind::Unit,
2454                            None => EnumKind::Struct(m),
2455                        };
2456                        return visitor.visit_enum(EnumDeserializer { variant, kind });
2457                    }
2458                    // 2) serde 外部标签(含 SML 裸词包裹形态):
2459                    //    {"in-maintenance": "in-maintenance"} -> 单元变体
2460                    //    {"Circle": 3}                        -> 单值变体
2461                    if m.len() == 1 {
2462                        let (k, v) = m.pop_first().expect("len==1 必有键");
2463                        let kind = match v {
2464                            Value::Str(s) if s == k => EnumKind::Unit,
2465                            other => EnumKind::Newtype(other),
2466                        };
2467                        return visitor.visit_enum(EnumDeserializer { variant: k, kind });
2468                    }
2469                    Err(de::Error::custom(
2470                        "枚举块需要 `__type` 键(SML 约定)或单键外部标签 `{ VariantName: ... }`",
2471                    ))
2472                }
2473                other => Err(type_err(&other, "枚举")),
2474            }
2475        }
2476
2477        fn deserialize_identifier<V>(self, visitor: V) -> Result<V::Value, Error>
2478        where
2479            V: Visitor<'de>,
2480        {
2481            self.deserialize_str(visitor)
2482        }
2483        fn deserialize_ignored_any<V>(self, visitor: V) -> Result<V::Value, Error>
2484        where
2485            V: Visitor<'de>,
2486        {
2487            self.deserialize_any(visitor)
2488        }
2489    }
2490
2491    struct SeqDeserializer {
2492        items: Vec<Value>,
2493        idx: usize,
2494    }
2495
2496    impl<'de> SeqAccess<'de> for SeqDeserializer {
2497        type Error = Error;
2498        fn next_element_seed<T: de::DeserializeSeed<'de>>(
2499            &mut self,
2500            seed: T,
2501        ) -> Result<Option<T::Value>, Error> {
2502            if self.idx >= self.items.len() {
2503                return Ok(None);
2504            }
2505            let item = self.items[self.idx].clone();
2506            self.idx += 1;
2507            seed.deserialize(ValueDeserializer(item)).map(Some)
2508        }
2509    }
2510
2511    struct MapDeserializer {
2512        map: BTreeMap<String, Value>,
2513        pending: Option<Value>,
2514    }
2515
2516    impl<'de> MapAccess<'de> for MapDeserializer {
2517        type Error = Error;
2518        fn next_key_seed<K: de::DeserializeSeed<'de>>(
2519            &mut self,
2520            seed: K,
2521        ) -> Result<Option<K::Value>, Error> {
2522            let Some((k, v)) = self.map.pop_first() else {
2523                return Ok(None);
2524            };
2525            self.pending = Some(v);
2526            seed.deserialize(KeyDeserializer(&k)).map(Some)
2527        }
2528        fn next_value_seed<V: de::DeserializeSeed<'de>>(
2529            &mut self,
2530            seed: V,
2531        ) -> Result<V::Value, Error> {
2532            let v = self.pending.take().ok_or_else(|| {
2533                de::Error::custom("value 缺失:需先调用 next_key_seed")
2534            })?;
2535            seed.deserialize(ValueDeserializer(v))
2536        }
2537    }
2538
2539    /// 字段名 / 变体名的轻量反序列化器(只认字符串)
2540    struct KeyDeserializer<'a>(&'a str);
2541
2542    macro_rules! key_delegate {
2543        ($($m:ident),* $(,)?) => {
2544            $(
2545                fn $m<V>(self, visitor: V) -> Result<V::Value, Error>
2546                where V: Visitor<'de> {
2547                    self.deserialize_any(visitor)
2548                }
2549            )*
2550        };
2551    }
2552
2553    impl<'de, 'a> Deserializer<'de> for KeyDeserializer<'a> {
2554        type Error = Error;
2555
2556        fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Error>
2557        where
2558            V: Visitor<'de>,
2559        {
2560            visitor.visit_str(self.0)
2561        }
2562        fn deserialize_str<V>(self, visitor: V) -> Result<V::Value, Error>
2563        where
2564            V: Visitor<'de>,
2565        {
2566            visitor.visit_str(self.0)
2567        }
2568        fn deserialize_string<V>(self, visitor: V) -> Result<V::Value, Error>
2569        where
2570            V: Visitor<'de>,
2571        {
2572            visitor.visit_str(self.0)
2573        }
2574        fn deserialize_identifier<V>(self, visitor: V) -> Result<V::Value, Error>
2575        where
2576            V: Visitor<'de>,
2577        {
2578            visitor.visit_str(self.0)
2579        }
2580        fn deserialize_enum<V>(
2581            self,
2582            _name: &'static str,
2583            _variants: &'static [&'static str],
2584            visitor: V,
2585        ) -> Result<V::Value, Error>
2586        where
2587            V: Visitor<'de>,
2588        {
2589            visitor.visit_enum(EnumDeserializer {
2590                variant: self.0.to_string(),
2591                kind: EnumKind::Unit,
2592            })
2593        }
2594        fn deserialize_option<V>(self, visitor: V) -> Result<V::Value, Error>
2595        where
2596            V: Visitor<'de>,
2597        {
2598            visitor.visit_some(self)
2599        }
2600        fn deserialize_unit_struct<V>(
2601            self,
2602            _name: &'static str,
2603            visitor: V,
2604        ) -> Result<V::Value, Error>
2605        where
2606            V: Visitor<'de>,
2607        {
2608            self.deserialize_unit(visitor)
2609        }
2610        fn deserialize_newtype_struct<V>(
2611            self,
2612            _name: &'static str,
2613            visitor: V,
2614        ) -> Result<V::Value, Error>
2615        where
2616            V: Visitor<'de>,
2617        {
2618            self.deserialize_any(visitor)
2619        }
2620        fn deserialize_tuple<V>(self, _len: usize, visitor: V) -> Result<V::Value, Error>
2621        where
2622            V: Visitor<'de>,
2623        {
2624            self.deserialize_seq(visitor)
2625        }
2626        fn deserialize_tuple_struct<V>(
2627            self,
2628            _name: &'static str,
2629            _len: usize,
2630            visitor: V,
2631        ) -> Result<V::Value, Error>
2632        where
2633            V: Visitor<'de>,
2634        {
2635            self.deserialize_seq(visitor)
2636        }
2637        fn deserialize_struct<V>(
2638            self,
2639            _name: &'static str,
2640            _fields: &'static [&'static str],
2641            visitor: V,
2642        ) -> Result<V::Value, Error>
2643        where
2644            V: Visitor<'de>,
2645        {
2646            self.deserialize_map(visitor)
2647        }
2648        fn deserialize_ignored_any<V>(self, visitor: V) -> Result<V::Value, Error>
2649        where
2650            V: Visitor<'de>,
2651        {
2652            self.deserialize_any(visitor)
2653        }
2654        key_delegate! {
2655            deserialize_bool, deserialize_i8, deserialize_i16, deserialize_i32,
2656            deserialize_i64, deserialize_u8, deserialize_u16, deserialize_u32,
2657            deserialize_u64, deserialize_f32, deserialize_f64, deserialize_char,
2658            deserialize_bytes, deserialize_byte_buf, deserialize_unit,
2659            deserialize_seq, deserialize_map,
2660        }
2661    }
2662
2663    // ---- 枚举(SML `__type` 约定,与 SmlDeserialize 一致)----
2664
2665    #[derive(Debug)]
2666    enum EnumKind {
2667        Unit,
2668        Newtype(Value),
2669        Tuple(Vec<Value>),
2670        Struct(BTreeMap<String, Value>),
2671    }
2672
2673    struct EnumDeserializer {
2674        variant: String,
2675        kind: EnumKind,
2676    }
2677
2678    impl<'de> de::EnumAccess<'de> for EnumDeserializer {
2679        type Error = Error;
2680        type Variant = VariantAccess;
2681        fn variant_seed<V: de::DeserializeSeed<'de>>(
2682            self,
2683            seed: V,
2684        ) -> Result<(V::Value, Self::Variant), Error> {
2685            let variant = seed.deserialize(KeyDeserializer(&self.variant))?;
2686            Ok((variant, VariantAccess { kind: self.kind }))
2687        }
2688    }
2689
2690    struct VariantAccess {
2691        kind: EnumKind,
2692    }
2693
2694    impl<'de> de::VariantAccess<'de> for VariantAccess {
2695        type Error = Error;
2696        fn unit_variant(self) -> Result<(), Error> {
2697            match self.kind {
2698                EnumKind::Unit => Ok(()),
2699                _ => Err(de::Error::custom("该变体携带数据,不能按单元变体解析")),
2700            }
2701        }
2702        fn newtype_variant_seed<T: de::DeserializeSeed<'de>>(
2703            self,
2704            seed: T,
2705        ) -> Result<T::Value, Error> {
2706            match self.kind {
2707                EnumKind::Newtype(v) => seed.deserialize(ValueDeserializer(v)),
2708                EnumKind::Tuple(items) => {
2709                    seed.deserialize(ValueDeserializer(Value::Array(items)))
2710                }
2711                _ => Err(de::Error::custom("该变体没有单值数据")),
2712            }
2713        }
2714        fn tuple_variant<V>(self, _len: usize, visitor: V) -> Result<V::Value, Error>
2715        where
2716            V: Visitor<'de>,
2717        {
2718            match self.kind {
2719                EnumKind::Tuple(items) => {
2720                    visitor.visit_seq(SeqDeserializer { items, idx: 0 })
2721                }
2722                _ => Err(de::Error::custom("该变体不是元组形态")),
2723            }
2724        }
2725        fn struct_variant<V>(
2726            self,
2727            _fields: &'static [&'static str],
2728            visitor: V,
2729        ) -> Result<V::Value, Error>
2730        where
2731            V: Visitor<'de>,
2732        {
2733            match self.kind {
2734                EnumKind::Struct(m) => {
2735                    visitor.visit_map(MapDeserializer { map: m, pending: None })
2736                }
2737                _ => Err(de::Error::custom("该变体不是结构体形态")),
2738            }
2739        }
2740    }
2741}
2742
2743// ---------------------------------------------------------------------------
2744// 自然序列化宏(derive)支持
2745// ---------------------------------------------------------------------------
2746
2747/// 把一个类型「自然地」序列化为 SML 值:
2748/// 结构体 → 块、newtype → 透明、单元结构体 → 裸词、
2749/// 枚举单元变体 → 裸词、带数据变体 → `__type` 块。
2750///
2751/// 通常用 `#[derive(SmlSerialize)]` 自动实现(`derive` feature 默认开启),
2752/// 也可手动实现。支持的 `#[sml(...)]` 属性见 `swsml-derive` 的文档。
2753pub trait SmlSerialize {
2754    fn to_sml_value(&self) -> Value;
2755
2756    /// 序列化为 SML 文本(等价于 [`to_sml`] 作用于本类型生成的值)。
2757    fn to_sml(&self) -> String {
2758        crate::to_sml(&self.to_sml_value())
2759    }
2760}
2761
2762/// 从 SML 值反序列化(`#[derive(SmlDeserialize)]` 自动实现)。
2763pub trait SmlDeserialize: Sized {
2764    fn from_sml_value(v: &Value) -> Result<Self, String>;
2765
2766    /// 解析 SML 文本并反序列化。
2767    fn from_sml(text: &str) -> Result<Self, String> {
2768        let v = crate::parse(text).map_err(|e| format!("SML 解析失败: {e}"))?;
2769        Self::from_sml_value(&v)
2770    }
2771}
2772
2773#[cfg(feature = "derive")]
2774pub use swsml_derive::{SmlDeserialize, SmlSerialize};
2775
2776/// 序列化为 SML 文本 —— toml-rs 风格的顶层函数(等价于 [`SmlSerialize::to_sml`])。
2777///
2778/// 用法与 `toml::to_string` 一致(序列化不会失败,故直接返回 `String`):
2779///
2780/// ```rust
2781/// # use sml::{SmlSerialize, SmlDeserialize};
2782/// # #[derive(SmlSerialize, SmlDeserialize, Debug, PartialEq)]
2783/// # struct Server { host: String, port: i32 }
2784/// # let cfg = Server { host: "web.example".into(), port: 8080 };
2785/// let text = sml::to_string(&cfg);
2786/// assert_eq!(text, "host: web.example\nport: 8080\n");
2787/// ```
2788pub fn to_string<T: SmlSerialize + ?Sized>(value: &T) -> String {
2789    crate::to_sml(&value.to_sml_value())
2790}
2791
2792/// 解析 SML 文本并反序列化 —— toml-rs 风格的顶层函数(等价于 [`SmlDeserialize::from_sml`])。
2793///
2794/// ```rust
2795/// # use sml::{SmlSerialize, SmlDeserialize};
2796/// # #[derive(SmlSerialize, SmlDeserialize, Debug, PartialEq)]
2797/// # struct Server { host: String, port: i32 }
2798/// let back: Server = sml::from_str("host: web.example\nport: 8080\n").unwrap();
2799/// assert_eq!(back.host, "web.example");
2800/// assert_eq!(back.port, 8080);
2801/// ```
2802pub fn from_str<T: SmlDeserialize>(text: &str) -> Result<T, String> {
2803    T::from_sml(text)
2804}
2805
2806/// 宏生成代码引用的内部辅助(请勿直接使用)。
2807#[doc(hidden)]
2808pub mod __private {
2809    use super::{SmlDeserialize, SmlSerialize, Value};
2810    use std::collections::{BTreeMap, HashMap};
2811
2812    /// 描述值的类型,用于错误信息。
2813    pub fn describe_value(v: &Value) -> String {
2814        match v {
2815            Value::Null => "null".to_string(),
2816            Value::Bool(b) => b.to_string(),
2817            Value::Int(i) => i.to_string(),
2818            Value::Float(f) => f.to_string(),
2819            Value::Str(s) => format!("字符串 `{s}`"),
2820            Value::Array(a) => format!("数组({} 个元素)", a.len()),
2821            Value::Object(o) => format!("块({} 个键)", o.len()),
2822        }
2823    }
2824
2825    /// 取出 `_value` 键(枚举单值变体)。
2826    pub fn take_value(m: &BTreeMap<String, Value>) -> Result<Value, String> {
2827        m.get("_value")
2828            .cloned()
2829            .ok_or_else(|| "缺少 _value 键".to_string())
2830    }
2831
2832    /// 取出 `_value` 键并断言为数组(枚举 tuple 变体)。
2833    pub fn take_array(m: &BTreeMap<String, Value>) -> Result<Vec<Value>, String> {
2834        match m.get("_value") {
2835            Some(Value::Array(a)) => Ok(a.clone()),
2836            Some(other) => Err(format!("_value 期望数组,实际为 {}", describe_value(other))),
2837            None => Err("缺少 _value 键".to_string()),
2838        }
2839    }
2840
2841    /// `#[sml(flatten)]` 反序列化:把整个块交给子类型。
2842    pub fn flatten_from<T: SmlDeserialize>(m: &BTreeMap<String, Value>) -> Result<T, String> {
2843        T::from_sml_value(&Value::Object(m.clone()))
2844    }
2845
2846    // ---- 基础类型 ----
2847
2848    impl SmlSerialize for bool {
2849        #[inline]
2850        fn to_sml_value(&self) -> Value {
2851            Value::Bool(*self)
2852        }
2853    }
2854    impl SmlDeserialize for bool {
2855        #[inline]
2856        fn from_sml_value(v: &Value) -> Result<Self, String> {
2857            match v {
2858                Value::Bool(b) => Ok(*b),
2859                other => Err(format!("期望布尔,实际为 {}", describe_value(other))),
2860            }
2861        }
2862    }
2863
2864    macro_rules! impl_int {
2865        ($($t:ty),* $(,)?) => {$(
2866            impl SmlSerialize for $t {
2867                #[inline]
2868                fn to_sml_value(&self) -> Value { Value::Int(*self as i64) }
2869            }
2870            impl SmlDeserialize for $t {
2871                #[inline]
2872                fn from_sml_value(v: &Value) -> Result<Self, String> {
2873                    match v {
2874                        Value::Int(i) => <$t>::try_from(*i)
2875                            .map_err(|_| format!("整数 {i} 超出 {} 范围", stringify!($t))),
2876                        Value::Float(f)
2877                            if f.fract() == 0.0
2878                                && *f >= <$t>::MIN as f64
2879                                && *f <= <$t>::MAX as f64 => Ok(*f as $t),
2880                        Value::Float(f) => Err(format!("期望整数,实际为小数 {f}")),
2881                        other => Err(format!("期望整数,实际为 {}", describe_value(other))),
2882                    }
2883                }
2884            }
2885        )*};
2886    }
2887    impl_int!(i8, i16, i32, i64, isize, u8, u16, u32, usize);
2888
2889    impl SmlSerialize for u64 {
2890        #[inline]
2891        fn to_sml_value(&self) -> Value {
2892            i64::try_from(*self).map(Value::Int).unwrap_or_else(|_| Value::Float(*self as f64))
2893        }
2894    }
2895    impl SmlDeserialize for u64 {
2896        #[inline]
2897        fn from_sml_value(v: &Value) -> Result<Self, String> {
2898            match v {
2899                Value::Int(i) => u64::try_from(*i).map_err(|_| format!("整数 {i} 为负数,超出 u64 范围")),
2900                Value::Float(f) if f.fract() == 0.0 && *f >= 0.0 => Ok(*f as u64),
2901                Value::Float(f) => Err(format!("期望非负整数,实际为 {f}")),
2902                other => Err(format!("期望整数,实际为 {}", describe_value(other))),
2903            }
2904        }
2905    }
2906
2907    macro_rules! impl_big {
2908        ($($t:ty),* $(,)?) => {$(
2909            impl SmlSerialize for $t {
2910                #[inline]
2911                fn to_sml_value(&self) -> Value {
2912                    i64::try_from(*self).map(Value::Int).unwrap_or_else(|_| Value::Float(*self as f64))
2913                }
2914            }
2915            impl SmlDeserialize for $t {
2916                #[inline]
2917                fn from_sml_value(v: &Value) -> Result<Self, String> {
2918                    match v {
2919                        Value::Int(i) => Ok(*i as $t),
2920                        Value::Float(f) if f.fract() == 0.0 => Ok(*f as $t),
2921                        Value::Float(f) => Err(format!("期望整数,实际为小数 {f}")),
2922                        other => Err(format!("期望整数,实际为 {}", describe_value(other))),
2923                    }
2924                }
2925            }
2926        )*};
2927    }
2928    impl_big!(i128, u128);
2929
2930    macro_rules! impl_float {
2931        ($($t:ty),* $(,)?) => {$(
2932            impl SmlSerialize for $t {
2933                #[inline]
2934                fn to_sml_value(&self) -> Value { Value::Float(*self as f64) }
2935            }
2936            impl SmlDeserialize for $t {
2937                #[inline]
2938                fn from_sml_value(v: &Value) -> Result<Self, String> {
2939                    match v {
2940                        Value::Int(i) => Ok(*i as $t),
2941                        Value::Float(f) => Ok(*f as $t),
2942                        other => Err(format!("期望数字,实际为 {}", describe_value(other))),
2943                    }
2944                }
2945            }
2946        )*};
2947    }
2948    impl_float!(f32, f64);
2949
2950    impl SmlSerialize for char {
2951        #[inline]
2952        fn to_sml_value(&self) -> Value {
2953            Value::Str(self.to_string())
2954        }
2955    }
2956    impl SmlDeserialize for char {
2957        #[inline]
2958        fn from_sml_value(v: &Value) -> Result<Self, String> {
2959            match v {
2960                Value::Str(s) => {
2961                    let mut it = s.chars();
2962                    match (it.next(), it.next()) {
2963                        (Some(c), None) => Ok(c),
2964                        _ => Err(format!("期望单个字符,实际为 `{s}`")),
2965                    }
2966                }
2967                other => Err(format!("期望字符串,实际为 {}", describe_value(other))),
2968            }
2969        }
2970    }
2971
2972    impl SmlSerialize for String {
2973        #[inline]
2974        fn to_sml_value(&self) -> Value {
2975            Value::Str(self.clone())
2976        }
2977    }
2978    impl SmlDeserialize for String {
2979        #[inline]
2980        fn from_sml_value(v: &Value) -> Result<Self, String> {
2981            match v {
2982                Value::Str(s) => Ok(s.clone()),
2983                other => Err(format!("期望字符串,实际为 {}", describe_value(other))),
2984            }
2985        }
2986    }
2987
2988    impl SmlSerialize for str {
2989        #[inline]
2990        fn to_sml_value(&self) -> Value {
2991            Value::Str(self.to_string())
2992        }
2993    }
2994
2995    impl SmlSerialize for &str {
2996        #[inline]
2997        fn to_sml_value(&self) -> Value {
2998            Value::Str(self.to_string())
2999        }
3000    }
3001
3002    impl SmlSerialize for () {
3003        #[inline]
3004        fn to_sml_value(&self) -> Value {
3005            Value::Null
3006        }
3007    }
3008    impl SmlDeserialize for () {
3009        #[inline]
3010        fn from_sml_value(v: &Value) -> Result<Self, String> {
3011            match v {
3012                Value::Null => Ok(()),
3013                other => Err(format!("期望 null,实际为 {}", describe_value(other))),
3014            }
3015        }
3016    }
3017
3018    impl SmlSerialize for Value {
3019        #[inline]
3020        fn to_sml_value(&self) -> Value {
3021            self.clone()
3022        }
3023    }
3024    impl SmlDeserialize for Value {
3025        #[inline]
3026        fn from_sml_value(v: &Value) -> Result<Self, String> {
3027            Ok(v.clone())
3028        }
3029    }
3030
3031    impl<T: SmlSerialize> SmlSerialize for Option<T> {
3032        #[inline]
3033        fn to_sml_value(&self) -> Value {
3034            match self {
3035                Some(v) => v.to_sml_value(),
3036                None => Value::Null,
3037            }
3038        }
3039    }
3040    impl<T: SmlDeserialize> SmlDeserialize for Option<T> {
3041        #[inline]
3042        fn from_sml_value(v: &Value) -> Result<Self, String> {
3043            match v {
3044                Value::Null => Ok(None),
3045                other => Ok(Some(T::from_sml_value(other)?)),
3046            }
3047        }
3048    }
3049
3050    impl<T: SmlSerialize> SmlSerialize for Vec<T> {
3051        #[inline]
3052        fn to_sml_value(&self) -> Value {
3053            Value::Array(self.iter().map(SmlSerialize::to_sml_value).collect())
3054        }
3055    }
3056    impl<T: SmlDeserialize> SmlDeserialize for Vec<T> {
3057        #[inline]
3058        fn from_sml_value(v: &Value) -> Result<Self, String> {
3059            match v {
3060                Value::Array(a) => a.iter().map(SmlDeserialize::from_sml_value).collect(),
3061                other => Err(format!("期望数组,实际为 {}", describe_value(other))),
3062            }
3063        }
3064    }
3065
3066    impl<T: SmlSerialize> SmlSerialize for Box<T> {
3067        #[inline]
3068        fn to_sml_value(&self) -> Value {
3069            (**self).to_sml_value()
3070        }
3071    }
3072    impl<T: SmlDeserialize> SmlDeserialize for Box<T> {
3073        #[inline]
3074        fn from_sml_value(v: &Value) -> Result<Self, String> {
3075            Ok(Box::new(T::from_sml_value(v)?))
3076        }
3077    }
3078
3079    impl<V: SmlSerialize> SmlSerialize for BTreeMap<String, V> {
3080        #[inline]
3081        fn to_sml_value(&self) -> Value {
3082            Value::Object(
3083                self.iter()
3084                    .map(|(k, v)| (k.clone(), v.to_sml_value()))
3085                    .collect(),
3086            )
3087        }
3088    }
3089    impl<V: SmlDeserialize> SmlDeserialize for BTreeMap<String, V> {
3090        #[inline]
3091        fn from_sml_value(v: &Value) -> Result<Self, String> {
3092            match v {
3093                Value::Object(m) => {
3094                    let mut out = BTreeMap::new();
3095                    for (k, val) in m {
3096                        out.insert(k.clone(), V::from_sml_value(val)?);
3097                    }
3098                    Ok(out)
3099                }
3100                other => Err(format!("期望块(object),实际为 {}", describe_value(other))),
3101            }
3102        }
3103    }
3104
3105    impl<V: SmlSerialize> SmlSerialize for HashMap<String, V> {
3106        #[inline]
3107        fn to_sml_value(&self) -> Value {
3108            Value::Object(
3109                self.iter()
3110                    .map(|(k, v)| (k.clone(), v.to_sml_value()))
3111                    .collect(),
3112            )
3113        }
3114    }
3115    impl<V: SmlDeserialize> SmlDeserialize for HashMap<String, V> {
3116        #[inline]
3117        fn from_sml_value(v: &Value) -> Result<Self, String> {
3118            match v {
3119                Value::Object(m) => {
3120                    let mut out = HashMap::new();
3121                    for (k, val) in m {
3122                        out.insert(k.clone(), V::from_sml_value(val)?);
3123                    }
3124                    Ok(out)
3125                }
3126                other => Err(format!("期望块(object),实际为 {}", describe_value(other))),
3127            }
3128        }
3129    }
3130}
3131
3132// ---------------------------------------------------------------------------
3133// 测试
3134// ---------------------------------------------------------------------------
3135
3136#[cfg(test)]
3137mod tests {
3138    use super::*;
3139
3140    // ---------------- version ----------------
3141
3142    #[test]
3143    fn version_defaults_to_current_when_absent() {
3144        // 既有文档没有版本声明,必须仍能解析且默认为当前版本
3145        let (v, ver) = parse_versioned("a: 1\n").unwrap();
3146        assert_eq!(ver, Version::CURRENT);
3147        assert_eq!(v.get("a"), Some(&Value::Int(1)));
3148    }
3149
3150    #[test]
3151    fn version_declared_as_v1() {
3152        let (v, ver) = parse_versioned("@version v1\na: 1\n").unwrap();
3153        assert_eq!(ver, Version::V1);
3154        assert_eq!(v.get("a"), Some(&Value::Int(1)));
3155    }
3156
3157    #[test]
3158    fn version_declaration_is_stripped_not_parsed_as_content() {
3159        // 若未剥离,`@version v1` 会被当成片段定义而解析异常
3160        let v = parse("@version v1\na: 1\n").unwrap();
3161        assert_eq!(v.get("a"), Some(&Value::Int(1)));
3162        assert!(v.get("version").is_none(), "@version 不应进入数据");
3163    }
3164
3165    #[test]
3166    fn unsupported_version_is_rejected() {
3167        let err = parse_versioned("@version v99\na: 1\n").unwrap_err();
3168        assert!(err.contains("不支持"), "应拒绝不支持的版本,got: {err}");
3169        assert!(err.contains("v99"), "错误应含版本号,got: {err}");
3170    }
3171
3172    #[test]
3173    fn conflicting_version_is_rejected() {
3174        let err = parse_versioned("@version v1\n@version v2\n").unwrap_err();
3175        // v2 尚未定义,优先报「不支持」
3176        assert!(!err.is_empty());
3177        // 两个都支持但不一致时的路径:v1 与 v1 不冲突
3178        let (_, ver) = parse_versioned("@version v1\n@version v1\n").unwrap();
3179        assert_eq!(ver, Version::V1, "重复但一致的声明应被接受");
3180    }
3181
3182    #[test]
3183    fn version_is_reserved_as_fragment_name() {
3184        let err = parse("@version { x: 1 }\n").unwrap_err();
3185        assert!(err.contains("保留") || err.contains("版本声明"), "got: {err}");
3186    }
3187
3188    #[test]
3189    fn version_works_with_include() {
3190        let d = tmpdir("version");
3191        std::fs::write(d.join("p.sml"), "@version v1\nb: 2\n").unwrap();
3192        std::fs::write(d.join("main.sml"), "@version v1\ninclude \"p.sml\"\n").unwrap();
3193        let (v, ver) = parse_file_versioned(d.join("main.sml")).unwrap();
3194        assert_eq!(ver, Version::V1);
3195        assert_eq!(v.get("b"), Some(&Value::Int(2)), "版本与 include 应协同");
3196        let _ = std::fs::remove_dir_all(&d);
3197    }
3198
3199    #[test]
3200    fn version_display_matches_name() {
3201        assert_eq!(Version::V1.name(), "v1");
3202        assert_eq!(format!("{}", Version::V1), "v1");
3203    }
3204
3205    // ---------------- include ----------------
3206
3207    /// 在临时目录下建文件,返回目录句柄(drop 时自动清理)
3208    fn tmpdir(tag: &str) -> std::path::PathBuf {
3209        let mut d = std::env::temp_dir();
3210        d.push(format!("sml_test_{tag}_{}", std::process::id()));
3211        let _ = std::fs::remove_dir_all(&d);
3212        std::fs::create_dir_all(&d).expect("create tmpdir");
3213        d
3214    }
3215
3216    #[test]
3217    fn include_inlines_external_file() {
3218        let d = tmpdir("inline");
3219        std::fs::write(d.join("part.sml"), "port: 8080\n").unwrap();
3220        std::fs::write(d.join("main.sml"), "host: local\ninclude \"part.sml\"\n").unwrap();
3221
3222        let v = parse_file(d.join("main.sml")).unwrap();
3223        assert_eq!(v.get("host").unwrap().as_str(), Some("local"));
3224        assert_eq!(v.get("port"), Some(&Value::Int(8080)));
3225        let _ = std::fs::remove_dir_all(&d);
3226    }
3227
3228    #[test]
3229    fn include_at_prefix_is_equivalent() {
3230        let d = tmpdir("at");
3231        std::fs::write(d.join("p.sml"), "b: 2\n").unwrap();
3232        std::fs::write(d.join("m.sml"), "@include \"p.sml\"\n").unwrap();
3233        let v = parse_file(d.join("m.sml")).unwrap();
3234        assert_eq!(v.get("b"), Some(&Value::Int(2)));
3235        let _ = std::fs::remove_dir_all(&d);
3236    }
3237
3238    #[test]
3239    fn include_resolves_relative_to_including_file() {
3240        // 关键:相对路径按「被包含文件自身目录」解析,而非进程工作目录
3241        let d = tmpdir("nested");
3242        std::fs::create_dir_all(d.join("sub")).unwrap();
3243        std::fs::write(d.join("sub/leaf.sml"), "leaf: yes\n").unwrap();
3244        // mid 在根,include sub/mid2;mid2 在 sub 内,include leaf.sml(相对 sub)
3245        std::fs::write(d.join("sub/mid2.sml"), "include \"leaf.sml\"\n").unwrap();
3246        std::fs::write(d.join("main.sml"), "include \"sub/mid2.sml\"\n").unwrap();
3247
3248        let v = parse_file(d.join("main.sml")).unwrap();
3249        assert_eq!(
3250            v.get("leaf").unwrap().as_str(),
3251            Some("yes"),
3252            "嵌套 include 的路径应相对各自所在目录解析"
3253        );
3254        let _ = std::fs::remove_dir_all(&d);
3255    }
3256
3257    #[test]
3258    fn include_inside_block_injects_fields() {
3259        // 文本内联语义:可在块内注入一组字段
3260        let d = tmpdir("block");
3261        std::fs::write(d.join("fields.sml"), "region: cn-north-1\nzone: a\n").unwrap();
3262        std::fs::write(d.join("main.sml"), "server web {\ninclude \"fields.sml\"\nport: 8080\n}\n").unwrap();
3263
3264        let v = parse_file(d.join("main.sml")).unwrap();
3265        let server = v.get("server").expect("应有 server 块");
3266        assert_eq!(server.get("region").unwrap().as_str(), Some("cn-north-1"));
3267        assert_eq!(server.get("zone").unwrap().as_str(), Some("a"));
3268        assert_eq!(server.get("port"), Some(&Value::Int(8080)));
3269        let _ = std::fs::remove_dir_all(&d);
3270    }
3271
3272    #[test]
3273    fn include_detects_cycles() {
3274        let d = tmpdir("cycle");
3275        std::fs::write(d.join("a.sml"), "include \"b.sml\"\n").unwrap();
3276        std::fs::write(d.join("b.sml"), "include \"a.sml\"\n").unwrap();
3277        let err = parse_file(d.join("a.sml")).unwrap_err();
3278        assert!(err.contains("循环引用"), "应报循环引用,got: {err}");
3279        let _ = std::fs::remove_dir_all(&d);
3280    }
3281
3282    #[test]
3283    fn include_missing_file_is_error() {
3284        let d = tmpdir("missing");
3285        std::fs::write(d.join("m.sml"), "include \"nope.sml\"\n").unwrap();
3286        let err = parse_file(d.join("m.sml")).unwrap_err();
3287        assert!(err.contains("nope.sml"), "错误应含缺失文件名,got: {err}");
3288        let _ = std::fs::remove_dir_all(&d);
3289    }
3290
3291    #[test]
3292    fn hash_in_quoted_string_is_not_a_comment() {
3293        // 引号内的 # 不应被当成注释,否则 `include "a#b.sml"` 会被截断
3294        assert_eq!(strip_line_comment("k: \"a#b\""), "k: \"a#b\"");
3295        assert_eq!(strip_line_comment("k: v # comment"), "k: v ");
3296    }
3297
3298    #[test]
3299    fn include_line_is_not_confused_with_key_named_include() {
3300        // `key: include` 是指令吗?不是——前面有 key 与冒号
3301        assert_eq!(include_target("key: include"), None);
3302        assert_eq!(include_target("include \"a.sml\""), Some("a.sml".into()));
3303        assert_eq!(include_target("@include \"a.sml\""), Some("a.sml".into()));
3304        assert_eq!(include_target("# include \"a.sml\""), None, "注释行不生效");
3305    }
3306
3307    // ---------------- 邮箱 / 裸词中的 @ ----------------
3308
3309    #[test]
3310    fn email_in_bare_word_survives() {
3311        // 回归:裸词中的 `@` 曾被切成 At token,导致邮箱被截断为 `a`
3312        let v = parse("to: a@b.c\nfrom: \"sal <sal@mail.swebase.cn>\"\n").unwrap();
3313        assert_eq!(v.get("to").unwrap().as_str(), Some("a@b.c"), "got: {v:?}");
3314        assert_eq!(
3315            v.get("from").unwrap().as_str(),
3316            Some("sal <sal@mail.swebase.cn>"),
3317            "got: {v:?}"
3318        );
3319    }
3320
3321    #[test]
3322    fn email_roundtrips_through_to_sml() {
3323        let v = Value::Object(BTreeMap::from([(
3324            "to".to_string(),
3325            Value::Str("SALflake@qq.com".into()),
3326        )]));
3327        let back = parse(&to_sml(&v)).unwrap();
3328        assert_eq!(back, v, "邮箱必须能往返,got:\n{}", to_sml(&v));
3329    }
3330
3331    #[test]
3332    fn fragment_definition_still_works() {
3333        // 词首的 `@` 仍是片段定义标记,不能被上面的修改破坏。
3334        // 注:SML 的片段继承用法是「定义后作为值引用」(`k: &base`);
3335        // 块内裸写 `&base` 会被当作键,不属于本用例覆盖范围。
3336        let v = parse("@base { region: cn }\nregion: &base\n").unwrap();
3337        assert_eq!(
3338            v.get("region").unwrap().get("region").unwrap().as_str(),
3339            Some("cn"),
3340            "片段引用应展开为定义的内容,got: {v:?}"
3341        );
3342    }
3343
3344    // ---------------- 顶层数组 / 对象(与 to_sml 对称)----------------
3345
3346    #[test]
3347    fn toplevel_array_roundtrips() {
3348        // 回归:to_sml 能输出顶层数组,但 parse 曾只认键值块,
3349        // 导致「能写不能读」("期望键, 得 LBrack")。
3350        let v = Value::Array(vec![
3351            Value::Object(BTreeMap::from([
3352                ("ts".to_string(), Value::Str("2026-01-01".into())),
3353                ("to".to_string(), Value::Str("a@b.c".into())),
3354            ])),
3355            Value::Object(BTreeMap::from([
3356                ("ts".to_string(), Value::Str("2026-01-02".into())),
3357                ("to".to_string(), Value::Str("x@y.z".into())),
3358            ])),
3359        ]);
3360        let text = to_sml(&v);
3361        let back = parse(&text).unwrap();
3362        assert_eq!(back, v, "顶层对象数组必须能往返,got text:\n{text}");
3363    }
3364
3365    #[test]
3366    fn toplevel_array_of_scalars_roundtrips() {
3367        let v = Value::Array(vec![
3368            Value::Int(1),
3369            Value::Str("two".into()),
3370            Value::Bool(true),
3371        ]);
3372        let back = parse(&to_sml(&v)).unwrap();
3373        assert_eq!(back, v, "顶层标量数组必须能往返");
3374    }
3375
3376    #[test]
3377    fn toplevel_object_block_roundtrips() {
3378        let mut m = BTreeMap::new();
3379        m.insert("k".to_string(), Value::Int(1));
3380        let v = Value::Object(m);
3381        let back = parse(&to_sml(&v)).unwrap();
3382        assert_eq!(back, v, "顶层对象块必须能往返");
3383    }
3384
3385    #[test]
3386    fn toplevel_empty_array_roundtrips() {
3387        let v = Value::Array(vec![]);
3388        let back = parse(&to_sml(&v)).unwrap();
3389        assert_eq!(back, v, "空数组必须能往返");
3390    }
3391
3392    // ---------------- serde ----------------
3393
3394    #[cfg(feature = "serde")]
3395    #[test]
3396    fn serde_roundtrip_preserves_shape() {
3397        let v = parse("name: John\nage: 27\ntags: [a b]\nnested { k: v }\n").unwrap();
3398        let json = serde_json::to_string(&v).unwrap();
3399        // 自然形状:字符串就是字符串,数字就是数字,而非 {"Int":27}
3400        assert!(json.contains("\"name\":\"John\""), "got: {json}");
3401        assert!(json.contains("\"age\":27"), "got: {json}");
3402        assert!(json.contains("\"tags\":[\"a\",\"b\"]"), "got: {json}");
3403        assert!(json.contains("\"nested\":{\"k\":\"v\"}"), "got: {json}");
3404
3405        let back: Value = serde_json::from_str(&json).unwrap();
3406        assert_eq!(back, v, "serde 往返应还原原值");
3407    }
3408
3409    #[cfg(feature = "serde")]
3410    #[test]
3411    fn serde_deserializes_json_into_value() {
3412        let v: Value = serde_json::from_str(r#"{"s":"x","i":5,"f":1.5,"b":true,"n":null,"a":[1,2]}"#).unwrap();
3413        assert_eq!(v.get("s").unwrap().as_str(), Some("x"));
3414        assert_eq!(v.get("i"), Some(&Value::Int(5)));
3415        assert_eq!(v.get("f"), Some(&Value::Float(1.5)));
3416        assert_eq!(v.get("b"), Some(&Value::Bool(true)));
3417        assert_eq!(v.get("n"), Some(&Value::Null));
3418        assert!(matches!(v.get("a"), Some(Value::Array(a)) if a.len() == 2));
3419    }
3420
3421    #[test]
3422    fn nested_array_inside_object_inside_array_survives_roundtrip() {
3423        // 回归测试:数组元素是对象、对象里又有数组(如配置的条目列表)。
3424        // dump_inline 曾把嵌套数组缩略成 [..],导致 chunks 丢成 [".."]。
3425        let mut item = BTreeMap::new();
3426        item.insert("path".to_string(), Value::Str("a.txt".into()));
3427        item.insert(
3428            "chunks".to_string(),
3429            Value::Array(vec![
3430                Value::Str("c1".into()),
3431                Value::Str("c2".into()),
3432            ]),
3433        );
3434        let mut root = BTreeMap::new();
3435        root.insert(
3436            "entries".to_string(),
3437            Value::Array(vec![Value::Object(item)]),
3438        );
3439        let text = to_sml(&Value::Object(root));
3440        assert!(!text.contains("[..]"), "嵌套数组不得被缩略: {text}");
3441
3442        let back = parse(&text).unwrap();
3443        let chunks = back.get("entries").and_then(|e| match e {
3444            Value::Array(a) => a.first(),
3445            _ => None,
3446        });
3447        let chunks = match chunks {
3448            Some(Value::Object(m)) => m.get("chunks"),
3449            _ => None,
3450        };
3451        match chunks {
3452            Some(Value::Array(a)) => {
3453                assert_eq!(a.len(), 2, "两个块都应保留: {text}");
3454                assert_eq!(
3455                    a.iter().filter_map(|c| c.as_str()).collect::<Vec<_>>(),
3456                    vec!["c1", "c2"]
3457                );
3458            }
3459            other => panic!("chunks 应解析为数组,实际 {other:?}"),
3460        }
3461    }
3462
3463    #[test]
3464    fn utf8_in_quoted_string_survives_roundtrip() {
3465        // 回归测试:tokenizer 曾按字节 `as char` 逐个处理,
3466        // 把 UTF-8 多字节字符拆成 Latin-1 字符,导致
3467        // `"修复若干问题"` 解析后变成双编码乱码。
3468        let v = parse(r#"note: "修复若干问题""#).unwrap();
3469        assert_eq!(
3470            v.get("note").and_then(|x| x.as_str()),
3471            Some("修复若干问题"),
3472            "引号串中的中文不应被破坏"
3473        );
3474        // 裸词中文同样不能破坏
3475        let v2 = parse("region: 华北").unwrap();
3476        assert_eq!(v2.get("region").and_then(|x| x.as_str()), Some("华北"));
3477        // 转义 \u 序列
3478        let v3 = parse(r#"k: "\u{4fee}\u{590d}""#).unwrap();
3479        assert_eq!(v3.get("k").and_then(|x| x.as_str()), Some("修复"));
3480    }
3481
3482    #[test]
3483    fn parse_basic() {
3484        let text = "firstName: John\nage: 27\nisAlive: true\nspouse: null\n";
3485        let v = parse(text).unwrap();
3486        assert_eq!(v.get("firstName"), Some(&Value::Str("John".into())));
3487        assert_eq!(v.get("age"), Some(&Value::Int(27)));
3488        assert_eq!(v.get("isAlive"), Some(&Value::Bool(true)));
3489        assert_eq!(v.get("spouse"), Some(&Value::Null));
3490    }
3491
3492    #[test]
3493    fn parse_nested() {
3494        let text = "address:\n{\n    streetAddress: \"21 2nd Street\"\n    state: NY\n}\n";
3495        let v = parse(text).unwrap();
3496        assert_eq!(
3497            v.get("address.streetAddress"),
3498            Some(&Value::Str("21 2nd Street".into()))
3499        );
3500        assert_eq!(v.get("address.state"), Some(&Value::Str("NY".into())));
3501    }
3502
3503    #[test]
3504    fn parse_array() {
3505        let text = "phoneNumbers:\n[\n    { type: home }\n    { type: office }\n]\n";
3506        let v = parse(text).unwrap();
3507        if let Some(Value::Array(a)) = v.get("phoneNumbers") {
3508            assert_eq!(a.len(), 2);
3509            assert_eq!(a[0].get("type"), Some(&Value::Str("home".into())));
3510        } else {
3511            panic!("not array");
3512        }
3513    }
3514
3515    #[test]
3516    fn parse_fragment() {
3517        let text = "@base { region: cn-north-1 }\nserver web { &base }\n";
3518        let v = parse(text).unwrap();
3519        // &base 展开为字段 (键名 "&base", 值=片段对象), 与 Lua 实现一致
3520        assert_eq!(
3521            v.get("server.&base.region"),
3522            Some(&Value::Str("cn-north-1".into()))
3523        );
3524        assert_eq!(v.get("server.__type"), Some(&Value::Str("server".into())));
3525        assert_eq!(v.get("server.__name"), Some(&Value::Str("web".into())));
3526    }
3527
3528    #[test]
3529    fn roundtrip() {
3530        let text = "name: myapp\nport: 8080\nflags: [ a b c ]\n";
3531        let v = parse(text).unwrap();
3532        let out = to_sml(&v);
3533        let v2 = parse(&out).unwrap();
3534        assert_eq!(v, v2);
3535    }
3536
3537    #[test]
3538    fn env_inline() {
3539        // Rust 1.85+ 起 set_var 为 unsafe(与 edition 无关,2021/2024 均需)
3540        unsafe { std::env::set_var("SML_TEST_VAR", "hello") };
3541        let text = "greeting: $env.SML_TEST_VAR\n";
3542        let v = parse(text).unwrap();
3543        assert_eq!(v.get("greeting"), Some(&Value::Str("hello".into())));
3544    }
3545
3546    #[test]
3547    fn c_abi_json_bridge() {
3548        let text = "name: John\nage: 27\n";
3549        let v = parse(text).unwrap();
3550        let j = jsonify(&v);
3551        assert!(j.contains("\"name\":\"John\""));
3552        let back = json_to_value(&j).unwrap();
3553        assert_eq!(back, v);
3554    }
3555}