Skip to main content

wp_model_core/model/data/
record.rs

1use crate::model::format::LevelFormatAble;
2use crate::model::{DataType, FNameStr, FValueStr, Value};
3use crate::model::{FieldRef, Maker};
4use crate::traits::AsValueRef;
5use serde_derive::{Deserialize, Serialize};
6use std::fmt::{Display, Formatter};
7use std::net::{IpAddr, Ipv4Addr};
8use std::sync::Arc;
9
10use super::field::Field;
11use super::storage::FieldStorage;
12pub const WP_EVENT_ID: &str = "wp_event_id";
13/// 记录中每一项需要暴露的行为
14pub trait RecordItem {
15    fn get_name(&self) -> &str;
16    fn get_meta(&self) -> &DataType;
17    fn get_value(&self) -> &Value;
18    fn get_value_mut(&mut self) -> &mut Value;
19}
20
21/// 为 Record 生成字段所需的工厂方法
22pub trait RecordItemFactory {
23    fn from_digit<S: Into<FNameStr>>(name: S, val: i64) -> Self;
24    fn from_ip<S: Into<FNameStr>>(name: S, ip: IpAddr) -> Self;
25    fn from_chars<N: Into<FNameStr>, Val: Into<FValueStr>>(name: N, val: Val) -> Self;
26}
27
28#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
29pub struct Record<T> {
30    pub id: u64,
31    pub items: Vec<T>,
32}
33
34impl<T> Default for Record<T> {
35    fn default() -> Self {
36        Self {
37            id: 0,
38            items: Vec::with_capacity(10),
39        }
40    }
41}
42
43impl<T> From<Vec<T>> for Record<T> {
44    fn from(value: Vec<T>) -> Self {
45        Self {
46            id: 0,
47            items: value,
48        }
49    }
50}
51
52impl<T> Display for Record<T>
53where
54    T: RecordItem + LevelFormatAble,
55{
56    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
57        writeln!(f)?;
58        for (i, o) in self.items.iter().enumerate() {
59            if *o.get_meta() != DataType::Ignore {
60                write!(f, "NO:{:<5}", i + 1)?;
61                o.level_fmt(f, 1)?;
62            }
63        }
64        Ok(())
65    }
66}
67
68impl<T> Record<T>
69where
70    T: RecordItem + RecordItemFactory,
71{
72    pub fn set_id(&mut self, id: u64) {
73        // 设置 id 字段
74        self.id = id;
75
76        // 如果已存在 wp_event_id 字段,避免重复追加
77        if self.items.iter().any(|f| f.get_name() == WP_EVENT_ID) {
78            return;
79        }
80        self.items
81            .insert(0, T::from_chars(WP_EVENT_ID, id.to_string()));
82    }
83    pub fn test_value() -> Self {
84        let data = vec![
85            T::from_ip("ip", IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1))),
86            T::from_chars("chars", "test"),
87        ];
88        Self { id: 0, items: data }
89    }
90}
91
92impl<T> Record<T>
93where
94    T: RecordItem,
95{
96    pub fn get_value(&self, key: &str) -> Option<&Value> {
97        self.items
98            .iter()
99            .find(|x| x.get_name() == key)
100            .map(|x| x.get_value())
101    }
102}
103
104impl<T> Record<T> {
105    pub fn len(&self) -> usize {
106        self.items.len()
107    }
108
109    pub fn is_empty(&self) -> bool {
110        self.items.is_empty()
111    }
112
113    /// Append a field to the record.
114    ///
115    /// Accepts any type that can be converted into `T`. For `DataRecord`,
116    /// this means you can pass [`DataField`], [`FieldStorage`], or `Arc<DataField>` directly.
117    pub fn append(&mut self, data: impl Into<T>) {
118        self.items.push(data.into());
119    }
120
121    /// Alias for [`append`](Self::append) following Vec naming convention.
122    pub fn push(&mut self, data: impl Into<T>) {
123        self.items.push(data.into());
124    }
125
126    pub fn merge(&mut self, mut other: Self) {
127        self.items.append(&mut other.items);
128    }
129}
130
131impl<T> Record<T>
132where
133    T: RecordItem,
134{
135    // 存在同名字段时取第一个字段返回值
136    pub fn field(&self, key: &str) -> Option<&T> {
137        self.items.iter().find(|item| item.get_name() == key)
138    }
139
140    pub fn field_mut(&mut self, key: &str) -> Option<&mut T> {
141        self.items.iter_mut().find(|item| item.get_name() == key)
142    }
143
144    pub fn get2(&self, name: &str) -> Option<&T> {
145        self.items.iter().find(|x| x.get_name() == name)
146    }
147    pub fn get_value_mut(&mut self, name: &str) -> Option<&mut T> {
148        self.items.iter_mut().find(|x| x.get_name() == name)
149    }
150    pub fn remove_field(&mut self, name: &str) -> bool {
151        let pos = self.items.iter().position(|x| x.get_name() == name);
152        if let Some(pos) = pos {
153            self.items.remove(pos);
154            true
155        } else {
156            false
157        }
158    }
159}
160
161impl<V> RecordItem for Field<V>
162where
163    V: AsValueRef<Value>,
164{
165    fn get_name(&self) -> &str {
166        Field::get_name(self)
167    }
168
169    fn get_meta(&self) -> &DataType {
170        Field::get_meta(self)
171    }
172
173    fn get_value(&self) -> &Value {
174        Field::get_value(self)
175    }
176
177    fn get_value_mut(&mut self) -> &mut Value {
178        Field::get_value_mut(self)
179    }
180}
181
182impl<V> RecordItemFactory for Field<V>
183where
184    V: Maker<i64> + Maker<FValueStr> + Maker<IpAddr>,
185{
186    fn from_digit<S: Into<FNameStr>>(name: S, val: i64) -> Self {
187        Field::from_digit(name, val)
188    }
189
190    fn from_ip<S: Into<FNameStr>>(name: S, ip: IpAddr) -> Self {
191        Field::from_ip(name, ip)
192    }
193
194    fn from_chars<N: Into<FNameStr>, Val: Into<FValueStr>>(name: N, val: Val) -> Self {
195        Field::from_chars(name, val)
196    }
197}
198
199// Convenience construction for Record<FieldStorage> from Vec<DataField>
200impl From<Vec<Field<Value>>> for Record<FieldStorage> {
201    fn from(fields: Vec<Field<Value>>) -> Self {
202        let items: Vec<FieldStorage> = fields.into_iter().map(FieldStorage::from_owned).collect();
203        Self { id: 0, items }
204    }
205}
206
207// Convenience construction for Record<FieldStorage> from a single DataField
208impl From<Field<Value>> for Record<FieldStorage> {
209    fn from(field: Field<Value>) -> Self {
210        Self {
211            id: 0,
212            items: vec![FieldStorage::from_owned(field)],
213        }
214    }
215}
216
217// Convenience methods for Record<FieldStorage> (DataRecord with mixed storage)
218impl Record<FieldStorage> {
219    /// Push a shared field (Arc-wrapped) to the record
220    ///
221    /// # Examples
222    ///
223    /// ```
224    /// use std::sync::Arc;
225    /// use wp_model_core::model::{DataRecord, Field, Value, DataType, FieldStorage};
226    ///
227    /// let mut record = DataRecord::default();
228    /// let field = Arc::new(Field::new(DataType::Chars, "app_name", Value::from("myapp")));
229    /// record.push_shared(field);
230    /// ```
231    pub fn push_shared(&mut self, field: Arc<Field<Value>>) {
232        self.items.push(FieldStorage::from_shared(field));
233    }
234
235    /// Push an owned field to the record
236    ///
237    /// # Examples
238    ///
239    /// ```
240    /// use wp_model_core::model::{DataRecord, Field, Value, DataType};
241    ///
242    /// let mut record = DataRecord::default();
243    /// let field = Field::new(DataType::Digit, "count", Value::from(42));
244    /// record.push_owned(field);
245    /// ```
246    pub fn push_owned(&mut self, field: Field<Value>) {
247        self.items.push(FieldStorage::from_owned(field));
248    }
249
250    /// Get a reference to the underlying field by index
251    ///
252    /// # Examples
253    ///
254    /// ```
255    /// use wp_model_core::model::{DataRecord, Field, Value, DataType};
256    ///
257    /// let mut record = DataRecord::default();
258    /// let field = Field::new(DataType::Digit, "x", Value::from(10));
259    /// record.push_owned(field);
260    ///
261    /// let retrieved = record.field_at(0);
262    /// assert!(retrieved.is_some());
263    /// assert_eq!(retrieved.unwrap().get_name(), "x");
264    /// ```
265    pub fn field_at(&self, index: usize) -> Option<&Field<Value>> {
266        self.items.get(index).map(|s| s.as_field())
267    }
268
269    /// Get a [`FieldRef`] by name (zero-copy, cur_name-aware).
270    ///
271    /// Returns a [`FieldRef`] that respects the `cur_name` override.
272    /// For owned field access, use [`get_field_owned()`](Self::get_field_owned).
273    ///
274    /// # Examples
275    ///
276    /// ```ignore
277    /// use wp_model_core::model::{DataRecord, DataField};
278    ///
279    /// let record = DataRecord::from(vec![
280    ///     DataField::from_chars("name", "Alice"),
281    /// ]);
282    /// assert_eq!(record.get_field("name").map(|f| f.get_name()), Some("name"));
283    /// assert!(record.get_field("missing").is_none());
284    /// ```
285    pub fn get_field(&self, name: &str) -> Option<FieldRef<'_>> {
286        self.field(name).map(|s| s.field_ref())
287    }
288
289    /// Get owned field by name with cur_name applied.
290    ///
291    /// Use when you need to modify the field or transfer ownership.
292    pub fn get_field_owned(&self, name: &str) -> Option<Field<Value>> {
293        self.get_field(name).map(|f| f.to_owned())
294    }
295
296    /// Get a mutable reference to the underlying [`DataField`] by name.
297    ///
298    /// For `Shared` fields, this converts to `Owned` first (clone-on-write).
299    ///
300    /// # Examples
301    ///
302    /// ```ignore
303    /// use wp_model_core::model::{DataRecord, DataField};
304    ///
305    /// let mut record = DataRecord::from(vec![
306    ///     DataField::from_chars("name", "Alice"),
307    /// ]);
308    /// if let Some(field) = record.get_field_mut("name") {
309    ///     field.set_name("renamed");
310    /// }
311    /// ```
312    pub fn get_field_mut(&mut self, name: &str) -> Option<&mut Field<Value>> {
313        self.field_mut(name).map(|s| s.as_field_mut())
314    }
315
316    /// Iterate over all fields as [`DataField`] references.
317    ///
318    /// Note: Returns underlying field references. Field names may not reflect
319    /// `cur_name` overrides. Use [`field_refs()`](Self::field_refs) for cur_name-aware iteration.
320    pub fn fields(&self) -> impl Iterator<Item = &Field<Value>> + '_ {
321        self.items.iter().map(|s| s.as_field())
322    }
323
324    /// Iterate over all fields as [`FieldRef`] (zero-copy, cur_name-aware).
325    pub fn field_refs(&self) -> impl Iterator<Item = FieldRef<'_>> + '_ {
326        self.items.iter().map(|s| s.field_ref())
327    }
328
329    /// Iterate over all fields as mutable [`DataField`] references.
330    ///
331    /// For `Shared` fields, this converts them to `Owned` (clone-on-write).
332    pub fn fields_mut(&mut self) -> impl Iterator<Item = &mut Field<Value>> + '_ {
333        self.items.iter_mut().map(|s| s.as_field_mut())
334    }
335
336    /// Get statistics about storage types (shared vs owned)
337    ///
338    /// Returns (shared_count, owned_count)
339    ///
340    /// # Examples
341    ///
342    /// ```
343    /// use std::sync::Arc;
344    /// use wp_model_core::model::{DataRecord, Field, Value, DataType};
345    ///
346    /// let mut record = DataRecord::default();
347    /// let static_field = Arc::new(Field::new(DataType::Chars, "static", Value::from("val")));
348    /// record.push_shared(static_field);
349    ///
350    /// let dynamic_field = Field::new(DataType::Digit, "dynamic", Value::from(10));
351    /// record.push_owned(dynamic_field);
352    ///
353    /// let (shared, owned) = record.storage_stats();
354    /// assert_eq!(shared, 1);
355    /// assert_eq!(owned, 1);
356    /// ```
357    pub fn storage_stats(&self) -> (usize, usize) {
358        let mut shared_count = 0;
359        let mut owned_count = 0;
360        for item in &self.items {
361            if item.is_shared() {
362                shared_count += 1;
363            } else {
364                owned_count += 1;
365            }
366        }
367        (shared_count, owned_count)
368    }
369
370    /// Convert to a fully owned record (Record<Field<Value>>)
371    ///
372    /// This is useful when you need to pass the record to code that expects
373    /// the old Record<Field<Value>> type.
374    ///
375    /// # Examples
376    ///
377    /// ```
378    /// use wp_model_core::model::{DataRecord, Field, Value, DataType};
379    ///
380    /// let mut record = DataRecord::default();
381    /// let field = Field::new(DataType::Digit, "x", Value::from(10));
382    /// record.push_owned(field);
383    ///
384    /// let owned_record = record.into_owned_record();
385    /// assert_eq!(owned_record.items.len(), 1);
386    /// ```
387    pub fn into_owned_record(self) -> Record<Field<Value>> {
388        Record {
389            id: self.id,
390            items: self
391                .items
392                .into_iter()
393                .map(|storage| storage.into_owned())
394                .collect(),
395        }
396    }
397}
398
399// ValueGetter impl removed from core; use function-style adapters in extension crates.
400
401#[cfg(test)]
402mod tests {
403    use super::*;
404    use crate::model::{DataField, DataRecord, FieldStorage};
405    use std::net::Ipv4Addr;
406
407    fn make_test_record() -> DataRecord {
408        let fields = vec![
409            FieldStorage::from_chars("name", "Alice"),
410            FieldStorage::from_digit("age", 30),
411            FieldStorage::from_ip("ip", IpAddr::V4(Ipv4Addr::new(192, 168, 1, 1))),
412        ];
413        Record::from(fields)
414    }
415
416    // ========== Record creation tests ==========
417
418    #[test]
419    fn test_record_default() {
420        let record: DataRecord = Record::default();
421        assert!(record.items.is_empty());
422    }
423
424    #[test]
425    fn test_record_from_vec() {
426        let fields: Vec<FieldStorage> = vec![
427            FieldStorage::from_digit("x", 1),
428            FieldStorage::from_digit("y", 2),
429        ];
430        let record: DataRecord = Record::from(fields);
431        assert_eq!(record.items.len(), 2);
432    }
433
434    #[test]
435    fn test_record_test_value() {
436        let record: DataRecord = Record::test_value();
437        assert_eq!(record.items.len(), 2);
438        assert!(record.field("ip").is_some());
439        assert!(record.field("chars").is_some());
440    }
441
442    // ========== Record field access tests ==========
443
444    #[test]
445    fn test_record_field() {
446        let record = make_test_record();
447
448        let name_field = record.field("name");
449        assert!(name_field.is_some());
450        assert_eq!(name_field.unwrap().get_name(), "name");
451
452        let missing = record.field("missing");
453        assert!(missing.is_none());
454    }
455
456    #[test]
457    fn test_record_get2() {
458        let record = make_test_record();
459
460        let age_field = record.get2("age");
461        assert!(age_field.is_some());
462        assert_eq!(age_field.unwrap().get_meta(), &DataType::Digit);
463    }
464
465    #[test]
466    fn test_record_get_value() {
467        let record = make_test_record();
468
469        let age_value = record.get_value("age");
470        assert!(age_value.is_some());
471        assert_eq!(age_value.unwrap(), &Value::Digit(30));
472
473        let missing = record.get_value("missing");
474        assert!(missing.is_none());
475    }
476
477    #[test]
478    fn test_record_get_value_mut() {
479        let mut record = make_test_record();
480
481        let field = record.get_value_mut("age");
482        assert!(field.is_some());
483
484        // Modify the value through mutable reference
485        if let Some(f) = field {
486            *f.get_value_mut() = Value::Digit(31);
487        }
488
489        assert_eq!(record.get_value("age"), Some(&Value::Digit(31)));
490    }
491
492    // ========== Record mutation tests ==========
493
494    #[test]
495    fn test_record_append() {
496        let mut record: DataRecord = Record::default();
497        assert_eq!(record.items.len(), 0);
498
499        record.append(FieldStorage::from_digit("count", 100));
500        assert_eq!(record.items.len(), 1);
501
502        record.append(FieldStorage::from_chars("msg", "hello"));
503        assert_eq!(record.items.len(), 2);
504    }
505
506    #[test]
507    fn test_record_merge() {
508        let mut record1: DataRecord = Record::from(vec![FieldStorage::from_digit("a", 1)]);
509        let record2: DataRecord = Record::from(vec![
510            FieldStorage::from_digit("b", 2),
511            FieldStorage::from_digit("c", 3),
512        ]);
513
514        record1.merge(record2);
515        assert_eq!(record1.items.len(), 3);
516        assert!(record1.field("a").is_some());
517        assert!(record1.field("b").is_some());
518        assert!(record1.field("c").is_some());
519    }
520
521    #[test]
522    fn test_record_remove_field() {
523        let mut record = make_test_record();
524        assert_eq!(record.items.len(), 3);
525
526        let removed = record.remove_field("age");
527        assert!(removed);
528        assert_eq!(record.items.len(), 2);
529        assert!(record.field("age").is_none());
530
531        let not_found = record.remove_field("nonexistent");
532        assert!(!not_found);
533        assert_eq!(record.items.len(), 2);
534    }
535
536    // ========== set_id tests ==========
537
538    #[test]
539    fn test_record_set_id() {
540        let mut record = make_test_record();
541        let original_len = record.items.len();
542
543        record.set_id(12345);
544
545        // ID should be set in both the id field and added to items
546        assert_eq!(record.id, 12345);
547        assert_eq!(record.items.len(), original_len + 1);
548        // ID should be inserted at position 0
549        assert_eq!(record.items[0].get_name(), WP_EVENT_ID);
550        assert_eq!(record.items[0].get_value(), &Value::Chars("12345".into()));
551    }
552
553    #[test]
554    fn test_record_set_id_no_duplicate() {
555        let mut record = make_test_record();
556
557        record.set_id(100);
558        assert_eq!(record.id, 100);
559        let len_after_first = record.items.len();
560
561        // Try to set ID again - should update id field but not add duplicate to items
562        record.set_id(200);
563        assert_eq!(record.id, 200);
564        assert_eq!(record.items.len(), len_after_first);
565        // Original ID in items should remain
566        assert_eq!(
567            record.get_value(WP_EVENT_ID),
568            Some(&Value::Chars("100".into()))
569        );
570    }
571
572    // ========== RecordItem trait tests ==========
573
574    #[test]
575    fn test_field_as_record_item() {
576        let field: DataField = Field::from_chars("key", "value");
577
578        // Test RecordItem trait methods
579        assert_eq!(field.get_name(), "key");
580        assert_eq!(field.get_meta(), &DataType::Chars);
581        assert_eq!(field.get_value(), &Value::Chars("value".into()));
582    }
583
584    #[test]
585    fn test_field_record_item_get_value_mut() {
586        let mut field: DataField = Field::from_digit("num", 10);
587
588        *field.get_value_mut() = Value::Digit(20);
589        assert_eq!(field.get_value(), &Value::Digit(20));
590    }
591
592    // ========== FieldStorage RecordItem tests ==========
593
594    #[test]
595    fn test_field_storage_as_record_item() {
596        let storage: FieldStorage = FieldStorage::from_chars("key", "value");
597
598        // Test RecordItem trait methods
599        assert_eq!(storage.get_name(), "key");
600        assert_eq!(storage.get_meta(), &DataType::Chars);
601        assert_eq!(storage.get_value(), &Value::Chars("value".into()));
602    }
603
604    #[test]
605    fn test_field_storage_record_item_get_value_mut() {
606        let mut storage: FieldStorage = FieldStorage::from_digit("num", 10);
607
608        *storage.get_value_mut() = Value::Digit(20);
609        assert_eq!(storage.get_value(), &Value::Digit(20));
610    }
611
612    // ========== RecordItemFactory trait tests ==========
613
614    #[test]
615    fn test_record_item_factory() {
616        let digit: FieldStorage = <FieldStorage as RecordItemFactory>::from_digit("n", 42);
617        assert_eq!(digit.get_meta(), &DataType::Digit);
618
619        let ip: FieldStorage = <FieldStorage as RecordItemFactory>::from_ip(
620            "addr",
621            IpAddr::V4(Ipv4Addr::new(10, 0, 0, 1)),
622        );
623        assert_eq!(ip.get_meta(), &DataType::IP);
624
625        let chars: FieldStorage = <FieldStorage as RecordItemFactory>::from_chars("s", "hello");
626        assert_eq!(chars.get_meta(), &DataType::Chars);
627    }
628
629    // ========== Display test ==========
630
631    #[test]
632    fn test_record_display() {
633        let record = make_test_record();
634        let display = format!("{}", record);
635
636        assert!(display.contains("name"));
637        assert!(display.contains("age"));
638        assert!(display.contains("ip"));
639    }
640
641    // ========== Record<FieldStorage> convenience methods tests ==========
642
643    #[test]
644    fn test_push_shared() {
645        let mut record = DataRecord::default();
646        let field = Arc::new(Field::new(DataType::Chars, "static", Value::from("value")));
647
648        record.push_shared(field.clone());
649        assert_eq!(record.items.len(), 1);
650        assert!(record.items[0].is_shared());
651        assert_eq!(record.items[0].as_field().get_name(), "static");
652    }
653
654    #[test]
655    fn test_push_owned() {
656        let mut record = DataRecord::default();
657        let field = Field::new(DataType::Digit, "dynamic", Value::from(42));
658
659        record.push_owned(field);
660        assert_eq!(record.items.len(), 1);
661        assert!(!record.items[0].is_shared());
662        assert_eq!(record.items[0].as_field().get_name(), "dynamic");
663    }
664
665    #[test]
666    fn test_get_field() {
667        let mut record = DataRecord::default();
668        record.push_owned(Field::new(DataType::Chars, "test", Value::from("value")));
669
670        let field = record.field_at(0);
671        assert!(field.is_some());
672        assert_eq!(field.unwrap().get_name(), "test");
673
674        let missing = record.field_at(10);
675        assert!(missing.is_none());
676    }
677
678    #[test]
679    fn test_storage_stats() {
680        let mut record = DataRecord::default();
681
682        // Add shared fields
683        record.push_shared(Arc::new(Field::new(
684            DataType::Chars,
685            "s1",
686            Value::from("a"),
687        )));
688        record.push_shared(Arc::new(Field::new(
689            DataType::Chars,
690            "s2",
691            Value::from("b"),
692        )));
693
694        // Add owned fields
695        record.push_owned(Field::new(DataType::Digit, "o1", Value::from(1)));
696        record.push_owned(Field::new(DataType::Digit, "o2", Value::from(2)));
697        record.push_owned(Field::new(DataType::Digit, "o3", Value::from(3)));
698
699        let (shared, owned) = record.storage_stats();
700        assert_eq!(shared, 2);
701        assert_eq!(owned, 3);
702    }
703
704    #[test]
705    fn test_into_owned_record() {
706        let mut record = DataRecord::default();
707        record.push_shared(Arc::new(Field::new(
708            DataType::Chars,
709            "s",
710            Value::from("shared"),
711        )));
712        record.push_owned(Field::new(DataType::Digit, "o", Value::from(10)));
713
714        let owned_record = record.into_owned_record();
715        assert_eq!(owned_record.items.len(), 2);
716        assert_eq!(owned_record.items[0].get_name(), "s");
717        assert_eq!(owned_record.items[1].get_name(), "o");
718    }
719
720    // ========== New convenience API tests ==========
721
722    #[test]
723    fn test_record_len_and_is_empty() {
724        let mut record = DataRecord::default();
725        assert!(record.is_empty());
726        assert_eq!(record.len(), 0);
727
728        record.append(FieldStorage::from_chars("a", "1"));
729        assert!(!record.is_empty());
730        assert_eq!(record.len(), 1);
731    }
732
733    #[test]
734    fn test_from_vec_datafield() {
735        let fields: Vec<DataField> = vec![
736            DataField::from_chars("a", "1"),
737            DataField::from_chars("b", "2"),
738        ];
739        let record = DataRecord::from(fields);
740        assert_eq!(record.len(), 2);
741        assert!(record.field("a").is_some());
742        assert!(record.field("b").is_some());
743    }
744
745    #[test]
746    fn test_from_single_datafield() {
747        let field = DataField::from_chars("name", "Alice");
748        let record = DataRecord::from(field);
749        assert_eq!(record.len(), 1);
750        assert!(record.field("name").is_some());
751    }
752
753    #[test]
754    fn test_append_generic() {
755        let mut record = DataRecord::default();
756
757        // Append a DataField directly (auto-converts via Into<FieldStorage>)
758        record.append(DataField::from_chars("a", "1"));
759
760        // Append a FieldStorage directly (still works)
761        record.append(FieldStorage::from_chars("b", "2"));
762
763        // Append via Arc (auto-converts to Shared)
764        let arc_field = Arc::new(DataField::from_chars("c", "3"));
765        record.append(arc_field);
766
767        assert_eq!(record.len(), 3);
768        assert!(record.items[0].is_owned());
769        assert!(record.items[1].is_owned());
770        assert!(record.items[2].is_shared());
771    }
772
773    #[test]
774    fn test_push_alias() {
775        let mut record = DataRecord::default();
776        record.push(DataField::from_chars("a", "1"));
777        record.push(FieldStorage::from_chars("b", "2"));
778        assert_eq!(record.len(), 2);
779    }
780
781    #[test]
782    fn test_get_field_by_name() {
783        let record = DataRecord::from(vec![
784            DataField::from_chars("name", "Alice"),
785            DataField::from_digit("age", 30),
786        ]);
787
788        let field = record.get_field("name");
789        assert!(field.is_some());
790        assert_eq!(field.unwrap().get_name(), "name");
791
792        assert!(record.get_field("missing").is_none());
793    }
794
795    #[test]
796    fn test_get_field_mut_by_name() {
797        let mut record = DataRecord::from(vec![DataField::from_chars("name", "Alice")]);
798
799        if let Some(field) = record.get_field_mut("name") {
800            field.set_name("renamed");
801        }
802        assert_eq!(
803            record.get_field("renamed").map(|f| f.get_name()),
804            Some("renamed")
805        );
806    }
807
808    #[test]
809    fn test_field_mut() {
810        let mut record = DataRecord::from(vec![DataField::from_chars("name", "Alice")]);
811
812        let storage = record.field_mut("name");
813        assert!(storage.is_some());
814    }
815
816    #[test]
817    fn test_fields_iterator() {
818        let record = DataRecord::from(vec![
819            DataField::from_chars("a", "1"),
820            DataField::from_chars("b", "2"),
821            DataField::from_chars("c", "3"),
822        ]);
823
824        let names: Vec<&str> = record.fields().map(|f| f.get_name()).collect();
825        assert_eq!(names, vec!["a", "b", "c"]);
826    }
827
828    #[test]
829    fn test_fields_mut_iterator() {
830        let mut record = DataRecord::from(vec![DataField::from_chars("a", "1")]);
831
832        for field in record.fields_mut() {
833            field.set_name("renamed");
834        }
835        assert_eq!(
836            record.get_field("renamed").map(|f| f.get_name()),
837            Some("renamed")
838        );
839    }
840}