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}