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