Skip to main content

wp_model_core/model/data/
storage.rs

1use crate::model::DataType;
2use crate::model::Value;
3use crate::model::format::LevelFormatAble;
4use crate::model::{FNameStr, FValueStr};
5use serde::{Deserialize, Deserializer, Serialize, Serializer};
6use std::fmt::{Display, Formatter};
7use std::net::IpAddr;
8use std::sync::Arc;
9
10use super::field::Field;
11use super::record::{RecordItem, RecordItemFactory};
12
13/// Storage mode for the underlying field value.
14#[derive(Clone, Debug)]
15pub enum ValueStorage {
16    /// Arc shared (zero-copy passing)
17    Shared(Arc<Field<Value>>),
18
19    /// Exclusive ownership
20    Owned(Field<Value>),
21}
22
23/// Field storage with zero-copy name override support.
24///
25/// Design principles:
26/// - `cur_name` acts as an overlay, never modifying the underlying DataField
27/// - Name lookup priority: cur_name > field.name
28/// - `set_name()` only modifies cur_name, achieving zero-copy
29///
30/// # Performance
31/// - Cloning `Shared` variant: ~5ns (Arc reference count increment)
32/// - Cloning `Owned` variant: 50-500ns (deep copy of Field<Value>)
33/// - Accessing field via `as_field()`: ~0-1ns
34/// - `set_name()`: ~0ns (only sets cur_name, no field clone)
35///
36/// # Examples
37///
38/// ```ignore
39/// use std::sync::Arc;
40/// use wp_model_core::model::{FieldStorage, Field, Value, DataType};
41///
42/// // Create a shared field (for static/constant values)
43/// let static_field = Arc::new(Field::new(DataType::Chars, "app_name", Value::from("myapp")));
44/// let shared = FieldStorage::from_shared(static_field);
45///
46/// // Zero-copy rename
47/// let mut renamed = shared.clone();
48/// renamed.set_name("application_name");  // Only sets cur_name, no clone!
49///
50/// // Create an owned field (for dynamic values)
51/// let dynamic_field = Field::new(DataType::Digit, "counter", Value::from(42));
52/// let owned = FieldStorage::from_owned(dynamic_field);
53/// ```
54#[derive(Clone, Debug)]
55pub struct FieldStorage {
56    /// Current field name (overrides field.name).
57    /// None means use the underlying field's original name.
58    cur_name: Option<FNameStr>,
59
60    /// Field value storage
61    value: ValueStorage,
62}
63
64impl FieldStorage {
65    /// Create from Arc<DataField> as Shared variant (zero-copy).
66    ///
67    /// # Examples
68    ///
69    /// ```ignore
70    /// use std::sync::Arc;
71    /// use wp_model_core::model::{FieldStorage, Field, Value, DataType};
72    ///
73    /// let field = Arc::new(Field::new(DataType::Chars, "name", Value::from("Alice")));
74    /// let storage = FieldStorage::from_shared(field);
75    ///
76    /// assert!(storage.is_shared());
77    /// ```
78    #[inline]
79    pub fn from_shared(field: Arc<Field<Value>>) -> Self {
80        Self {
81            cur_name: None,
82            value: ValueStorage::Shared(field),
83        }
84    }
85
86    /// Create Owned variant from owned field.
87    ///
88    /// # Examples
89    ///
90    /// ```ignore
91    /// use wp_model_core::model::{FieldStorage, Field, Value, DataType};
92    ///
93    /// let field = Field::new(DataType::Digit, "count", Value::from(10));
94    /// let storage = FieldStorage::from_owned(field);
95    ///
96    /// assert!(storage.is_owned());
97    /// ```
98    #[inline]
99    pub fn from_owned(field: Field<Value>) -> Self {
100        Self {
101            cur_name: None,
102            value: ValueStorage::Owned(field),
103        }
104    }
105
106    /// Zero-copy set field name.
107    ///
108    /// Only modifies `cur_name`, does not affect the underlying Arc<DataField>.
109    /// This is the core method of the zero-copy optimization!
110    ///
111    /// # Examples
112    ///
113    /// ```ignore
114    /// use std::sync::Arc;
115    /// use wp_model_core::model::{FieldStorage, Field, Value, DataType};
116    ///
117    /// let field = Arc::new(Field::new(DataType::Chars, "HOST", Value::from("192.168.1.1")));
118    /// let mut storage = FieldStorage::from_shared(Arc::clone(&field));
119    /// storage.set_name("server_ip");  // Zero-copy!
120    ///
121    /// assert_eq!(storage.get_name(), "server_ip");
122    /// assert_eq!(field.get_name(), "HOST");  // Original unchanged
123    /// ```
124    #[inline]
125    pub fn set_name(&mut self, name: impl Into<FNameStr>) {
126        self.cur_name = Some(name.into());
127    }
128
129    /// Get the current effective field name.
130    ///
131    /// Priority: cur_name > field.name
132    #[inline]
133    pub fn get_name(&self) -> &str {
134        if let Some(ref name) = self.cur_name {
135            name.as_str()
136        } else {
137            self.as_field().get_name()
138        }
139    }
140
141    /// Get a reference to the underlying field (unified interface).
142    ///
143    /// Note: This returns the underlying field, whose name may differ from
144    /// `get_name()` if `set_name()` was called.
145    ///
146    /// # Performance
147    /// - Shared variant: ~1ns (dereference)
148    /// - Owned variant: 0ns (direct reference)
149    #[inline]
150    pub fn as_field(&self) -> &Field<Value> {
151        match &self.value {
152            ValueStorage::Shared(arc) => arc.as_ref(),
153            ValueStorage::Owned(field) => field,
154        }
155    }
156
157    /// Convert to owned Field<Value>.
158    ///
159    /// If `cur_name` is set, it will be applied to the returned field.
160    /// If `cur_name` is None and this is an Owned variant, returns without cloning.
161    ///
162    /// # Performance
163    /// - Shared variant: ~50-500ns (clone the inner field if multiple references exist)
164    /// - Owned variant: 0ns (move)
165    pub fn into_owned(self) -> Field<Value> {
166        let mut field = match self.value {
167            ValueStorage::Shared(arc) => {
168                // Try to unwrap if this is the only reference, otherwise clone
169                Arc::try_unwrap(arc).unwrap_or_else(|arc| (*arc).clone())
170            }
171            ValueStorage::Owned(field) => field,
172        };
173
174        // Apply cur_name override
175        if let Some(name) = self.cur_name {
176            field.set_name(name);
177        }
178
179        field
180    }
181
182    /// Check if this is a Shared variant.
183    #[inline]
184    pub fn is_shared(&self) -> bool {
185        matches!(self.value, ValueStorage::Shared(_))
186    }
187
188    /// Check if this is an Owned variant.
189    #[inline]
190    pub fn is_owned(&self) -> bool {
191        matches!(self.value, ValueStorage::Owned(_))
192    }
193
194    /// Get Arc reference count (for debugging/diagnostics).
195    ///
196    /// Returns `Some(count)` for Shared variant, `None` for Owned variant.
197    pub fn shared_count(&self) -> Option<usize> {
198        match &self.value {
199            ValueStorage::Shared(arc) => Some(Arc::strong_count(arc)),
200            ValueStorage::Owned(_) => None,
201        }
202    }
203
204    /// Get a mutable reference to the underlying field.
205    ///
206    /// For the `Shared` variant, this converts to `Owned` first (clone-on-write).
207    /// If `cur_name` is set, it will be applied to the field before returning.
208    ///
209    /// # Examples
210    ///
211    /// ```ignore
212    /// use wp_model_core::model::{FieldStorage, Field, Value, DataType};
213    ///
214    /// let mut storage = FieldStorage::from_owned(Field::from_chars("name", "Alice"));
215    /// storage.as_field_mut().set_name("renamed");
216    /// assert_eq!(storage.as_field().get_name(), "renamed");
217    /// ```
218    pub fn as_field_mut(&mut self) -> &mut Field<Value> {
219        // Convert Shared to Owned if needed
220        if let ValueStorage::Shared(_) = self.value {
221            let old_value = std::mem::replace(
222                &mut self.value,
223                ValueStorage::Owned(Field::new(DataType::Ignore, "", Value::from(false))),
224            );
225            let field = match old_value {
226                ValueStorage::Shared(arc) => {
227                    Arc::try_unwrap(arc).unwrap_or_else(|arc| (*arc).clone())
228                }
229                ValueStorage::Owned(field) => field,
230            };
231            self.value = ValueStorage::Owned(field);
232        }
233
234        // Apply cur_name if set
235        if let Some(name) = self.cur_name.take()
236            && let ValueStorage::Owned(ref mut field) = self.value
237        {
238            field.set_name(name);
239        }
240
241        match &mut self.value {
242            ValueStorage::Owned(field) => field,
243            ValueStorage::Shared(_) => unreachable!(),
244        }
245    }
246
247    /// Get field value reference.
248    #[inline]
249    pub fn get_value(&self) -> &Value {
250        self.as_field().get_value()
251    }
252
253    /// Get type metadata.
254    #[inline]
255    pub fn get_meta(&self) -> &DataType {
256        self.as_field().get_meta()
257    }
258}
259
260// Implement Display by delegating to inner field
261impl Display for FieldStorage {
262    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
263        self.as_field().fmt(f)
264    }
265}
266
267// Implement PartialEq by comparing effective names and field contents
268impl PartialEq for FieldStorage {
269    fn eq(&self, other: &Self) -> bool {
270        self.get_name() == other.get_name()
271            && self.as_field().get_meta() == other.as_field().get_meta()
272            && self.as_field().get_value() == other.as_field().get_value()
273    }
274}
275
276impl Eq for FieldStorage {}
277
278// Serialize: Transparently serialize as Field<Value> with effective name
279impl Serialize for FieldStorage {
280    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
281    where
282        S: Serializer,
283    {
284        if let Some(ref name) = self.cur_name {
285            // Serialize with the effective name
286            let mut field = self.as_field().clone();
287            field.set_name(name.as_str());
288            field.serialize(serializer)
289        } else {
290            self.as_field().serialize(serializer)
291        }
292    }
293}
294
295// Deserialize: Always deserialize to Owned variant
296impl<'de> Deserialize<'de> for FieldStorage {
297    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
298    where
299        D: Deserializer<'de>,
300    {
301        Field::<Value>::deserialize(deserializer).map(FieldStorage::from_owned)
302    }
303}
304
305// Implement RecordItem trait by delegating to the inner field
306impl RecordItem for FieldStorage {
307    fn get_name(&self) -> &str {
308        if let Some(ref name) = self.cur_name {
309            name.as_str()
310        } else {
311            self.as_field().get_name()
312        }
313    }
314
315    fn get_meta(&self) -> &DataType {
316        self.as_field().get_meta()
317    }
318
319    fn get_value(&self) -> &Value {
320        self.as_field().get_value()
321    }
322
323    fn get_value_mut(&mut self) -> &mut Value {
324        self.as_field_mut().get_value_mut()
325    }
326}
327
328// Implement RecordItemFactory trait
329impl RecordItemFactory for FieldStorage {
330    fn from_digit<S: Into<FNameStr>>(name: S, val: i64) -> Self {
331        FieldStorage::from_owned(Field::from_digit(name, val))
332    }
333
334    fn from_ip<S: Into<FNameStr>>(name: S, ip: IpAddr) -> Self {
335        FieldStorage::from_owned(Field::from_ip(name, ip))
336    }
337
338    fn from_chars<N: Into<FNameStr>, Val: Into<FValueStr>>(name: N, val: Val) -> Self {
339        FieldStorage::from_owned(Field::from_chars(name, val))
340    }
341}
342
343// Implement LevelFormatAble
344impl LevelFormatAble for FieldStorage {
345    fn level_fmt(&self, f: &mut Formatter<'_>, level: usize) -> std::fmt::Result {
346        if let Some(ref name) = self.cur_name {
347            let meta: String = From::from(self.as_field().get_meta());
348            writeln!(
349                f,
350                "{:width$}[{:<16}] {:<20} : {}",
351                "",
352                meta,
353                name,
354                self.as_field().value,
355                width = level * 6
356            )
357        } else {
358            self.as_field().level_fmt(f, level)
359        }
360    }
361}
362
363// Auto conversion (reduce migration cost)
364impl From<Field<Value>> for FieldStorage {
365    fn from(field: Field<Value>) -> Self {
366        FieldStorage::from_owned(field)
367    }
368}
369
370impl From<Arc<Field<Value>>> for FieldStorage {
371    fn from(arc: Arc<Field<Value>>) -> Self {
372        FieldStorage::from_shared(arc)
373    }
374}
375
376#[cfg(test)]
377mod tests {
378    use super::*;
379    use crate::model::DataType;
380
381    #[test]
382    fn test_field_storage_shared_variant() {
383        let field = Field::new(DataType::Chars, "test", Value::from("hello"));
384        let storage = FieldStorage::from_shared(Arc::new(field.clone()));
385
386        // as_field returns correct reference
387        assert_eq!(storage.as_field().get_name(), "test");
388        assert!(storage.is_shared());
389        assert_eq!(storage.shared_count(), Some(1));
390
391        // Clone Shared variant only increments reference count
392        let storage2 = storage.clone();
393        assert_eq!(storage.shared_count(), Some(2));
394        assert_eq!(storage2.shared_count(), Some(2));
395    }
396
397    #[test]
398    fn test_field_storage_owned_variant() {
399        let field = Field::new(DataType::Digit, "test", Value::from(42));
400        let storage = FieldStorage::from_owned(field);
401
402        assert_eq!(storage.as_field().get_name(), "test");
403        assert!(!storage.is_shared());
404        assert_eq!(storage.shared_count(), None);
405    }
406
407    #[test]
408    fn test_into_owned() {
409        // Shared variant
410        let field1 = Field::new(DataType::Chars, "shared_field", Value::from("value"));
411        let storage1 = FieldStorage::from_shared(Arc::new(field1));
412        let owned1 = storage1.into_owned();
413        assert_eq!(owned1.get_name(), "shared_field");
414
415        // Owned variant
416        let field2 = Field::new(DataType::Digit, "owned_field", Value::from(123));
417        let storage2 = FieldStorage::from_owned(field2);
418        let owned2 = storage2.into_owned();
419        assert_eq!(owned2.get_name(), "owned_field");
420    }
421
422    #[test]
423    fn test_from_shared() {
424        let field = Field::new(DataType::Chars, "name", Value::from("Alice"));
425        let storage = FieldStorage::from_shared(Arc::new(field));
426
427        assert!(storage.is_shared());
428        assert_eq!(storage.as_field().get_name(), "name");
429    }
430
431    #[test]
432    fn test_from_owned() {
433        let field = Field::new(DataType::Digit, "count", Value::from(10));
434        let storage = FieldStorage::from_owned(field);
435
436        assert!(!storage.is_shared());
437        assert_eq!(storage.as_field().get_name(), "count");
438    }
439
440    #[test]
441    fn test_display() {
442        let field = Field::new(DataType::Digit, "num", Value::from(42));
443        let storage = FieldStorage::from_owned(field);
444
445        let display = format!("{}", storage);
446        assert!(display.contains("42"));
447    }
448
449    #[test]
450    fn test_equality() {
451        let field1 = Field::new(DataType::Chars, "test", Value::from("value"));
452        let field2 = Field::new(DataType::Chars, "test", Value::from("value"));
453        let field3 = Field::new(DataType::Chars, "test", Value::from("different"));
454
455        let shared1 = FieldStorage::from_shared(Arc::new(field1.clone()));
456        let owned1 = FieldStorage::from_owned(field1);
457        let shared2 = FieldStorage::from_shared(Arc::new(field2));
458        let owned3 = FieldStorage::from_owned(field3);
459
460        // Same content should be equal regardless of storage type
461        assert_eq!(shared1, owned1);
462        assert_eq!(shared1, shared2);
463
464        // Different content should not be equal
465        assert_ne!(shared1, owned3);
466    }
467
468    #[test]
469    fn test_equality_with_cur_name() {
470        let field = Field::new(DataType::Chars, "test", Value::from("value"));
471
472        let mut storage1 = FieldStorage::from_owned(field.clone());
473        storage1.set_name("renamed");
474
475        let storage2 = FieldStorage::from_owned(field);
476
477        // Different effective names should not be equal
478        assert_ne!(storage1, storage2);
479    }
480
481    #[test]
482    fn test_serde_serialization() {
483        let field1 = Field::new(DataType::Chars, "f1", Value::from("shared"));
484        let field2 = Field::new(DataType::Digit, "f2", Value::from(99));
485
486        let shared = FieldStorage::from_shared(Arc::new(field1));
487        let owned = FieldStorage::from_owned(field2);
488
489        // Serialize
490        let json_shared = serde_json::to_string(&shared).unwrap();
491        let json_owned = serde_json::to_string(&owned).unwrap();
492
493        // Deserialize (should always get Owned variant)
494        let deserialized_shared: FieldStorage = serde_json::from_str(&json_shared).unwrap();
495        let deserialized_owned: FieldStorage = serde_json::from_str(&json_owned).unwrap();
496
497        // Verify values are correct
498        assert_eq!(deserialized_shared.as_field().get_name(), "f1");
499        assert_eq!(deserialized_owned.as_field().get_name(), "f2");
500
501        // Verify both are Owned variant after deserialization
502        assert!(!deserialized_shared.is_shared());
503        assert!(!deserialized_owned.is_shared());
504    }
505
506    #[test]
507    fn test_serde_with_cur_name() {
508        let field = Field::new(DataType::Chars, "original", Value::from("value"));
509        let mut storage = FieldStorage::from_owned(field);
510        storage.set_name("renamed");
511
512        // Serialize should use the effective name
513        let json = serde_json::to_string(&storage).unwrap();
514        let deserialized: FieldStorage = serde_json::from_str(&json).unwrap();
515
516        assert_eq!(deserialized.get_name(), "renamed");
517    }
518
519    #[test]
520    fn test_clone_performance_difference() {
521        // This is more of a documentation test showing the usage pattern
522        use crate::model::FValueStr;
523        let large_str = FValueStr::from("x".repeat(1000));
524        let field = Field::new(DataType::Chars, "large", Value::from(large_str));
525
526        // Shared: cheap clone
527        let shared = FieldStorage::from_shared(Arc::new(field.clone()));
528        let _shared2 = shared.clone();
529        assert_eq!(shared.shared_count(), Some(2));
530
531        // Owned: deep clone
532        let owned = FieldStorage::from_owned(field);
533        let _owned2 = owned.clone();
534        assert!(owned.shared_count().is_none());
535    }
536
537    #[test]
538    fn test_from_arc_to_fieldstorage() {
539        let field = Field::new(DataType::Chars, "name", Value::from("Alice"));
540        let arc = Arc::new(field);
541        let storage: FieldStorage = arc.into();
542
543        assert!(storage.is_shared());
544        assert_eq!(storage.as_field().get_name(), "name");
545    }
546
547    #[test]
548    fn test_is_owned() {
549        let field = Field::new(DataType::Digit, "x", Value::from(1));
550        let owned = FieldStorage::from_owned(field.clone());
551        let shared = FieldStorage::from_shared(Arc::new(field));
552
553        assert!(owned.is_owned());
554        assert!(!shared.is_owned());
555    }
556
557    #[test]
558    fn test_as_field_mut_owned() {
559        let mut storage = FieldStorage::from_owned(Field::from_chars("name", "Alice"));
560        storage.as_field_mut().set_name("renamed");
561        assert_eq!(storage.as_field().get_name(), "renamed");
562        assert!(storage.is_owned());
563    }
564
565    #[test]
566    fn test_as_field_mut_shared() {
567        let field = Field::from_chars("name", "Alice");
568        let mut storage = FieldStorage::from_shared(Arc::new(field));
569        assert!(storage.is_shared());
570
571        // Mutating converts Shared to Owned
572        storage.as_field_mut().set_name("renamed");
573        assert!(storage.is_owned());
574        assert_eq!(storage.as_field().get_name(), "renamed");
575    }
576
577    #[test]
578    fn test_as_field_mut_applies_cur_name() {
579        let field = Field::from_chars("original", "value");
580        let mut storage = FieldStorage::from_owned(field);
581        storage.set_name("override");
582
583        // as_field_mut should apply cur_name
584        let field_mut = storage.as_field_mut();
585        assert_eq!(field_mut.get_name(), "override");
586
587        // After as_field_mut, cur_name should be consumed
588        assert_eq!(storage.as_field().get_name(), "override");
589    }
590
591    // ===== Zero-copy specific tests =====
592
593    #[test]
594    fn test_zero_copy_set_name() {
595        // Create Arc field
596        let field = Arc::new(Field::from_chars("original", "value"));
597        let original_count = Arc::strong_count(&field);
598
599        // Create Shared storage
600        let mut storage = FieldStorage::from_shared(Arc::clone(&field));
601        assert_eq!(Arc::strong_count(&field), original_count + 1);
602
603        // Zero-copy set name
604        storage.set_name("renamed");
605
606        // Verify: Arc reference count unchanged (no clone happened)
607        assert_eq!(Arc::strong_count(&field), original_count + 1);
608
609        // Verify: name updated
610        assert_eq!(storage.get_name(), "renamed");
611
612        // Verify: underlying field name unchanged
613        assert_eq!(field.get_name(), "original");
614
615        // Verify: value unchanged
616        assert_eq!(storage.get_value().as_str().unwrap(), "value");
617    }
618
619    #[test]
620    fn test_name_priority() {
621        let field = Field::from_chars("field_name", "value");
622        let mut storage = FieldStorage::from_owned(field);
623
624        // Initial: use field.name
625        assert_eq!(storage.get_name(), "field_name");
626
627        // Set cur_name
628        storage.set_name("override_name");
629
630        // cur_name takes priority
631        assert_eq!(storage.get_name(), "override_name");
632
633        // Underlying field name unchanged
634        assert_eq!(storage.as_field().get_name(), "field_name");
635    }
636
637    #[test]
638    fn test_into_owned_applies_cur_name() {
639        let field = Arc::new(Field::from_chars("original", "value"));
640        let mut storage = FieldStorage::from_shared(field);
641
642        storage.set_name("renamed");
643
644        let owned = storage.into_owned();
645
646        // Verify: name applied
647        assert_eq!(owned.get_name(), "renamed");
648        assert_eq!(owned.get_value().as_str().unwrap(), "value");
649    }
650
651    #[test]
652    fn test_shared_vs_owned() {
653        let arc_field = Arc::new(Field::from_chars("arc", "value1"));
654        let owned_field = Field::from_chars("owned", "value2");
655
656        let shared = FieldStorage::from_shared(arc_field);
657        let owned = FieldStorage::from_owned(owned_field);
658
659        assert!(shared.is_shared());
660        assert!(!shared.is_owned());
661
662        assert!(!owned.is_shared());
663        assert!(owned.is_owned());
664    }
665
666    #[test]
667    fn test_arc_strong_count() {
668        let field = Arc::new(Field::from_chars("test", "value"));
669        let initial_count = Arc::strong_count(&field);
670
671        let storage1 = FieldStorage::from_shared(Arc::clone(&field));
672        assert_eq!(storage1.shared_count(), Some(initial_count + 1));
673
674        let storage2 = FieldStorage::from_shared(Arc::clone(&field));
675        assert_eq!(storage2.shared_count(), Some(initial_count + 2));
676
677        let owned = FieldStorage::from_owned(Field::from_chars("test", "value"));
678        assert_eq!(owned.shared_count(), None);
679    }
680
681    #[test]
682    fn test_multi_stage_zero_copy() {
683        // Simulate multi-stage processing
684        let field = Arc::new(Field::from_chars("HOST", "192.168.1.1"));
685        let initial_count = Arc::strong_count(&field);
686
687        // Stage 1: rename to server_ip
688        let mut stage1 = FieldStorage::from_shared(Arc::clone(&field));
689        stage1.set_name("server_ip");
690
691        // Stage 2: rename to host_address
692        let mut stage2 = FieldStorage::from_shared(Arc::clone(&field));
693        stage2.set_name("host_address");
694
695        // Stage 3: rename to ip_addr
696        let mut stage3 = FieldStorage::from_shared(Arc::clone(&field));
697        stage3.set_name("ip_addr");
698
699        // Verify: all stages share the same Arc
700        assert_eq!(stage1.shared_count(), Some(initial_count + 3));
701        assert_eq!(stage2.shared_count(), Some(initial_count + 3));
702        assert_eq!(stage3.shared_count(), Some(initial_count + 3));
703
704        // Verify: each stage has independent name
705        assert_eq!(stage1.get_name(), "server_ip");
706        assert_eq!(stage2.get_name(), "host_address");
707        assert_eq!(stage3.get_name(), "ip_addr");
708
709        // Verify: all stages share the same value
710        assert_eq!(stage1.get_value().as_str().unwrap(), "192.168.1.1");
711        assert_eq!(stage2.get_value().as_str().unwrap(), "192.168.1.1");
712        assert_eq!(stage3.get_value().as_str().unwrap(), "192.168.1.1");
713    }
714
715    #[test]
716    fn test_record_item_get_name_with_cur_name() {
717        let field = Field::from_chars("original", "value");
718        let mut storage = FieldStorage::from_owned(field);
719        storage.set_name("overridden");
720
721        // RecordItem::get_name should return the effective name
722        let name: &str = RecordItem::get_name(&storage);
723        assert_eq!(name, "overridden");
724    }
725}