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