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