Skip to main content

qubit_value/
named_multi_values.rs

1/*******************************************************************************
2 *
3 *    Copyright (c) 2025 - 2026 Haixing Hu.
4 *
5 *    SPDX-License-Identifier: Apache-2.0
6 *
7 *    Licensed under the Apache License, Version 2.0.
8 *
9 ******************************************************************************/
10//! # Named Multiple Values
11//!
12//! Provides a lightweight container for binding names to multiple value collections,
13//! facilitating human-readable identification of groups of values in configurations,
14//! serialization, logging, and other scenarios.
15//!
16
17use serde::{
18    Deserialize,
19    Serialize,
20};
21use std::ops::{
22    Deref,
23    DerefMut,
24};
25
26use super::multi_values::MultiValues;
27use super::named_value::NamedValue;
28
29/// Named multiple values
30///
31/// A container that associates a readable name with a set of `MultiValues`, suitable for
32/// organizing data in key-value (name-multiple values) scenarios, such as configuration items,
33/// command-line parameter aggregation, structured log fields, etc.
34///
35/// # Features
36///
37/// - Provides clear name identification for multiple value collections
38/// - Transparently reuses all capabilities of `MultiValues` through `Deref/DerefMut`
39/// - Supports `serde` serialization and deserialization
40///
41/// # Use Cases
42///
43/// - Aggregating a set of ports, hostnames, etc., as semantically meaningful fields
44/// - Outputting named multiple value lists in configurations/logs
45///
46/// # Example
47///
48/// ```rust
49/// use qubit_value::{NamedMultiValues, MultiValues};
50///
51/// // Identify a group of ports with the name "ports"
52/// let named = NamedMultiValues::new(
53///     "ports",
54///     MultiValues::Int32(vec![8080, 8081, 8082])
55/// );
56///
57/// assert_eq!(named.name(), "ports");
58/// assert_eq!(named.count(), 3);
59/// ```
60///
61///
62#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
63pub struct NamedMultiValues {
64    /// Name of the values
65    name: String,
66    /// Content of the multiple values
67    value: MultiValues,
68}
69
70impl NamedMultiValues {
71    /// Create a new named multiple values
72    ///
73    /// Associates a given name with `MultiValues`, generating a container that can be referenced by name.
74    ///
75    /// # Use Cases
76    ///
77    /// - Building configuration fields (e.g., `servers`, `ports`, etc.)
78    /// - Binding parsed multiple value results to semantic names
79    ///
80    /// # Parameters
81    ///
82    /// * `name` - Name of the multiple values
83    /// * `value` - Content of the multiple values
84    ///
85    /// # Returns
86    ///
87    /// Returns a newly created named multiple values
88    ///
89    /// # Example
90    ///
91    /// ```rust
92    /// use qubit_value::{NamedMultiValues, MultiValues};
93    ///
94    /// let named = NamedMultiValues::new(
95    ///     "servers",
96    ///     MultiValues::String(vec!["s1".to_string(), "s2".to_string()])
97    /// );
98    /// assert_eq!(named.name(), "servers");
99    /// ```
100    #[inline]
101    pub fn new(name: impl Into<String>, value: MultiValues) -> Self {
102        Self {
103            name: name.into(),
104            value,
105        }
106    }
107
108    /// Get a reference to the name
109    ///
110    /// # Returns
111    ///
112    /// Returns a string slice of the name
113    ///
114    /// # Example
115    ///
116    /// ```rust
117    /// use qubit_value::{NamedMultiValues, MultiValues};
118    ///
119    /// let named = NamedMultiValues::new("items", MultiValues::Int32(vec![1, 2, 3]));
120    /// assert_eq!(named.name(), "items");
121    /// ```
122    #[inline]
123    pub fn name(&self) -> &str {
124        &self.name
125    }
126
127    // Methods of MultiValues are forwarded through Deref/DerefMut
128
129    /// Set a new name
130    ///
131    /// # Parameters
132    ///
133    /// * `name` - The new name
134    ///
135    /// # Returns
136    ///
137    /// No return value
138    ///
139    /// # Example
140    ///
141    /// ```rust
142    /// use qubit_value::{NamedMultiValues, MultiValues};
143    ///
144    /// let mut named = NamedMultiValues::new("old", MultiValues::Bool(vec![true]));
145    /// named.set_name("new");
146    /// assert_eq!(named.name(), "new");
147    /// ```
148    #[inline]
149    pub fn set_name(&mut self, name: impl Into<String>) {
150        self.name = name.into();
151    }
152
153    /// Convert this named multi-values into a named single value.
154    ///
155    /// The returned value keeps the same name and uses the first element from
156    /// the inner [`MultiValues`]. If there is no element, the returned value is
157    /// `Value::Empty` with the same data type.
158    #[inline]
159    pub fn to_named_value(&self) -> NamedValue {
160        NamedValue::new(self.name.as_str(), self.value.to_value())
161    }
162
163    // Values can be directly assigned or mutable methods called on the inner value through DerefMut
164}
165
166/// Transparently delegate read-only methods to the inner `MultiValues` through `Deref`.
167impl Deref for NamedMultiValues {
168    type Target = MultiValues;
169
170    #[inline]
171    fn deref(&self) -> &Self::Target {
172        &self.value
173    }
174}
175
176/// Transparently delegate mutable methods to the inner `MultiValues` through `DerefMut`.
177impl DerefMut for NamedMultiValues {
178    #[inline]
179    fn deref_mut(&mut self) -> &mut Self::Target {
180        &mut self.value
181    }
182}
183
184impl From<NamedValue> for NamedMultiValues {
185    /// Construct `NamedMultiValues` from `NamedValue`
186    ///
187    /// Reuses the name and promotes the single value to a `MultiValues` containing only one element.
188    #[inline]
189    fn from(named: NamedValue) -> Self {
190        let (name, value) = named.into_parts();
191        let value = MultiValues::from(value);
192        Self { name, value }
193    }
194}