Skip to main content

sz_orm_core/
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_core::accessors::{
22//!     AccessorRegistry, AttributeCaster, CastType,
23//! };
24//! use sz_orm_core::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        #[cfg(feature = "perf-box-str")]
496        Value::BoxedStr(s) => serde_json::Value::String(s.to_string()),
497        Value::Bytes(b) => {
498            // 字节值:以 base64 编码字符串形式表示
499            use std::fmt::Write;
500            let mut s = String::with_capacity(b.len() * 2);
501            for byte in b {
502                let _ = write!(&mut s, "{:02x}", byte);
503            }
504            serde_json::Value::String(s)
505        }
506        Value::Uuid(s) => serde_json::Value::String(s.clone()),
507        Value::Date(s) => serde_json::Value::String(s.clone()),
508        Value::DateTime(s) => serde_json::Value::String(s.clone()),
509        Value::Time(s) => serde_json::Value::String(s.clone()),
510        Value::Json(s) => serde_json::from_str(s).unwrap_or(serde_json::Value::String(s.clone())),
511        Value::Array(items) => serde_json::Value::Array(items.iter().map(value_to_json).collect()),
512        Value::Object(map) => {
513            let mut obj = serde_json::Map::new();
514            for (k, v) in map {
515                obj.insert(k.clone(), value_to_json(v));
516            }
517            serde_json::Value::Object(obj)
518        }
519    }
520}
521
522/// 将 `Value` 转换为 JSON 字符串
523fn value_to_json_string(value: &Value) -> String {
524    serde_json::to_string(&value_to_json(value)).unwrap_or_else(|_| "null".to_string())
525}
526
527/// 将 `serde_json::Value` 转换为内部 `Value`
528///
529/// 用于 `to_array` 等场景,将解析出的 JSON 数组元素转换为内部 Value。
530fn json_to_value(jv: serde_json::Value) -> Value {
531    match jv {
532        serde_json::Value::Null => Value::Null,
533        serde_json::Value::Bool(b) => Value::Bool(b),
534        serde_json::Value::Number(n) => {
535            if let Some(i) = n.as_i64() {
536                Value::I64(i)
537            } else if let Some(u) = n.as_u64() {
538                Value::U64(u)
539            } else if let Some(f) = n.as_f64() {
540                Value::F64(f)
541            } else {
542                Value::Null
543            }
544        }
545        serde_json::Value::String(s) => Value::String(s),
546        serde_json::Value::Array(arr) => Value::Array(arr.into_iter().map(json_to_value).collect()),
547        serde_json::Value::Object(obj) => {
548            let mut map = std::collections::HashMap::new();
549            for (k, v) in obj {
550                map.insert(k, json_to_value(v));
551            }
552            Value::Object(map)
553        }
554    }
555}
556
557// ============================================================================
558// AccessorRegistry — 注册中心
559// ============================================================================
560
561/// Accessor / Mutator / Cast 注册中心
562///
563/// 管理字段级别的读取器、设置器、类型转换器。
564pub struct AccessorRegistry {
565    /// 字段读取器
566    accessors: HashMap<String, Box<dyn Accessor>>,
567    /// 字段设置器
568    mutators: HashMap<String, Box<dyn Mutator>>,
569    /// 字段类型转换
570    casts: HashMap<String, CastType>,
571}
572
573impl Default for AccessorRegistry {
574    fn default() -> Self {
575        Self::new()
576    }
577}
578
579impl AccessorRegistry {
580    /// 创建空注册中心
581    pub fn new() -> Self {
582        Self {
583            accessors: HashMap::new(),
584            mutators: HashMap::new(),
585            casts: HashMap::new(),
586        }
587    }
588
589    /// 注册 Accessor
590    pub fn register_accessor(&mut self, accessor: Box<dyn Accessor>) {
591        let field = accessor.field().to_string();
592        self.accessors.insert(field, accessor);
593    }
594
595    /// 注册 Mutator
596    pub fn register_mutator(&mut self, mutator: Box<dyn Mutator>) {
597        let field = mutator.field().to_string();
598        self.mutators.insert(field, mutator);
599    }
600
601    /// 注册类型转换
602    pub fn register_cast(&mut self, field: impl Into<String>, cast: CastType) {
603        self.casts.insert(field.into(), cast);
604    }
605
606    /// 应用读取流程:cast_read → accessor.read
607    pub fn read(&self, field: &str, value: Value) -> Value {
608        let v1 = if let Some(cast) = self.casts.get(field) {
609            AttributeCaster::cast_read(value, *cast)
610        } else {
611            value
612        };
613        if let Some(accessor) = self.accessors.get(field) {
614            accessor.read(v1)
615        } else {
616            v1
617        }
618    }
619
620    /// 应用写入流程:mutator.write → cast_write
621    pub fn write(&self, field: &str, value: Value) -> Value {
622        let v1 = if let Some(mutator) = self.mutators.get(field) {
623            mutator.write(value)
624        } else {
625            value
626        };
627        if let Some(cast) = self.casts.get(field) {
628            AttributeCaster::cast_write(v1, *cast)
629        } else {
630            v1
631        }
632    }
633
634    /// 仅应用类型转换(读取方向)
635    pub fn cast_read(&self, field: &str, value: Value) -> Value {
636        if let Some(cast) = self.casts.get(field) {
637            AttributeCaster::cast_read(value, *cast)
638        } else {
639            value
640        }
641    }
642
643    /// 仅应用类型转换(写入方向)
644    pub fn cast_write(&self, field: &str, value: Value) -> Value {
645        if let Some(cast) = self.casts.get(field) {
646            AttributeCaster::cast_write(value, *cast)
647        } else {
648            value
649        }
650    }
651
652    /// 检查字段是否已注册 Accessor
653    pub fn has_accessor(&self, field: &str) -> bool {
654        self.accessors.contains_key(field)
655    }
656
657    /// 检查字段是否已注册 Mutator
658    pub fn has_mutator(&self, field: &str) -> bool {
659        self.mutators.contains_key(field)
660    }
661
662    /// 检查字段是否已注册 Cast
663    pub fn has_cast(&self, field: &str) -> bool {
664        self.casts.contains_key(field)
665    }
666
667    /// 获取字段已注册的 CastType
668    pub fn get_cast(&self, field: &str) -> Option<CastType> {
669        self.casts.get(field).copied()
670    }
671
672    /// 已注册 Accessor 数量
673    pub fn accessor_count(&self) -> usize {
674        self.accessors.len()
675    }
676
677    /// 已注册 Mutator 数量
678    pub fn mutator_count(&self) -> usize {
679        self.mutators.len()
680    }
681
682    /// 已注册 Cast 数量
683    pub fn cast_count(&self) -> usize {
684        self.casts.len()
685    }
686}
687
688// ============================================================================
689// 单元测试
690// ============================================================================
691
692#[cfg(test)]
693mod tests {
694    use super::*;
695
696    // ===== CastType 测试 =====
697
698    #[test]
699    fn test_cast_type_name() {
700        assert_eq!(CastType::Integer.name(), "integer");
701        assert_eq!(CastType::Boolean.name(), "boolean");
702        assert_eq!(CastType::Json.name(), "json");
703        assert_eq!(CastType::DateTime.name(), "datetime");
704    }
705
706    // ===== AttributeCaster - Integer =====
707
708    #[test]
709    fn test_cast_to_integer_from_string() {
710        let v = AttributeCaster::cast_read(Value::String("42".to_string()), CastType::Integer);
711        assert_eq!(v, Value::I64(42));
712    }
713
714    #[test]
715    fn test_cast_to_integer_from_invalid_string() {
716        let v = AttributeCaster::cast_read(Value::String("abc".to_string()), CastType::Integer);
717        assert_eq!(v, Value::Null);
718    }
719
720    #[test]
721    fn test_cast_to_integer_from_bool() {
722        let v = AttributeCaster::cast_read(Value::Bool(true), CastType::Integer);
723        assert_eq!(v, Value::I64(1));
724    }
725
726    #[test]
727    fn test_cast_to_integer_from_float() {
728        let v = AttributeCaster::cast_read(Value::F64(3.7), CastType::Integer);
729        assert_eq!(v, Value::I64(3));
730    }
731
732    #[test]
733    fn test_cast_to_integer_preserves_i64() {
734        let v = AttributeCaster::cast_read(Value::I64(100), CastType::Integer);
735        assert_eq!(v, Value::I64(100));
736    }
737
738    // ===== AttributeCaster - Float =====
739
740    #[test]
741    fn test_cast_to_float_from_string() {
742        let v = AttributeCaster::cast_read(Value::String("3.15".to_string()), CastType::Float);
743        assert_eq!(v, Value::F64(3.15));
744    }
745
746    #[test]
747    fn test_cast_to_float_from_i64() {
748        let v = AttributeCaster::cast_read(Value::I64(42), CastType::Float);
749        assert_eq!(v, Value::F64(42.0));
750    }
751
752    // ===== AttributeCaster - Boolean =====
753
754    #[test]
755    fn test_cast_to_boolean_from_i64_one() {
756        let v = AttributeCaster::cast_read(Value::I64(1), CastType::Boolean);
757        assert_eq!(v, Value::Bool(true));
758    }
759
760    #[test]
761    fn test_cast_to_boolean_from_i64_zero() {
762        let v = AttributeCaster::cast_read(Value::I64(0), CastType::Boolean);
763        assert_eq!(v, Value::Bool(false));
764    }
765
766    #[test]
767    fn test_cast_to_boolean_from_string_true() {
768        let v = AttributeCaster::cast_read(Value::String("true".to_string()), CastType::Boolean);
769        assert_eq!(v, Value::Bool(true));
770    }
771
772    #[test]
773    fn test_cast_to_boolean_from_string_yes() {
774        let v = AttributeCaster::cast_read(Value::String("yes".to_string()), CastType::Boolean);
775        assert_eq!(v, Value::Bool(true));
776    }
777
778    #[test]
779    fn test_cast_to_boolean_from_string_on() {
780        let v = AttributeCaster::cast_read(Value::String("on".to_string()), CastType::Boolean);
781        assert_eq!(v, Value::Bool(true));
782    }
783
784    #[test]
785    fn test_cast_to_boolean_from_string_random() {
786        let v = AttributeCaster::cast_read(Value::String("random".to_string()), CastType::Boolean);
787        assert_eq!(v, Value::Bool(false));
788    }
789
790    #[test]
791    fn test_cast_to_boolean_preserves_bool() {
792        let v = AttributeCaster::cast_read(Value::Bool(true), CastType::Boolean);
793        assert_eq!(v, Value::Bool(true));
794    }
795
796    // ===== AttributeCaster - Boolean Storage(写入方向)=====
797
798    #[test]
799    fn test_cast_to_boolean_storage_from_bool() {
800        let v = AttributeCaster::cast_write(Value::Bool(true), CastType::Boolean);
801        assert_eq!(v, Value::I64(1));
802    }
803
804    #[test]
805    fn test_cast_to_boolean_storage_from_string() {
806        let v = AttributeCaster::cast_write(Value::String("yes".to_string()), CastType::Boolean);
807        assert_eq!(v, Value::I64(1));
808    }
809
810    // ===== AttributeCaster - String =====
811
812    #[test]
813    fn test_cast_to_string_from_i64() {
814        let v = AttributeCaster::cast_read(Value::I64(42), CastType::String);
815        assert_eq!(v, Value::String("42".to_string()));
816    }
817
818    #[test]
819    fn test_cast_to_string_from_bool() {
820        let v = AttributeCaster::cast_read(Value::Bool(true), CastType::String);
821        assert_eq!(v, Value::String("true".to_string()));
822    }
823
824    #[test]
825    fn test_cast_to_string_preserves_string() {
826        let v = AttributeCaster::cast_read(Value::String("hello".to_string()), CastType::String);
827        assert_eq!(v, Value::String("hello".to_string()));
828    }
829
830    // ===== AttributeCaster - Json =====
831
832    #[test]
833    fn test_cast_to_json_from_string() {
834        let v = AttributeCaster::cast_read(
835            Value::String(r#"{"key":"value"}"#.to_string()),
836            CastType::Json,
837        );
838        // 合法 JSON 字符串应转换为 Value::Json
839        assert!(matches!(v, Value::Json(_)));
840        if let Value::Json(s) = v {
841            // 验证 JSON 内容正确
842            let parsed: serde_json::Value = serde_json::from_str(&s).unwrap();
843            assert_eq!(parsed["key"], "value");
844        }
845    }
846
847    #[test]
848    fn test_cast_to_json_from_invalid_string() {
849        let v = AttributeCaster::cast_read(Value::String("not a json".to_string()), CastType::Json);
850        // 非法 JSON 字符串应保留为 String
851        assert!(matches!(v, Value::String(_)));
852    }
853
854    #[test]
855    fn test_cast_to_json_from_other() {
856        let v = AttributeCaster::cast_read(Value::I64(42), CastType::Json);
857        assert!(matches!(v, Value::Json(_)));
858        if let Value::Json(s) = v {
859            // 验证产生的 JSON 是合法的
860            let parsed: serde_json::Value = serde_json::from_str(&s).unwrap();
861            assert_eq!(parsed, serde_json::Value::Number(42.into()));
862        }
863    }
864
865    // ===== AttributeCaster - DateTime / Date / Time =====
866
867    #[test]
868    fn test_cast_to_datetime_from_string() {
869        let v = AttributeCaster::cast_read(
870            Value::String("2026-07-19T10:00:00Z".to_string()),
871            CastType::DateTime,
872        );
873        assert_eq!(v, Value::DateTime("2026-07-19T10:00:00Z".to_string()));
874    }
875
876    #[test]
877    fn test_cast_to_date_from_string() {
878        let v = AttributeCaster::cast_read(Value::String("2026-07-19".to_string()), CastType::Date);
879        assert_eq!(v, Value::Date("2026-07-19".to_string()));
880    }
881
882    #[test]
883    fn test_cast_to_time_from_string() {
884        let v = AttributeCaster::cast_read(Value::String("10:30:00".to_string()), CastType::Time);
885        assert_eq!(v, Value::Time("10:30:00".to_string()));
886    }
887
888    // ===== AttributeCaster - Bytes =====
889
890    #[test]
891    fn test_cast_to_bytes_from_string() {
892        let v = AttributeCaster::cast_read(Value::String("hello".to_string()), CastType::Bytes);
893        assert_eq!(v, Value::Bytes(b"hello".to_vec()));
894    }
895
896    #[test]
897    fn test_cast_to_bytes_preserves_bytes() {
898        let v = AttributeCaster::cast_read(Value::Bytes(b"data".to_vec()), CastType::Bytes);
899        assert_eq!(v, Value::Bytes(b"data".to_vec()));
900    }
901
902    // ===== AttributeCaster - Array =====
903
904    #[test]
905    fn test_cast_to_array_from_string() {
906        let v = AttributeCaster::cast_read(Value::String("item".to_string()), CastType::Array);
907        assert!(matches!(v, Value::Array(_)));
908        if let Value::Array(arr) = v {
909            assert_eq!(arr.len(), 1);
910        }
911    }
912
913    #[test]
914    fn test_cast_to_array_from_json_string() {
915        // 合法 JSON 数组字符串应被正确解析
916        let v = AttributeCaster::cast_read(Value::String("[1, 2, 3]".to_string()), CastType::Array);
917        assert!(matches!(v, Value::Array(_)));
918        if let Value::Array(arr) = v {
919            assert_eq!(arr.len(), 3);
920            assert_eq!(arr[0], Value::I64(1));
921            assert_eq!(arr[1], Value::I64(2));
922            assert_eq!(arr[2], Value::I64(3));
923        }
924    }
925
926    #[test]
927    fn test_cast_to_array_from_json_value() {
928        // Value::Json 中的合法 JSON 数组应被正确解析
929        let v =
930            AttributeCaster::cast_read(Value::Json(r#"["a", "b"]"#.to_string()), CastType::Array);
931        assert!(matches!(v, Value::Array(_)));
932        if let Value::Array(arr) = v {
933            assert_eq!(arr.len(), 2);
934            assert_eq!(arr[0], Value::String("a".to_string()));
935            assert_eq!(arr[1], Value::String("b".to_string()));
936        }
937    }
938
939    #[test]
940    fn test_cast_to_array_preserves_array() {
941        let arr = vec![Value::I64(1), Value::I64(2)];
942        let v = AttributeCaster::cast_read(Value::Array(arr.clone()), CastType::Array);
943        assert_eq!(v, Value::Array(arr));
944    }
945
946    #[test]
947    fn test_cast_to_array_storage_serializes_to_json() {
948        let v = AttributeCaster::cast_write(
949            Value::Array(vec![Value::I64(1), Value::I64(2)]),
950            CastType::Array,
951        );
952        assert!(matches!(v, Value::Json(_)));
953        if let Value::Json(s) = v {
954            // 验证产生的 JSON 是合法的 JSON 数组
955            let parsed: serde_json::Value = serde_json::from_str(&s).unwrap();
956            assert!(parsed.is_array());
957            assert_eq!(parsed[0], serde_json::Value::Number(1.into()));
958            assert_eq!(parsed[1], serde_json::Value::Number(2.into()));
959        }
960    }
961
962    #[test]
963    fn test_cast_to_array_storage_not_debug_format() {
964        // P2-5 回归测试:确保不再使用 Debug 格式([I64(1), I64(2)])
965        let v = AttributeCaster::cast_write(
966            Value::Array(vec![Value::I64(1), Value::I64(2)]),
967            CastType::Array,
968        );
969        if let Value::Json(s) = v {
970            // Debug 格式会包含 "I64" 字样,合法 JSON 不会
971            assert!(!s.contains("I64"), "JSON 不应包含 Debug 格式 I64: {}", s);
972            // 应为合法 JSON 数组
973            let parsed: serde_json::Value = serde_json::from_str(&s).unwrap();
974            assert!(parsed.is_array());
975        }
976    }
977
978    #[test]
979    fn test_cast_to_json_storage_from_other() {
980        let v = AttributeCaster::cast_write(Value::I64(42), CastType::Json);
981        assert!(matches!(v, Value::Json(_)));
982        if let Value::Json(s) = v {
983            // 验证产生的 JSON 是合法的
984            let parsed: serde_json::Value = serde_json::from_str(&s).unwrap();
985            assert_eq!(parsed, serde_json::Value::Number(42.into()));
986        }
987    }
988
989    // ===== ClosureAccessor / ClosureMutator =====
990
991    #[test]
992    fn test_closure_accessor() {
993        let accessor = ClosureAccessor::new("name", |v| match v {
994            Value::String(s) => Value::String(s.to_uppercase()),
995            other => other,
996        });
997        let v = accessor.read(Value::String("alice".to_string()));
998        assert_eq!(v, Value::String("ALICE".to_string()));
999        assert_eq!(accessor.field(), "name");
1000    }
1001
1002    #[test]
1003    fn test_closure_mutator() {
1004        let mutator = ClosureMutator::new("email", |v| match v {
1005            Value::String(s) => Value::String(s.to_lowercase()),
1006            other => other,
1007        });
1008        let v = mutator.write(Value::String("ALICE@EXAMPLE.COM".to_string()));
1009        assert_eq!(v, Value::String("alice@example.com".to_string()));
1010        assert_eq!(mutator.field(), "email");
1011    }
1012
1013    // ===== AccessorRegistry - 基本操作 =====
1014
1015    #[test]
1016    fn test_registry_empty() {
1017        let r = AccessorRegistry::new();
1018        assert_eq!(r.accessor_count(), 0);
1019        assert_eq!(r.mutator_count(), 0);
1020        assert_eq!(r.cast_count(), 0);
1021    }
1022
1023    #[test]
1024    fn test_registry_register_cast() {
1025        let mut r = AccessorRegistry::new();
1026        r.register_cast("is_admin", CastType::Boolean);
1027        assert!(r.has_cast("is_admin"));
1028        assert_eq!(r.get_cast("is_admin"), Some(CastType::Boolean));
1029        assert_eq!(r.cast_count(), 1);
1030    }
1031
1032    #[test]
1033    fn test_registry_register_accessor() {
1034        let mut r = AccessorRegistry::new();
1035        r.register_accessor(Box::new(ClosureAccessor::new("name", |v| match v {
1036            Value::String(s) => Value::String(s.to_uppercase()),
1037            other => other,
1038        })));
1039        assert!(r.has_accessor("name"));
1040        assert_eq!(r.accessor_count(), 1);
1041    }
1042
1043    #[test]
1044    fn test_registry_register_mutator() {
1045        let mut r = AccessorRegistry::new();
1046        r.register_mutator(Box::new(ClosureMutator::new("email", |v| match v {
1047            Value::String(s) => Value::String(s.to_lowercase()),
1048            other => other,
1049        })));
1050        assert!(r.has_mutator("email"));
1051        assert_eq!(r.mutator_count(), 1);
1052    }
1053
1054    // ===== AccessorRegistry - read/write 流程 =====
1055
1056    #[test]
1057    fn test_registry_read_applies_cast_then_accessor() {
1058        let mut r = AccessorRegistry::new();
1059        r.register_cast("is_admin", CastType::Boolean);
1060        r.register_accessor(Box::new(ClosureAccessor::new("is_admin", |v| {
1061            if v == Value::Bool(true) {
1062                Value::String("管理员".to_string())
1063            } else {
1064                Value::String("普通用户".to_string())
1065            }
1066        })));
1067
1068        // 读取:I64(1) → cast(Boolean) → Bool(true) → accessor → String("管理员")
1069        let v = r.read("is_admin", Value::I64(1));
1070        assert_eq!(v, Value::String("管理员".to_string()));
1071    }
1072
1073    #[test]
1074    fn test_registry_write_applies_mutator_then_cast() {
1075        let mut r = AccessorRegistry::new();
1076        r.register_cast("is_admin", CastType::Boolean);
1077        r.register_mutator(Box::new(ClosureMutator::new("is_admin", |v| match v {
1078            Value::String(s) => {
1079                let lower = s.to_lowercase();
1080                Value::Bool(lower == "admin" || lower == "true")
1081            }
1082            other => other,
1083        })));
1084
1085        // 写入:String("admin") → mutator → Bool(true) → cast → I64(1)
1086        let v = r.write("is_admin", Value::String("admin".to_string()));
1087        assert_eq!(v, Value::I64(1));
1088    }
1089
1090    #[test]
1091    fn test_registry_read_without_cast_or_accessor() {
1092        let r = AccessorRegistry::new();
1093        let v = r.read("any_field", Value::I64(42));
1094        assert_eq!(v, Value::I64(42));
1095    }
1096
1097    #[test]
1098    fn test_registry_write_without_cast_or_mutator() {
1099        let r = AccessorRegistry::new();
1100        let v = r.write("any_field", Value::I64(42));
1101        assert_eq!(v, Value::I64(42));
1102    }
1103
1104    #[test]
1105    fn test_registry_cast_read_only() {
1106        let mut r = AccessorRegistry::new();
1107        r.register_cast("is_admin", CastType::Boolean);
1108
1109        let v = r.cast_read("is_admin", Value::I64(1));
1110        assert_eq!(v, Value::Bool(true));
1111    }
1112
1113    #[test]
1114    fn test_registry_cast_write_only() {
1115        let mut r = AccessorRegistry::new();
1116        r.register_cast("is_admin", CastType::Boolean);
1117
1118        let v = r.cast_write("is_admin", Value::Bool(true));
1119        assert_eq!(v, Value::I64(1));
1120    }
1121
1122    // ===== 综合场景测试 =====
1123
1124    #[test]
1125    fn test_complex_user_model_scenario() {
1126        let mut r = AccessorRegistry::new();
1127
1128        // 1. is_admin: i64(0/1) ↔ bool
1129        r.register_cast("is_admin", CastType::Boolean);
1130
1131        // 2. email: 自动转小写
1132        r.register_mutator(Box::new(ClosureMutator::new("email", |v| match v {
1133            Value::String(s) => Value::String(s.to_lowercase()),
1134            other => other,
1135        })));
1136
1137        // 3. full_name: 拼接 first + last(演示 accessor)
1138        r.register_accessor(Box::new(ClosureAccessor::new(
1139            "full_name",
1140            |v| v, // 简化:直接返回
1141        )));
1142
1143        // 4. settings: JSON 字段
1144        r.register_cast("settings", CastType::Json);
1145
1146        // 5. created_at: DateTime
1147        r.register_cast("created_at", CastType::DateTime);
1148
1149        // 读取 is_admin
1150        let v = r.read("is_admin", Value::I64(1));
1151        assert_eq!(v, Value::Bool(true));
1152
1153        // 写入 email
1154        let v = r.write("email", Value::String("Alice@Example.COM".to_string()));
1155        assert_eq!(v, Value::String("alice@example.com".to_string()));
1156
1157        // 读取 settings(合法 JSON 应转换为 Value::Json)
1158        let v = r.read("settings", Value::String(r#"{"theme":"dark"}"#.to_string()));
1159        assert!(matches!(v, Value::Json(_)));
1160
1161        assert_eq!(r.accessor_count(), 1);
1162        assert_eq!(r.mutator_count(), 1);
1163        assert_eq!(r.cast_count(), 3);
1164    }
1165
1166    // ===== Default 测试 =====
1167
1168    #[test]
1169    fn test_default_is_empty() {
1170        let r = AccessorRegistry::default();
1171        assert_eq!(r.accessor_count(), 0);
1172        assert_eq!(r.mutator_count(), 0);
1173        assert_eq!(r.cast_count(), 0);
1174    }
1175}