Skip to main content

sz_orm_model/
accessors.rs

1//! Accessors / Mutators + Attribute Casting
2//!
3//! 对应文档 6.8 节改进项 22(Accessors/Mutators)+ 23(Attribute Casting)。
4//!
5//! # 核心概念
6//!
7//! - **Accessor**:字段读取器(getter),从存储值转换为展示值
8//! - **Mutator**:字段设置器(setter),从输入值转换为存储值
9//! - **AttributeCaster**:字段类型转换器(数据库 <-> Rust 类型)
10//! - **AccessorRegistry**:Accessor/Mutator 注册中心
11//!
12//! # 设计灵感
13//!
14//! - Laravel Eloquent `getCasts()` / `mutators` / `accessors`
15//! - Doctrine `@Column(type="...")` 类型转换
16//! - Rails ActiveRecord `serialize` / `attr_accessor`
17//!
18//! # 使用示例
19//!
20//! ```no_run
21//! use sz_orm_model::accessors::{
22//!     AccessorRegistry, AttributeCaster, CastType,
23//! };
24//! use sz_orm_model::Value;
25//!
26//! let mut registry = AccessorRegistry::new();
27//!
28//! // 注册 is_admin 字段:数据库存 SMALLINT,读出时转为 bool
29//! registry.register_cast("is_admin", CastType::Boolean);
30//!
31//! // 注册 settings 字段:数据库存 TEXT,读出时解析为 JSON
32//! registry.register_cast("settings", CastType::Json);
33//!
34//! // 应用 casting(从数据库读出)
35//! let stored = Value::I64(1);
36//! let casted = registry.cast_read("is_admin", stored);
37//! assert_eq!(casted, Value::Bool(true));
38//! ```
39
40use crate::value::Value;
41use std::collections::HashMap;
42
43// ============================================================================
44// CastType — 字段类型转换枚举
45// ============================================================================
46
47/// 字段类型转换枚举
48///
49/// 定义字段在数据库存储与 Rust 类型之间的转换方式。
50#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
51pub enum CastType {
52    /// 转 i64(适用于 INTEGER/BIGINT → i64)
53    Integer,
54    /// 转 f64(适用于 FLOAT/DOUBLE → f64)
55    Float,
56    /// 转布尔(适用于 SMALLINT(0/1)/CHAR('Y'/'N') → bool)
57    Boolean,
58    /// 转字符串(适用于 TEXT/VARCHAR → String)
59    String,
60    /// 转 JSON(适用于 TEXT → JSON 反序列化)
61    Json,
62    /// 转 DateTime(适用于 TIMESTAMP → ISO8601 字符串)
63    DateTime,
64    /// 转 Date(适用于 DATE → YYYY-MM-DD 字符串)
65    Date,
66    /// 转 Time(适用于 TIME → HH:MM:SS 字符串)
67    Time,
68    /// 转 Bytes(适用于 BLOB → `Vec<u8>`)
69    Bytes,
70    /// 转 Array(适用于 JSON 数组 → `Vec<Value>`)
71    Array,
72}
73
74impl CastType {
75    /// 类型名称(用于错误信息)
76    pub fn name(&self) -> &'static str {
77        match self {
78            CastType::Integer => "integer",
79            CastType::Float => "float",
80            CastType::Boolean => "boolean",
81            CastType::String => "string",
82            CastType::Json => "json",
83            CastType::DateTime => "datetime",
84            CastType::Date => "date",
85            CastType::Time => "time",
86            CastType::Bytes => "bytes",
87            CastType::Array => "array",
88        }
89    }
90}
91
92// ============================================================================
93// Accessor / Mutator trait — 自定义字段读写器
94// ============================================================================
95
96/// 自定义字段读取器(Accessor / Getter)
97///
98/// 在从数据库读取字段值后调用,将存储值转换为展示值。
99pub trait Accessor: Send + Sync {
100    /// 字段名
101    fn field(&self) -> &str;
102
103    /// 读取转换:将存储值转换为展示值
104    fn read(&self, value: Value) -> Value;
105}
106
107/// 自定义字段设置器(Mutator / Setter)
108///
109/// 在写入数据库前调用,将输入值转换为存储值。
110pub trait Mutator: Send + Sync {
111    /// 字段名
112    fn field(&self) -> &str;
113
114    /// 写入转换:将输入值转换为存储值
115    fn write(&self, value: Value) -> Value;
116}
117
118// ============================================================================
119// 闭包风格的 Accessor / Mutator
120// ============================================================================
121
122/// 闭包风格 Accessor
123pub struct ClosureAccessor {
124    /// 字段名
125    pub field_name: String,
126    /// 读取转换闭包
127    pub reader: Box<dyn Fn(Value) -> Value + Send + Sync>,
128}
129
130impl ClosureAccessor {
131    /// 创建闭包 Accessor
132    pub fn new(
133        field: impl Into<String>,
134        reader: impl Fn(Value) -> Value + Send + Sync + 'static,
135    ) -> Self {
136        Self {
137            field_name: field.into(),
138            reader: Box::new(reader),
139        }
140    }
141}
142
143impl Accessor for ClosureAccessor {
144    fn field(&self) -> &str {
145        &self.field_name
146    }
147
148    fn read(&self, value: Value) -> Value {
149        (self.reader)(value)
150    }
151}
152
153/// 闭包风格 Mutator
154pub struct ClosureMutator {
155    /// 字段名
156    pub field_name: String,
157    /// 写入转换闭包
158    pub writer: Box<dyn Fn(Value) -> Value + Send + Sync>,
159}
160
161impl ClosureMutator {
162    /// 创建闭包 Mutator
163    pub fn new(
164        field: impl Into<String>,
165        writer: impl Fn(Value) -> Value + Send + Sync + 'static,
166    ) -> Self {
167        Self {
168            field_name: field.into(),
169            writer: Box::new(writer),
170        }
171    }
172}
173
174impl Mutator for ClosureMutator {
175    fn field(&self) -> &str {
176        &self.field_name
177    }
178
179    fn write(&self, value: Value) -> Value {
180        (self.writer)(value)
181    }
182}
183
184// ============================================================================
185// AttributeCaster — 类型转换器(数据库 <-> Rust 类型)
186// ============================================================================
187
188/// 类型转换器
189///
190/// 根据 `CastType` 将 Value 在数据库存储类型与 Rust 业务类型之间转换。
191pub struct AttributeCaster;
192
193impl AttributeCaster {
194    /// 从数据库读出时的类型转换(db → rust)
195    pub fn cast_read(value: Value, target: CastType) -> Value {
196        match target {
197            CastType::Integer => Self::to_integer(value),
198            CastType::Float => Self::to_float(value),
199            CastType::Boolean => Self::to_boolean(value),
200            CastType::String => Self::to_string_value(value),
201            CastType::Json => Self::to_json(value),
202            CastType::DateTime => Self::to_datetime(value),
203            CastType::Date => Self::to_date(value),
204            CastType::Time => Self::to_time(value),
205            CastType::Bytes => Self::to_bytes(value),
206            CastType::Array => Self::to_array(value),
207        }
208    }
209
210    /// 写入数据库时的类型转换(rust → db)
211    pub fn cast_write(value: Value, target: CastType) -> Value {
212        match target {
213            CastType::Integer => Self::to_integer(value),
214            CastType::Float => Self::to_float(value),
215            CastType::Boolean => Self::to_boolean_storage(value),
216            CastType::String => Self::to_string_value(value),
217            CastType::Json => Self::to_json_storage(value),
218            CastType::DateTime => Self::to_datetime_storage(value),
219            CastType::Date => Self::to_date_storage(value),
220            CastType::Time => Self::to_time_storage(value),
221            CastType::Bytes => Self::to_bytes(value),
222            CastType::Array => Self::to_array_storage(value),
223        }
224    }
225
226    // ===== 转换函数 =====
227
228    fn to_integer(value: Value) -> Value {
229        match value {
230            Value::I64(_) | Value::I32(_) | Value::I8(_) | Value::I16(_) => value,
231            Value::U32(v) => Value::I64(v as i64),
232            Value::U64(v) => Value::I64(v as i64),
233            Value::U8(v) => Value::I64(v as i64),
234            Value::U16(v) => Value::I64(v as i64),
235            Value::F32(v) => Value::I64(v as i64),
236            Value::F64(v) => Value::I64(v as i64),
237            Value::Bool(b) => Value::I64(if b { 1 } else { 0 }),
238            Value::String(s) => {
239                if let Ok(n) = s.trim().parse::<i64>() {
240                    Value::I64(n)
241                } else {
242                    Value::Null
243                }
244            }
245            Value::Null => Value::Null,
246            _ => Value::Null,
247        }
248    }
249
250    fn to_float(value: Value) -> Value {
251        match value {
252            Value::F32(_) | Value::F64(_) => value,
253            Value::I64(v) => Value::F64(v as f64),
254            Value::I32(v) => Value::F64(v as f64),
255            Value::I8(v) => Value::F64(v as f64),
256            Value::I16(v) => Value::F64(v as f64),
257            Value::U32(v) => Value::F64(v as f64),
258            Value::U64(v) => Value::F64(v as f64),
259            Value::U8(v) => Value::F64(v as f64),
260            Value::U16(v) => Value::F64(v as f64),
261            Value::Bool(b) => Value::F64(if b { 1.0 } else { 0.0 }),
262            Value::String(s) => {
263                if let Ok(n) = s.trim().parse::<f64>() {
264                    Value::F64(n)
265                } else {
266                    Value::Null
267                }
268            }
269            Value::Null => Value::Null,
270            _ => Value::Null,
271        }
272    }
273
274    fn to_boolean(value: Value) -> Value {
275        match value {
276            Value::Bool(_) => value,
277            Value::I64(v) => Value::Bool(v != 0),
278            Value::I32(v) => Value::Bool(v != 0),
279            Value::I8(v) => Value::Bool(v != 0),
280            Value::I16(v) => Value::Bool(v != 0),
281            Value::U32(v) => Value::Bool(v != 0),
282            Value::U64(v) => Value::Bool(v != 0),
283            Value::U8(v) => Value::Bool(v != 0),
284            Value::U16(v) => Value::Bool(v != 0),
285            Value::F32(v) => Value::Bool(v != 0.0),
286            Value::F64(v) => Value::Bool(v != 0.0),
287            Value::String(s) => {
288                let lower = s.trim().to_lowercase();
289                Value::Bool(matches!(
290                    lower.as_str(),
291                    "1" | "true" | "yes" | "on" | "y" | "t"
292                ))
293            }
294            Value::Null => Value::Null,
295            _ => Value::Null,
296        }
297    }
298
299    fn to_boolean_storage(value: Value) -> Value {
300        match value {
301            Value::Bool(b) => Value::I64(if b { 1 } else { 0 }),
302            Value::I64(_) | Value::I32(_) | Value::I8(_) | Value::I16(_) => value,
303            Value::U32(v) => Value::I64(if v != 0 { 1 } else { 0 }),
304            Value::U64(v) => Value::I64(if v != 0 { 1 } else { 0 }),
305            Value::U8(v) => Value::I64(if v != 0 { 1 } else { 0 }),
306            Value::U16(v) => Value::I64(if v != 0 { 1 } else { 0 }),
307            Value::F32(v) => Value::I64(if v != 0.0 { 1 } else { 0 }),
308            Value::F64(v) => Value::I64(if v != 0.0 { 1 } else { 0 }),
309            Value::String(s) => {
310                let lower = s.trim().to_lowercase();
311                Value::I64(
312                    if matches!(lower.as_str(), "1" | "true" | "yes" | "on" | "y" | "t") {
313                        1
314                    } else {
315                        0
316                    },
317                )
318            }
319            Value::Null => Value::Null,
320            _ => Value::Null,
321        }
322    }
323
324    fn to_string_value(value: Value) -> Value {
325        match value {
326            Value::String(_) => value,
327            Value::I64(v) => Value::String(v.to_string()),
328            Value::I32(v) => Value::String(v.to_string()),
329            Value::I8(v) => Value::String(v.to_string()),
330            Value::I16(v) => Value::String(v.to_string()),
331            Value::U32(v) => Value::String(v.to_string()),
332            Value::U64(v) => Value::String(v.to_string()),
333            Value::U8(v) => Value::String(v.to_string()),
334            Value::U16(v) => Value::String(v.to_string()),
335            Value::F32(v) => Value::String(v.to_string()),
336            Value::F64(v) => Value::String(v.to_string()),
337            Value::Bool(b) => Value::String(b.to_string()),
338            Value::Null => Value::Null,
339            other => Value::String(format!("{:?}", other)),
340        }
341    }
342
343    fn to_json(value: Value) -> Value {
344        match value {
345            Value::String(s) => {
346                // 校验是否为合法 JSON;合法则包装为 Value::Json,否则保留为 String
347                if serde_json::from_str::<serde_json::Value>(&s).is_ok() {
348                    Value::Json(s)
349                } else {
350                    Value::String(s)
351                }
352            }
353            Value::Json(s) => Value::Json(s),
354            other => Value::Json(value_to_json_string(&other)),
355        }
356    }
357
358    fn to_json_storage(value: Value) -> Value {
359        match value {
360            Value::Json(s) => Value::Json(s),
361            Value::String(s) => Value::Json(s),
362            other => Value::Json(value_to_json_string(&other)),
363        }
364    }
365
366    fn to_datetime(value: Value) -> Value {
367        match value {
368            Value::DateTime(s) => Value::DateTime(s),
369            Value::String(s) => Value::DateTime(s),
370            Value::Null => Value::Null,
371            other => Value::DateTime(format!("{:?}", other)),
372        }
373    }
374
375    fn to_datetime_storage(value: Value) -> Value {
376        match value {
377            Value::DateTime(s) => Value::DateTime(s),
378            Value::String(s) => Value::DateTime(s),
379            Value::Null => Value::Null,
380            other => Value::DateTime(format!("{:?}", other)),
381        }
382    }
383
384    fn to_date(value: Value) -> Value {
385        match value {
386            Value::Date(s) => Value::Date(s),
387            Value::String(s) => Value::Date(s),
388            Value::Null => Value::Null,
389            other => Value::Date(format!("{:?}", other)),
390        }
391    }
392
393    fn to_date_storage(value: Value) -> Value {
394        match value {
395            Value::Date(s) => Value::Date(s),
396            Value::String(s) => Value::Date(s),
397            Value::Null => Value::Null,
398            other => Value::Date(format!("{:?}", other)),
399        }
400    }
401
402    fn to_time(value: Value) -> Value {
403        match value {
404            Value::Time(s) => Value::Time(s),
405            Value::String(s) => Value::Time(s),
406            Value::Null => Value::Null,
407            other => Value::Time(format!("{:?}", other)),
408        }
409    }
410
411    fn to_time_storage(value: Value) -> Value {
412        match value {
413            Value::Time(s) => Value::Time(s),
414            Value::String(s) => Value::Time(s),
415            Value::Null => Value::Null,
416            other => Value::Time(format!("{:?}", other)),
417        }
418    }
419
420    fn to_bytes(value: Value) -> Value {
421        match value {
422            Value::Bytes(_) => value,
423            Value::String(s) => Value::Bytes(s.into_bytes()),
424            Value::Null => Value::Null,
425            _ => Value::Null,
426        }
427    }
428
429    fn to_array(value: Value) -> Value {
430        match value {
431            Value::Array(_) => value,
432            Value::Json(s) => {
433                // 尝试解析 JSON 数组;解析失败则包装为单元素数组
434                match serde_json::from_str::<Vec<serde_json::Value>>(&s) {
435                    Ok(json_arr) => {
436                        let items: Vec<Value> = json_arr.into_iter().map(json_to_value).collect();
437                        Value::Array(items)
438                    }
439                    Err(_) => Value::Array(vec![Value::Json(s)]),
440                }
441            }
442            Value::String(s) => {
443                // 尝试解析字符串为 JSON 数组;失败则包装为单元素数组
444                match serde_json::from_str::<Vec<serde_json::Value>>(&s) {
445                    Ok(json_arr) => {
446                        let items: Vec<Value> = json_arr.into_iter().map(json_to_value).collect();
447                        Value::Array(items)
448                    }
449                    Err(_) => Value::Array(vec![Value::String(s)]),
450                }
451            }
452            Value::Null => Value::Null,
453            other => Value::Array(vec![other]),
454        }
455    }
456
457    fn to_array_storage(value: Value) -> Value {
458        match value {
459            Value::Array(items) => {
460                // 序列化为合法 JSON 数组字符串存储
461                let json_arr: Vec<serde_json::Value> = items.iter().map(value_to_json).collect();
462                Value::Json(serde_json::to_string(&json_arr).unwrap_or_else(|_| "[]".to_string()))
463            }
464            other => Value::Json(value_to_json_string(&other)),
465        }
466    }
467}
468
469/// 将 `Value` 转换为 `serde_json::Value`
470///
471/// 用于 `to_array_storage` / `to_json_storage` 等场景,确保产生合法 JSON。
472fn value_to_json(value: &Value) -> serde_json::Value {
473    match value {
474        Value::Null => serde_json::Value::Null,
475        Value::Bool(b) => serde_json::Value::Bool(*b),
476        Value::I8(v) => serde_json::Value::Number((*v).into()),
477        Value::I16(v) => serde_json::Value::Number((*v).into()),
478        Value::I32(v) => serde_json::Value::Number((*v).into()),
479        Value::I64(v) => serde_json::Value::Number((*v).into()),
480        Value::U8(v) => serde_json::Value::Number((*v).into()),
481        Value::U16(v) => serde_json::Value::Number((*v).into()),
482        Value::U32(v) => serde_json::Value::Number((*v).into()),
483        Value::U64(v) => serde_json::Value::Number((*v).into()),
484        Value::F32(v) => serde_json::Number::from_f64(*v as f64)
485            .map(serde_json::Value::Number)
486            .unwrap_or(serde_json::Value::Null),
487        Value::F64(v) => serde_json::Number::from_f64(*v)
488            .map(serde_json::Value::Number)
489            .unwrap_or(serde_json::Value::Null),
490        Value::Decimal(s) => {
491            // 高精度十进制数:尝试作为数字,否则作为字符串
492            serde_json::from_str(s).unwrap_or_else(|_| serde_json::Value::String(s.clone()))
493        }
494        Value::String(s) => serde_json::Value::String(s.clone()),
495        Value::Bytes(b) => {
496            // 字节值:以 base64 编码字符串形式表示
497            use std::fmt::Write;
498            let mut s = String::with_capacity(b.len() * 2);
499            for byte in b {
500                let _ = write!(&mut s, "{:02x}", byte);
501            }
502            serde_json::Value::String(s)
503        }
504        Value::Uuid(s) => serde_json::Value::String(s.clone()),
505        Value::Date(s) => serde_json::Value::String(s.clone()),
506        Value::DateTime(s) => serde_json::Value::String(s.clone()),
507        Value::Time(s) => serde_json::Value::String(s.clone()),
508        Value::Json(s) => serde_json::from_str(s).unwrap_or(serde_json::Value::String(s.clone())),
509        Value::Array(items) => serde_json::Value::Array(items.iter().map(value_to_json).collect()),
510        Value::Object(map) => {
511            let mut obj = serde_json::Map::new();
512            for (k, v) in map {
513                obj.insert(k.clone(), value_to_json(v));
514            }
515            serde_json::Value::Object(obj)
516        }
517    }
518}
519
520/// 将 `Value` 转换为 JSON 字符串
521fn value_to_json_string(value: &Value) -> String {
522    serde_json::to_string(&value_to_json(value)).unwrap_or_else(|_| "null".to_string())
523}
524
525/// 将 `serde_json::Value` 转换为内部 `Value`
526///
527/// 用于 `to_array` 等场景,将解析出的 JSON 数组元素转换为内部 Value。
528fn json_to_value(jv: serde_json::Value) -> Value {
529    match jv {
530        serde_json::Value::Null => Value::Null,
531        serde_json::Value::Bool(b) => Value::Bool(b),
532        serde_json::Value::Number(n) => {
533            if let Some(i) = n.as_i64() {
534                Value::I64(i)
535            } else if let Some(u) = n.as_u64() {
536                Value::U64(u)
537            } else if let Some(f) = n.as_f64() {
538                Value::F64(f)
539            } else {
540                Value::Null
541            }
542        }
543        serde_json::Value::String(s) => Value::String(s),
544        serde_json::Value::Array(arr) => Value::Array(arr.into_iter().map(json_to_value).collect()),
545        serde_json::Value::Object(obj) => {
546            let mut map = std::collections::HashMap::new();
547            for (k, v) in obj {
548                map.insert(k, json_to_value(v));
549            }
550            Value::Object(map)
551        }
552    }
553}
554
555// ============================================================================
556// AccessorRegistry — 注册中心
557// ============================================================================
558
559/// Accessor / Mutator / Cast 注册中心
560///
561/// 管理字段级别的读取器、设置器、类型转换器。
562pub struct AccessorRegistry {
563    /// 字段读取器
564    accessors: HashMap<String, Box<dyn Accessor>>,
565    /// 字段设置器
566    mutators: HashMap<String, Box<dyn Mutator>>,
567    /// 字段类型转换
568    casts: HashMap<String, CastType>,
569}
570
571impl Default for AccessorRegistry {
572    fn default() -> Self {
573        Self::new()
574    }
575}
576
577impl AccessorRegistry {
578    /// 创建空注册中心
579    pub fn new() -> Self {
580        Self {
581            accessors: HashMap::new(),
582            mutators: HashMap::new(),
583            casts: HashMap::new(),
584        }
585    }
586
587    /// 注册 Accessor
588    pub fn register_accessor(&mut self, accessor: Box<dyn Accessor>) {
589        let field = accessor.field().to_string();
590        self.accessors.insert(field, accessor);
591    }
592
593    /// 注册 Mutator
594    pub fn register_mutator(&mut self, mutator: Box<dyn Mutator>) {
595        let field = mutator.field().to_string();
596        self.mutators.insert(field, mutator);
597    }
598
599    /// 注册类型转换
600    pub fn register_cast(&mut self, field: impl Into<String>, cast: CastType) {
601        self.casts.insert(field.into(), cast);
602    }
603
604    /// 应用读取流程:cast_read → accessor.read
605    pub fn read(&self, field: &str, value: Value) -> Value {
606        let v1 = if let Some(cast) = self.casts.get(field) {
607            AttributeCaster::cast_read(value, *cast)
608        } else {
609            value
610        };
611        if let Some(accessor) = self.accessors.get(field) {
612            accessor.read(v1)
613        } else {
614            v1
615        }
616    }
617
618    /// 应用写入流程:mutator.write → cast_write
619    pub fn write(&self, field: &str, value: Value) -> Value {
620        let v1 = if let Some(mutator) = self.mutators.get(field) {
621            mutator.write(value)
622        } else {
623            value
624        };
625        if let Some(cast) = self.casts.get(field) {
626            AttributeCaster::cast_write(v1, *cast)
627        } else {
628            v1
629        }
630    }
631
632    /// 仅应用类型转换(读取方向)
633    pub fn cast_read(&self, field: &str, value: Value) -> Value {
634        if let Some(cast) = self.casts.get(field) {
635            AttributeCaster::cast_read(value, *cast)
636        } else {
637            value
638        }
639    }
640
641    /// 仅应用类型转换(写入方向)
642    pub fn cast_write(&self, field: &str, value: Value) -> Value {
643        if let Some(cast) = self.casts.get(field) {
644            AttributeCaster::cast_write(value, *cast)
645        } else {
646            value
647        }
648    }
649
650    /// 检查字段是否已注册 Accessor
651    pub fn has_accessor(&self, field: &str) -> bool {
652        self.accessors.contains_key(field)
653    }
654
655    /// 检查字段是否已注册 Mutator
656    pub fn has_mutator(&self, field: &str) -> bool {
657        self.mutators.contains_key(field)
658    }
659
660    /// 检查字段是否已注册 Cast
661    pub fn has_cast(&self, field: &str) -> bool {
662        self.casts.contains_key(field)
663    }
664
665    /// 获取字段已注册的 CastType
666    pub fn get_cast(&self, field: &str) -> Option<CastType> {
667        self.casts.get(field).copied()
668    }
669
670    /// 已注册 Accessor 数量
671    pub fn accessor_count(&self) -> usize {
672        self.accessors.len()
673    }
674
675    /// 已注册 Mutator 数量
676    pub fn mutator_count(&self) -> usize {
677        self.mutators.len()
678    }
679
680    /// 已注册 Cast 数量
681    pub fn cast_count(&self) -> usize {
682        self.casts.len()
683    }
684}
685
686// ============================================================================
687// 单元测试
688// ============================================================================
689
690#[cfg(test)]
691mod tests {
692    use super::*;
693
694    // ===== CastType 测试 =====
695
696    #[test]
697    fn test_cast_type_name() {
698        assert_eq!(CastType::Integer.name(), "integer");
699        assert_eq!(CastType::Boolean.name(), "boolean");
700        assert_eq!(CastType::Json.name(), "json");
701        assert_eq!(CastType::DateTime.name(), "datetime");
702    }
703
704    // ===== AttributeCaster - Integer =====
705
706    #[test]
707    fn test_cast_to_integer_from_string() {
708        let v = AttributeCaster::cast_read(Value::String("42".to_string()), CastType::Integer);
709        assert_eq!(v, Value::I64(42));
710    }
711
712    #[test]
713    fn test_cast_to_integer_from_invalid_string() {
714        let v = AttributeCaster::cast_read(Value::String("abc".to_string()), CastType::Integer);
715        assert_eq!(v, Value::Null);
716    }
717
718    #[test]
719    fn test_cast_to_integer_from_bool() {
720        let v = AttributeCaster::cast_read(Value::Bool(true), CastType::Integer);
721        assert_eq!(v, Value::I64(1));
722    }
723
724    #[test]
725    fn test_cast_to_integer_from_float() {
726        let v = AttributeCaster::cast_read(Value::F64(3.7), CastType::Integer);
727        assert_eq!(v, Value::I64(3));
728    }
729
730    #[test]
731    fn test_cast_to_integer_preserves_i64() {
732        let v = AttributeCaster::cast_read(Value::I64(100), CastType::Integer);
733        assert_eq!(v, Value::I64(100));
734    }
735
736    // ===== AttributeCaster - Float =====
737
738    #[test]
739    fn test_cast_to_float_from_string() {
740        let v = AttributeCaster::cast_read(Value::String("3.15".to_string()), CastType::Float);
741        assert_eq!(v, Value::F64(3.15));
742    }
743
744    #[test]
745    fn test_cast_to_float_from_i64() {
746        let v = AttributeCaster::cast_read(Value::I64(42), CastType::Float);
747        assert_eq!(v, Value::F64(42.0));
748    }
749
750    // ===== AttributeCaster - Boolean =====
751
752    #[test]
753    fn test_cast_to_boolean_from_i64_one() {
754        let v = AttributeCaster::cast_read(Value::I64(1), CastType::Boolean);
755        assert_eq!(v, Value::Bool(true));
756    }
757
758    #[test]
759    fn test_cast_to_boolean_from_i64_zero() {
760        let v = AttributeCaster::cast_read(Value::I64(0), CastType::Boolean);
761        assert_eq!(v, Value::Bool(false));
762    }
763
764    #[test]
765    fn test_cast_to_boolean_from_string_true() {
766        let v = AttributeCaster::cast_read(Value::String("true".to_string()), CastType::Boolean);
767        assert_eq!(v, Value::Bool(true));
768    }
769
770    #[test]
771    fn test_cast_to_boolean_from_string_yes() {
772        let v = AttributeCaster::cast_read(Value::String("yes".to_string()), CastType::Boolean);
773        assert_eq!(v, Value::Bool(true));
774    }
775
776    #[test]
777    fn test_cast_to_boolean_from_string_on() {
778        let v = AttributeCaster::cast_read(Value::String("on".to_string()), CastType::Boolean);
779        assert_eq!(v, Value::Bool(true));
780    }
781
782    #[test]
783    fn test_cast_to_boolean_from_string_random() {
784        let v = AttributeCaster::cast_read(Value::String("random".to_string()), CastType::Boolean);
785        assert_eq!(v, Value::Bool(false));
786    }
787
788    #[test]
789    fn test_cast_to_boolean_preserves_bool() {
790        let v = AttributeCaster::cast_read(Value::Bool(true), CastType::Boolean);
791        assert_eq!(v, Value::Bool(true));
792    }
793
794    // ===== AttributeCaster - Boolean Storage(写入方向)=====
795
796    #[test]
797    fn test_cast_to_boolean_storage_from_bool() {
798        let v = AttributeCaster::cast_write(Value::Bool(true), CastType::Boolean);
799        assert_eq!(v, Value::I64(1));
800    }
801
802    #[test]
803    fn test_cast_to_boolean_storage_from_string() {
804        let v = AttributeCaster::cast_write(Value::String("yes".to_string()), CastType::Boolean);
805        assert_eq!(v, Value::I64(1));
806    }
807
808    // ===== AttributeCaster - String =====
809
810    #[test]
811    fn test_cast_to_string_from_i64() {
812        let v = AttributeCaster::cast_read(Value::I64(42), CastType::String);
813        assert_eq!(v, Value::String("42".to_string()));
814    }
815
816    #[test]
817    fn test_cast_to_string_from_bool() {
818        let v = AttributeCaster::cast_read(Value::Bool(true), CastType::String);
819        assert_eq!(v, Value::String("true".to_string()));
820    }
821
822    #[test]
823    fn test_cast_to_string_preserves_string() {
824        let v = AttributeCaster::cast_read(Value::String("hello".to_string()), CastType::String);
825        assert_eq!(v, Value::String("hello".to_string()));
826    }
827
828    // ===== AttributeCaster - Json =====
829
830    #[test]
831    fn test_cast_to_json_from_string() {
832        let v = AttributeCaster::cast_read(
833            Value::String(r#"{"key":"value"}"#.to_string()),
834            CastType::Json,
835        );
836        // 合法 JSON 字符串应转换为 Value::Json
837        assert!(matches!(v, Value::Json(_)));
838        if let Value::Json(s) = v {
839            // 验证 JSON 内容正确
840            let parsed: serde_json::Value = serde_json::from_str(&s).unwrap();
841            assert_eq!(parsed["key"], "value");
842        }
843    }
844
845    #[test]
846    fn test_cast_to_json_from_invalid_string() {
847        let v = AttributeCaster::cast_read(Value::String("not a json".to_string()), CastType::Json);
848        // 非法 JSON 字符串应保留为 String
849        assert!(matches!(v, Value::String(_)));
850    }
851
852    #[test]
853    fn test_cast_to_json_from_other() {
854        let v = AttributeCaster::cast_read(Value::I64(42), CastType::Json);
855        assert!(matches!(v, Value::Json(_)));
856        if let Value::Json(s) = v {
857            // 验证产生的 JSON 是合法的
858            let parsed: serde_json::Value = serde_json::from_str(&s).unwrap();
859            assert_eq!(parsed, serde_json::Value::Number(42.into()));
860        }
861    }
862
863    // ===== AttributeCaster - DateTime / Date / Time =====
864
865    #[test]
866    fn test_cast_to_datetime_from_string() {
867        let v = AttributeCaster::cast_read(
868            Value::String("2026-07-19T10:00:00Z".to_string()),
869            CastType::DateTime,
870        );
871        assert_eq!(v, Value::DateTime("2026-07-19T10:00:00Z".to_string()));
872    }
873
874    #[test]
875    fn test_cast_to_date_from_string() {
876        let v = AttributeCaster::cast_read(Value::String("2026-07-19".to_string()), CastType::Date);
877        assert_eq!(v, Value::Date("2026-07-19".to_string()));
878    }
879
880    #[test]
881    fn test_cast_to_time_from_string() {
882        let v = AttributeCaster::cast_read(Value::String("10:30:00".to_string()), CastType::Time);
883        assert_eq!(v, Value::Time("10:30:00".to_string()));
884    }
885
886    // ===== AttributeCaster - Bytes =====
887
888    #[test]
889    fn test_cast_to_bytes_from_string() {
890        let v = AttributeCaster::cast_read(Value::String("hello".to_string()), CastType::Bytes);
891        assert_eq!(v, Value::Bytes(b"hello".to_vec()));
892    }
893
894    #[test]
895    fn test_cast_to_bytes_preserves_bytes() {
896        let v = AttributeCaster::cast_read(Value::Bytes(b"data".to_vec()), CastType::Bytes);
897        assert_eq!(v, Value::Bytes(b"data".to_vec()));
898    }
899
900    // ===== AttributeCaster - Array =====
901
902    #[test]
903    fn test_cast_to_array_from_string() {
904        let v = AttributeCaster::cast_read(Value::String("item".to_string()), CastType::Array);
905        assert!(matches!(v, Value::Array(_)));
906        if let Value::Array(arr) = v {
907            assert_eq!(arr.len(), 1);
908        }
909    }
910
911    #[test]
912    fn test_cast_to_array_from_json_string() {
913        // 合法 JSON 数组字符串应被正确解析
914        let v = AttributeCaster::cast_read(Value::String("[1, 2, 3]".to_string()), CastType::Array);
915        assert!(matches!(v, Value::Array(_)));
916        if let Value::Array(arr) = v {
917            assert_eq!(arr.len(), 3);
918            assert_eq!(arr[0], Value::I64(1));
919            assert_eq!(arr[1], Value::I64(2));
920            assert_eq!(arr[2], Value::I64(3));
921        }
922    }
923
924    #[test]
925    fn test_cast_to_array_from_json_value() {
926        // Value::Json 中的合法 JSON 数组应被正确解析
927        let v =
928            AttributeCaster::cast_read(Value::Json(r#"["a", "b"]"#.to_string()), CastType::Array);
929        assert!(matches!(v, Value::Array(_)));
930        if let Value::Array(arr) = v {
931            assert_eq!(arr.len(), 2);
932            assert_eq!(arr[0], Value::String("a".to_string()));
933            assert_eq!(arr[1], Value::String("b".to_string()));
934        }
935    }
936
937    #[test]
938    fn test_cast_to_array_preserves_array() {
939        let arr = vec![Value::I64(1), Value::I64(2)];
940        let v = AttributeCaster::cast_read(Value::Array(arr.clone()), CastType::Array);
941        assert_eq!(v, Value::Array(arr));
942    }
943
944    #[test]
945    fn test_cast_to_array_storage_serializes_to_json() {
946        let v = AttributeCaster::cast_write(
947            Value::Array(vec![Value::I64(1), Value::I64(2)]),
948            CastType::Array,
949        );
950        assert!(matches!(v, Value::Json(_)));
951        if let Value::Json(s) = v {
952            // 验证产生的 JSON 是合法的 JSON 数组
953            let parsed: serde_json::Value = serde_json::from_str(&s).unwrap();
954            assert!(parsed.is_array());
955            assert_eq!(parsed[0], serde_json::Value::Number(1.into()));
956            assert_eq!(parsed[1], serde_json::Value::Number(2.into()));
957        }
958    }
959
960    #[test]
961    fn test_cast_to_array_storage_not_debug_format() {
962        // P2-5 回归测试:确保不再使用 Debug 格式([I64(1), I64(2)])
963        let v = AttributeCaster::cast_write(
964            Value::Array(vec![Value::I64(1), Value::I64(2)]),
965            CastType::Array,
966        );
967        if let Value::Json(s) = v {
968            // Debug 格式会包含 "I64" 字样,合法 JSON 不会
969            assert!(!s.contains("I64"), "JSON 不应包含 Debug 格式 I64: {}", s);
970            // 应为合法 JSON 数组
971            let parsed: serde_json::Value = serde_json::from_str(&s).unwrap();
972            assert!(parsed.is_array());
973        }
974    }
975
976    #[test]
977    fn test_cast_to_json_storage_from_other() {
978        let v = AttributeCaster::cast_write(Value::I64(42), CastType::Json);
979        assert!(matches!(v, Value::Json(_)));
980        if let Value::Json(s) = v {
981            // 验证产生的 JSON 是合法的
982            let parsed: serde_json::Value = serde_json::from_str(&s).unwrap();
983            assert_eq!(parsed, serde_json::Value::Number(42.into()));
984        }
985    }
986
987    // ===== ClosureAccessor / ClosureMutator =====
988
989    #[test]
990    fn test_closure_accessor() {
991        let accessor = ClosureAccessor::new("name", |v| match v {
992            Value::String(s) => Value::String(s.to_uppercase()),
993            other => other,
994        });
995        let v = accessor.read(Value::String("alice".to_string()));
996        assert_eq!(v, Value::String("ALICE".to_string()));
997        assert_eq!(accessor.field(), "name");
998    }
999
1000    #[test]
1001    fn test_closure_mutator() {
1002        let mutator = ClosureMutator::new("email", |v| match v {
1003            Value::String(s) => Value::String(s.to_lowercase()),
1004            other => other,
1005        });
1006        let v = mutator.write(Value::String("ALICE@EXAMPLE.COM".to_string()));
1007        assert_eq!(v, Value::String("alice@example.com".to_string()));
1008        assert_eq!(mutator.field(), "email");
1009    }
1010
1011    // ===== AccessorRegistry - 基本操作 =====
1012
1013    #[test]
1014    fn test_registry_empty() {
1015        let r = AccessorRegistry::new();
1016        assert_eq!(r.accessor_count(), 0);
1017        assert_eq!(r.mutator_count(), 0);
1018        assert_eq!(r.cast_count(), 0);
1019    }
1020
1021    #[test]
1022    fn test_registry_register_cast() {
1023        let mut r = AccessorRegistry::new();
1024        r.register_cast("is_admin", CastType::Boolean);
1025        assert!(r.has_cast("is_admin"));
1026        assert_eq!(r.get_cast("is_admin"), Some(CastType::Boolean));
1027        assert_eq!(r.cast_count(), 1);
1028    }
1029
1030    #[test]
1031    fn test_registry_register_accessor() {
1032        let mut r = AccessorRegistry::new();
1033        r.register_accessor(Box::new(ClosureAccessor::new("name", |v| match v {
1034            Value::String(s) => Value::String(s.to_uppercase()),
1035            other => other,
1036        })));
1037        assert!(r.has_accessor("name"));
1038        assert_eq!(r.accessor_count(), 1);
1039    }
1040
1041    #[test]
1042    fn test_registry_register_mutator() {
1043        let mut r = AccessorRegistry::new();
1044        r.register_mutator(Box::new(ClosureMutator::new("email", |v| match v {
1045            Value::String(s) => Value::String(s.to_lowercase()),
1046            other => other,
1047        })));
1048        assert!(r.has_mutator("email"));
1049        assert_eq!(r.mutator_count(), 1);
1050    }
1051
1052    // ===== AccessorRegistry - read/write 流程 =====
1053
1054    #[test]
1055    fn test_registry_read_applies_cast_then_accessor() {
1056        let mut r = AccessorRegistry::new();
1057        r.register_cast("is_admin", CastType::Boolean);
1058        r.register_accessor(Box::new(ClosureAccessor::new("is_admin", |v| {
1059            if v == Value::Bool(true) {
1060                Value::String("管理员".to_string())
1061            } else {
1062                Value::String("普通用户".to_string())
1063            }
1064        })));
1065
1066        // 读取:I64(1) → cast(Boolean) → Bool(true) → accessor → String("管理员")
1067        let v = r.read("is_admin", Value::I64(1));
1068        assert_eq!(v, Value::String("管理员".to_string()));
1069    }
1070
1071    #[test]
1072    fn test_registry_write_applies_mutator_then_cast() {
1073        let mut r = AccessorRegistry::new();
1074        r.register_cast("is_admin", CastType::Boolean);
1075        r.register_mutator(Box::new(ClosureMutator::new("is_admin", |v| match v {
1076            Value::String(s) => {
1077                let lower = s.to_lowercase();
1078                Value::Bool(lower == "admin" || lower == "true")
1079            }
1080            other => other,
1081        })));
1082
1083        // 写入:String("admin") → mutator → Bool(true) → cast → I64(1)
1084        let v = r.write("is_admin", Value::String("admin".to_string()));
1085        assert_eq!(v, Value::I64(1));
1086    }
1087
1088    #[test]
1089    fn test_registry_read_without_cast_or_accessor() {
1090        let r = AccessorRegistry::new();
1091        let v = r.read("any_field", Value::I64(42));
1092        assert_eq!(v, Value::I64(42));
1093    }
1094
1095    #[test]
1096    fn test_registry_write_without_cast_or_mutator() {
1097        let r = AccessorRegistry::new();
1098        let v = r.write("any_field", Value::I64(42));
1099        assert_eq!(v, Value::I64(42));
1100    }
1101
1102    #[test]
1103    fn test_registry_cast_read_only() {
1104        let mut r = AccessorRegistry::new();
1105        r.register_cast("is_admin", CastType::Boolean);
1106
1107        let v = r.cast_read("is_admin", Value::I64(1));
1108        assert_eq!(v, Value::Bool(true));
1109    }
1110
1111    #[test]
1112    fn test_registry_cast_write_only() {
1113        let mut r = AccessorRegistry::new();
1114        r.register_cast("is_admin", CastType::Boolean);
1115
1116        let v = r.cast_write("is_admin", Value::Bool(true));
1117        assert_eq!(v, Value::I64(1));
1118    }
1119
1120    // ===== 综合场景测试 =====
1121
1122    #[test]
1123    fn test_complex_user_model_scenario() {
1124        let mut r = AccessorRegistry::new();
1125
1126        // 1. is_admin: i64(0/1) ↔ bool
1127        r.register_cast("is_admin", CastType::Boolean);
1128
1129        // 2. email: 自动转小写
1130        r.register_mutator(Box::new(ClosureMutator::new("email", |v| match v {
1131            Value::String(s) => Value::String(s.to_lowercase()),
1132            other => other,
1133        })));
1134
1135        // 3. full_name: 拼接 first + last(演示 accessor)
1136        r.register_accessor(Box::new(ClosureAccessor::new(
1137            "full_name",
1138            |v| v, // 简化:直接返回
1139        )));
1140
1141        // 4. settings: JSON 字段
1142        r.register_cast("settings", CastType::Json);
1143
1144        // 5. created_at: DateTime
1145        r.register_cast("created_at", CastType::DateTime);
1146
1147        // 读取 is_admin
1148        let v = r.read("is_admin", Value::I64(1));
1149        assert_eq!(v, Value::Bool(true));
1150
1151        // 写入 email
1152        let v = r.write("email", Value::String("Alice@Example.COM".to_string()));
1153        assert_eq!(v, Value::String("alice@example.com".to_string()));
1154
1155        // 读取 settings(合法 JSON 应转换为 Value::Json)
1156        let v = r.read("settings", Value::String(r#"{"theme":"dark"}"#.to_string()));
1157        assert!(matches!(v, Value::Json(_)));
1158
1159        assert_eq!(r.accessor_count(), 1);
1160        assert_eq!(r.mutator_count(), 1);
1161        assert_eq!(r.cast_count(), 3);
1162    }
1163
1164    // ===== Default 测试 =====
1165
1166    #[test]
1167    fn test_default_is_empty() {
1168        let r = AccessorRegistry::default();
1169        assert_eq!(r.accessor_count(), 0);
1170        assert_eq!(r.mutator_count(), 0);
1171        assert_eq!(r.cast_count(), 0);
1172    }
1173}