Skip to main content

sml/
derive_macro.rs

1// ---------------------------------------------------------------------------
2// 自然序列化宏(derive)支持
3// ---------------------------------------------------------------------------
4
5use crate::value::Value;
6
7/// 把一个类型「自然地」序列化为 SML 值:
8/// 结构体 → 块、newtype → 透明、单元结构体 → 裸词、
9/// 枚举单元变体 → 裸词、带数据变体 → `__type` 块。
10///
11/// 通常用 `#[derive(SmlSerialize)]` 自动实现(`derive` feature 默认开启),
12/// 也可手动实现。支持的 `#[sml(...)]` 属性见 `swsml-derive` 的文档。
13pub trait SmlSerialize {
14    fn to_sml_value(&self) -> Value;
15
16    /// 序列化为 SML 文本(等价于 [`to_sml`] 作用于本类型生成的值)。
17    fn to_sml(&self) -> String {
18        crate::to_sml(&self.to_sml_value())
19    }
20}
21
22/// 从 SML 值反序列化(`#[derive(SmlDeserialize)]` 自动实现)。
23pub trait SmlDeserialize: Sized {
24    fn from_sml_value(v: &Value) -> Result<Self, String>;
25
26    /// 解析 SML 文本并反序列化。
27    fn from_sml(text: &str) -> Result<Self, String> {
28        let v = crate::parse(text).map_err(|e| format!("SML 解析失败: {e}"))?;
29        Self::from_sml_value(&v)
30    }
31}
32
33/// 序列化为 SML 文本 —— toml-rs 风格的顶层函数(等价于 [`SmlSerialize::to_sml`])。
34///
35/// 用法与 `toml::to_string` 一致(序列化不会失败,故直接返回 `String`):
36///
37/// ```rust
38/// # use sml::{SmlSerialize, SmlDeserialize};
39/// # #[derive(SmlSerialize, SmlDeserialize, Debug, PartialEq)]
40/// # struct Server { host: String, port: i32 }
41/// # let cfg = Server { host: "web.example".into(), port: 8080 };
42/// let text = sml::to_string(&cfg);
43/// assert_eq!(text, "host: web.example\nport: 8080\n");
44/// ```
45pub fn to_string<T: SmlSerialize + ?Sized>(value: &T) -> String {
46    crate::to_sml(&value.to_sml_value())
47}
48
49/// 解析 SML 文本并反序列化 —— toml-rs 风格的顶层函数(等价于 [`SmlDeserialize::from_sml`])。
50///
51/// ```rust
52/// # use sml::{SmlSerialize, SmlDeserialize};
53/// # #[derive(SmlSerialize, SmlDeserialize, Debug, PartialEq)]
54/// # struct Server { host: String, port: i32 }
55/// let back: Server = sml::from_str("host: web.example\nport: 8080\n").unwrap();
56/// assert_eq!(back.host, "web.example");
57/// assert_eq!(back.port, 8080);
58/// ```
59pub fn from_str<T: SmlDeserialize>(text: &str) -> Result<T, String> {
60    T::from_sml(text)
61}
62
63/// 宏生成代码引用的内部辅助(请勿直接使用)。
64#[doc(hidden)]
65pub mod __private {
66    use crate::value::Value;
67    use super::{SmlDeserialize, SmlSerialize};
68    use std::collections::{BTreeMap, HashMap};
69
70    /// 描述值的类型,用于错误信息。
71    pub fn describe_value(v: &Value) -> String {
72        match v {
73            Value::Null => "null".to_string(),
74            Value::Bool(b) => b.to_string(),
75            Value::Int(i) => i.to_string(),
76            Value::Float(f) => f.to_string(),
77            Value::Str(s) => format!("字符串 `{s}`"),
78            Value::Array(a) => format!("数组({} 个元素)", a.len()),
79            Value::Object(o) => format!("块({} 个键)", o.len()),
80        }
81    }
82
83    /// 取出 `_value` 键(枚举单值变体)。
84    pub fn take_value(m: &BTreeMap<String, Value>) -> Result<Value, String> {
85        m.get("_value")
86            .cloned()
87            .ok_or_else(|| "缺少 _value 键".to_string())
88    }
89
90    /// 取出 `_value` 键并断言为数组(枚举 tuple 变体)。
91    pub fn take_array(m: &BTreeMap<String, Value>) -> Result<Vec<Value>, String> {
92        match m.get("_value") {
93            Some(Value::Array(a)) => Ok(a.clone()),
94            Some(other) => Err(format!("_value 期望数组,实际为 {}", describe_value(other))),
95            None => Err("缺少 _value 键".to_string()),
96        }
97    }
98
99    /// `#[sml(flatten)]` 反序列化:把整个块交给子类型。
100    pub fn flatten_from<T: SmlDeserialize>(m: &BTreeMap<String, Value>) -> Result<T, String> {
101        T::from_sml_value(&Value::Object(m.clone()))
102    }
103
104    // ---- 基础类型 ----
105
106    impl SmlSerialize for bool {
107        #[inline]
108        fn to_sml_value(&self) -> Value {
109            Value::Bool(*self)
110        }
111    }
112    impl SmlDeserialize for bool {
113        #[inline]
114        fn from_sml_value(v: &Value) -> Result<Self, String> {
115            match v {
116                Value::Bool(b) => Ok(*b),
117                other => Err(format!("期望布尔,实际为 {}", describe_value(other))),
118            }
119        }
120    }
121
122    macro_rules! impl_int {
123        ($($t:ty),* $(,)?) => {$(
124            impl SmlSerialize for $t {
125                #[inline]
126                fn to_sml_value(&self) -> Value { Value::Int(*self as i64) }
127            }
128            impl SmlDeserialize for $t {
129                #[inline]
130                fn from_sml_value(v: &Value) -> Result<Self, String> {
131                    match v {
132                        Value::Int(i) => <$t>::try_from(*i)
133                            .map_err(|_| format!("整数 {i} 超出 {} 范围", stringify!($t))),
134                        Value::Float(f)
135                            if f.fract() == 0.0
136                                && *f >= <$t>::MIN as f64
137                                && *f <= <$t>::MAX as f64 => Ok(*f as $t),
138                        Value::Float(f) => Err(format!("期望整数,实际为小数 {f}")),
139                        other => Err(format!("期望整数,实际为 {}", describe_value(other))),
140                    }
141                }
142            }
143        )*};
144    }
145    impl_int!(i8, i16, i32, i64, isize, u8, u16, u32, usize);
146
147    impl SmlSerialize for u64 {
148        #[inline]
149        fn to_sml_value(&self) -> Value {
150            i64::try_from(*self).map(Value::Int).unwrap_or_else(|_| Value::Float(*self as f64))
151        }
152    }
153    impl SmlDeserialize for u64 {
154        #[inline]
155        fn from_sml_value(v: &Value) -> Result<Self, String> {
156            match v {
157                Value::Int(i) => u64::try_from(*i).map_err(|_| format!("整数 {i} 为负数,超出 u64 范围")),
158                Value::Float(f) if f.fract() == 0.0 && *f >= 0.0 => Ok(*f as u64),
159                Value::Float(f) => Err(format!("期望非负整数,实际为 {f}")),
160                other => Err(format!("期望整数,实际为 {}", describe_value(other))),
161            }
162        }
163    }
164
165    macro_rules! impl_big {
166        ($($t:ty),* $(,)?) => {$(
167            impl SmlSerialize for $t {
168                #[inline]
169                fn to_sml_value(&self) -> Value {
170                    i64::try_from(*self).map(Value::Int).unwrap_or_else(|_| Value::Float(*self as f64))
171                }
172            }
173            impl SmlDeserialize for $t {
174                #[inline]
175                fn from_sml_value(v: &Value) -> Result<Self, String> {
176                    match v {
177                        Value::Int(i) => Ok(*i as $t),
178                        Value::Float(f) if f.fract() == 0.0 => Ok(*f as $t),
179                        Value::Float(f) => Err(format!("期望整数,实际为小数 {f}")),
180                        other => Err(format!("期望整数,实际为 {}", describe_value(other))),
181                    }
182                }
183            }
184        )*};
185    }
186    impl_big!(i128, u128);
187
188    macro_rules! impl_float {
189        ($($t:ty),* $(,)?) => {$(
190            impl SmlSerialize for $t {
191                #[inline]
192                fn to_sml_value(&self) -> Value { Value::Float(*self as f64) }
193            }
194            impl SmlDeserialize for $t {
195                #[inline]
196                fn from_sml_value(v: &Value) -> Result<Self, String> {
197                    match v {
198                        Value::Int(i) => Ok(*i as $t),
199                        Value::Float(f) => Ok(*f as $t),
200                        other => Err(format!("期望数字,实际为 {}", describe_value(other))),
201                    }
202                }
203            }
204        )*};
205    }
206    impl_float!(f32, f64);
207
208    impl SmlSerialize for char {
209        #[inline]
210        fn to_sml_value(&self) -> Value {
211            Value::Str(self.to_string())
212        }
213    }
214    impl SmlDeserialize for char {
215        #[inline]
216        fn from_sml_value(v: &Value) -> Result<Self, String> {
217            match v {
218                Value::Str(s) => {
219                    let mut it = s.chars();
220                    match (it.next(), it.next()) {
221                        (Some(c), None) => Ok(c),
222                        _ => Err(format!("期望单个字符,实际为 `{s}`")),
223                    }
224                }
225                other => Err(format!("期望字符串,实际为 {}", describe_value(other))),
226            }
227        }
228    }
229
230    impl SmlSerialize for String {
231        #[inline]
232        fn to_sml_value(&self) -> Value {
233            Value::Str(self.clone())
234        }
235    }
236    impl SmlDeserialize for String {
237        #[inline]
238        fn from_sml_value(v: &Value) -> Result<Self, String> {
239            match v {
240                Value::Str(s) => Ok(s.clone()),
241                other => Err(format!("期望字符串,实际为 {}", describe_value(other))),
242            }
243        }
244    }
245
246    impl SmlSerialize for str {
247        #[inline]
248        fn to_sml_value(&self) -> Value {
249            Value::Str(self.to_string())
250        }
251    }
252
253    impl SmlSerialize for &str {
254        #[inline]
255        fn to_sml_value(&self) -> Value {
256            Value::Str(self.to_string())
257        }
258    }
259
260    impl SmlSerialize for () {
261        #[inline]
262        fn to_sml_value(&self) -> Value {
263            Value::Null
264        }
265    }
266    impl SmlDeserialize for () {
267        #[inline]
268        fn from_sml_value(v: &Value) -> Result<Self, String> {
269            match v {
270                Value::Null => Ok(()),
271                other => Err(format!("期望 null,实际为 {}", describe_value(other))),
272            }
273        }
274    }
275
276    impl SmlSerialize for Value {
277        #[inline]
278        fn to_sml_value(&self) -> Value {
279            self.clone()
280        }
281    }
282    impl SmlDeserialize for Value {
283        #[inline]
284        fn from_sml_value(v: &Value) -> Result<Self, String> {
285            Ok(v.clone())
286        }
287    }
288
289    impl<T: SmlSerialize> SmlSerialize for Option<T> {
290        #[inline]
291        fn to_sml_value(&self) -> Value {
292            match self {
293                Some(v) => v.to_sml_value(),
294                None => Value::Null,
295            }
296        }
297    }
298    impl<T: SmlDeserialize> SmlDeserialize for Option<T> {
299        #[inline]
300        fn from_sml_value(v: &Value) -> Result<Self, String> {
301            match v {
302                Value::Null => Ok(None),
303                other => Ok(Some(T::from_sml_value(other)?)),
304            }
305        }
306    }
307
308    impl<T: SmlSerialize> SmlSerialize for Vec<T> {
309        #[inline]
310        fn to_sml_value(&self) -> Value {
311            Value::Array(self.iter().map(SmlSerialize::to_sml_value).collect())
312        }
313    }
314    impl<T: SmlDeserialize> SmlDeserialize for Vec<T> {
315        #[inline]
316        fn from_sml_value(v: &Value) -> Result<Self, String> {
317            match v {
318                Value::Array(a) => a.iter().map(SmlDeserialize::from_sml_value).collect(),
319                other => Err(format!("期望数组,实际为 {}", describe_value(other))),
320            }
321        }
322    }
323
324    impl<T: SmlSerialize> SmlSerialize for Box<T> {
325        #[inline]
326        fn to_sml_value(&self) -> Value {
327            (**self).to_sml_value()
328        }
329    }
330    impl<T: SmlDeserialize> SmlDeserialize for Box<T> {
331        #[inline]
332        fn from_sml_value(v: &Value) -> Result<Self, String> {
333            Ok(Box::new(T::from_sml_value(v)?))
334        }
335    }
336
337    impl<V: SmlSerialize> SmlSerialize for BTreeMap<String, V> {
338        #[inline]
339        fn to_sml_value(&self) -> Value {
340            Value::Object(
341                self.iter()
342                    .map(|(k, v)| (k.clone(), v.to_sml_value()))
343                    .collect(),
344            )
345        }
346    }
347    impl<V: SmlDeserialize> SmlDeserialize for BTreeMap<String, V> {
348        #[inline]
349        fn from_sml_value(v: &Value) -> Result<Self, String> {
350            match v {
351                Value::Object(m) => {
352                    let mut out = BTreeMap::new();
353                    for (k, val) in m {
354                        out.insert(k.clone(), V::from_sml_value(val)?);
355                    }
356                    Ok(out)
357                }
358                other => Err(format!("期望块(object),实际为 {}", describe_value(other))),
359            }
360        }
361    }
362
363    impl<V: SmlSerialize> SmlSerialize for HashMap<String, V> {
364        #[inline]
365        fn to_sml_value(&self) -> Value {
366            Value::Object(
367                self.iter()
368                    .map(|(k, v)| (k.clone(), v.to_sml_value()))
369                    .collect(),
370            )
371        }
372    }
373    impl<V: SmlDeserialize> SmlDeserialize for HashMap<String, V> {
374        #[inline]
375        fn from_sml_value(v: &Value) -> Result<Self, String> {
376            match v {
377                Value::Object(m) => {
378                    let mut out = HashMap::new();
379                    for (k, val) in m {
380                        out.insert(k.clone(), V::from_sml_value(val)?);
381                    }
382                    Ok(out)
383                }
384                other => Err(format!("期望块(object),实际为 {}", describe_value(other))),
385            }
386        }
387    }
388}