Skip to main content

qubit_value/value/
value.rs

1/*******************************************************************************
2 *
3 *    Copyright (c) 2025 - 2026.
4 *    Haixing Hu, Qubit Co. Ltd.
5 *
6 *    All rights reserved.
7 *
8 ******************************************************************************/
9//! # Single Value Container
10//!
11//! Provides type-safe storage and access functionality for single values.
12//!
13//! # Author
14//!
15//! Haixing Hu
16
17use bigdecimal::BigDecimal;
18use chrono::{DateTime, NaiveDate, NaiveDateTime, NaiveTime, Utc};
19use num_bigint::BigInt;
20use serde::{Deserialize, Serialize};
21use std::collections::HashMap;
22use std::time::Duration;
23use url::Url;
24
25use qubit_common::lang::DataType;
26
27use crate::error::ValueResult;
28
29/// Single value container
30///
31/// Uses an enum to represent different types of values, providing
32/// type-safe value storage and access.
33///
34/// # Features
35///
36/// - Zero-cost abstraction with compile-time type checking
37/// - Supports multiple basic data types
38/// - Provides two sets of APIs for type checking and type conversion
39/// - Automatic memory management
40///
41/// # Example
42///
43/// ```rust
44/// use qubit_value::Value;
45///
46/// // Create an integer value
47/// let value = Value::Int32(42);
48/// assert_eq!(value.get_int32().unwrap(), 42);
49///
50/// // Type conversion
51/// let converted = value.to::<i64>().unwrap();
52/// assert_eq!(converted, 42i64);
53///
54/// // String value
55/// let text = Value::String("hello".to_string());
56/// assert_eq!(text.get_string().unwrap(), "hello");
57/// ```
58///
59/// # Author
60///
61/// Haixing Hu
62///
63#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
64pub enum Value {
65    /// Empty value (has type but no value)
66    Empty(DataType),
67    /// Boolean value
68    Bool(bool),
69    /// Character value
70    Char(char),
71    /// 8-bit signed integer
72    Int8(i8),
73    /// 16-bit signed integer
74    Int16(i16),
75    /// 32-bit signed integer
76    Int32(i32),
77    /// 64-bit signed integer
78    Int64(i64),
79    /// 128-bit signed integer
80    Int128(i128),
81    /// 8-bit unsigned integer
82    UInt8(u8),
83    /// 16-bit unsigned integer
84    UInt16(u16),
85    /// 32-bit unsigned integer
86    UInt32(u32),
87    /// 64-bit unsigned integer
88    UInt64(u64),
89    /// 128-bit unsigned integer
90    UInt128(u128),
91    /// Platform-dependent signed integer (isize)
92    IntSize(isize),
93    /// Platform-dependent unsigned integer (usize)
94    UIntSize(usize),
95    /// 32-bit floating point number
96    Float32(f32),
97    /// 64-bit floating point number
98    Float64(f64),
99    /// Big integer type
100    BigInteger(BigInt),
101    /// Big decimal type
102    BigDecimal(BigDecimal),
103    /// String
104    String(String),
105    /// Date
106    Date(NaiveDate),
107    /// Time
108    Time(NaiveTime),
109    /// Date and time
110    DateTime(NaiveDateTime),
111    /// UTC instant
112    Instant(DateTime<Utc>),
113    /// Duration type (std::time::Duration)
114    Duration(Duration),
115    /// URL type (url::Url)
116    Url(Url),
117    /// String map type (HashMap<String, String>)
118    StringMap(HashMap<String, String>),
119    /// JSON value type (serde_json::Value)
120    Json(serde_json::Value),
121}
122
123pub use super::value_converters::{ValueConstructor, ValueConverter, ValueGetter, ValueSetter};
124
125// ============================================================================
126// Getter method generation macro
127// ============================================================================
128
129/// Unified getter generation macro
130///
131/// Supports two modes:
132/// 1. `copy:` - For types implementing the Copy trait, directly returns the value
133/// 2. `ref:` - For non-Copy types, returns a reference
134///
135/// # Documentation Comment Support
136///
137/// The macro automatically extracts preceding documentation comments, so
138/// you can add `///` comments before macro invocations.
139///
140/// # Author
141///
142/// Haixing Hu
143///
144impl Value {
145    /// Generic constructor method
146    ///
147    /// Creates a `Value` from any supported type, avoiding direct use of
148    /// enum variants.
149    ///
150    /// # Supported Generic Types
151    ///
152    /// `Value::new<T>(value)` currently supports the following `T`:
153    ///
154    /// - `bool`
155    /// - `char`
156    /// - `i8`, `i16`, `i32`, `i64`, `i128`
157    /// - `u8`, `u16`, `u32`, `u64`, `u128`
158    /// - `f32`, `f64`
159    /// - `String`, `&str`
160    /// - `NaiveDate`, `NaiveTime`, `NaiveDateTime`, `DateTime<Utc>`
161    /// - `BigInt`, `BigDecimal`
162    /// - `isize`, `usize`
163    /// - `Duration`
164    /// - `Url`
165    /// - `HashMap<String, String>`
166    /// - `serde_json::Value`
167    ///
168    /// # Type Parameters
169    ///
170    /// * `T` - The type of the value to wrap
171    ///
172    /// # Returns
173    ///
174    /// Returns a `Value` wrapping the given value
175    ///
176    /// # Example
177    ///
178    /// ```rust
179    /// use qubit_value::Value;
180    ///
181    /// // Basic types
182    /// let v = Value::new(42i32);
183    /// assert_eq!(v.get_int32().unwrap(), 42);
184    ///
185    /// let v = Value::new(true);
186    /// assert_eq!(v.get_bool().unwrap(), true);
187    ///
188    /// // String
189    /// let v = Value::new("hello".to_string());
190    /// assert_eq!(v.get_string().unwrap(), "hello");
191    /// ```
192    #[inline]
193    pub fn new<T>(value: T) -> Self
194    where
195        Self: ValueConstructor<T>,
196    {
197        <Self as ValueConstructor<T>>::from_type(value)
198    }
199
200    /// Generic getter method
201    ///
202    /// Automatically selects the correct getter method based on the target
203    /// type, performing strict type checking.
204    ///
205    /// `get<T>()` performs strict type matching. It does not do cross-type
206    /// conversion.
207    ///
208    /// For example, `Value::Int32(42).get::<i64>()` fails, while
209    /// `Value::Int32(42).to::<i64>()` succeeds.
210    ///
211    /// # Supported Generic Types
212    ///
213    /// `Value::get<T>()` currently supports the following `T`:
214    ///
215    /// - `bool`
216    /// - `char`
217    /// - `i8`, `i16`, `i32`, `i64`, `i128`
218    /// - `u8`, `u16`, `u32`, `u64`, `u128`
219    /// - `f32`, `f64`
220    /// - `String`
221    /// - `NaiveDate`, `NaiveTime`, `NaiveDateTime`, `DateTime<Utc>`
222    /// - `BigInt`, `BigDecimal`
223    /// - `isize`, `usize`
224    /// - `Duration`
225    /// - `Url`
226    /// - `HashMap<String, String>`
227    /// - `serde_json::Value`
228    ///
229    /// # Type Parameters
230    ///
231    /// * `T` - The target type to retrieve
232    ///
233    /// # Returns
234    ///
235    /// If types match, returns the value of the corresponding type;
236    /// otherwise returns an error
237    ///
238    /// # Example
239    ///
240    /// ```rust
241    /// use qubit_value::Value;
242    ///
243    /// let value = Value::Int32(42);
244    ///
245    /// // Through type inference
246    /// let num: i32 = value.get().unwrap();
247    /// assert_eq!(num, 42);
248    ///
249    /// // Explicitly specify type parameter
250    /// let num = value.get::<i32>().unwrap();
251    /// assert_eq!(num, 42);
252    ///
253    /// // Different type
254    /// let text = Value::String("hello".to_string());
255    /// let s: String = text.get().unwrap();
256    /// assert_eq!(s, "hello");
257    ///
258    /// // Boolean value
259    /// let flag = Value::Bool(true);
260    /// let b: bool = flag.get().unwrap();
261    /// assert_eq!(b, true);
262    /// ```
263    #[inline]
264    pub fn get<T>(&self) -> ValueResult<T>
265    where
266        Self: ValueGetter<T>,
267    {
268        <Self as ValueGetter<T>>::get_value(self)
269    }
270
271    /// Generic conversion method
272    ///
273    /// Converts the current value to the target type according to the conversion
274    /// rules defined by [`ValueConverter<T>`].
275    ///
276    /// # Supported Target Types And Source Variants
277    ///
278    /// `Value::to<T>()` currently supports the following target types:
279    ///
280    /// - `bool`
281    ///   - `Value::Bool`
282    ///   - `Value::Int8`, `Value::Int16`, `Value::Int32`, `Value::Int64`,
283    ///     `Value::Int128`
284    ///   - `Value::UInt8`, `Value::UInt16`, `Value::UInt32`,
285    ///     `Value::UInt64`, `Value::UInt128`
286    ///   - `Value::String`, parsed as `bool`
287    /// - `char`
288    ///   - `Value::Char`
289    /// - `i8`
290    ///   - `Value::Int8`
291    /// - `i16`
292    ///   - `Value::Int16`
293    /// - `i32`
294    ///   - `Value::Int32`
295    ///   - `Value::Bool`
296    ///   - `Value::Char`
297    ///   - `Value::Int8`, `Value::Int16`, `Value::Int64`, `Value::Int128`
298    ///   - `Value::UInt8`, `Value::UInt16`, `Value::UInt32`,
299    ///     `Value::UInt64`, `Value::UInt128`
300    ///   - `Value::Float32`, `Value::Float64`
301    ///   - `Value::String`, parsed as `i32`
302    ///   - `Value::BigInteger`, `Value::BigDecimal`
303    /// - `i64`
304    ///   - `Value::Int64`
305    ///   - `Value::Bool`
306    ///   - `Value::Char`
307    ///   - `Value::Int8`, `Value::Int16`, `Value::Int32`, `Value::Int128`
308    ///   - `Value::UInt8`, `Value::UInt16`, `Value::UInt32`,
309    ///     `Value::UInt64`, `Value::UInt128`
310    ///   - `Value::Float32`, `Value::Float64`
311    ///   - `Value::String`, parsed as `i64`
312    ///   - `Value::BigInteger`, `Value::BigDecimal`
313    /// - `i128`
314    ///   - `Value::Int128`
315    /// - `u8`
316    ///   - `Value::UInt8`
317    ///   - `Value::Bool`
318    ///   - `Value::Char`
319    ///   - `Value::Int8`, `Value::Int16`, `Value::Int32`, `Value::Int64`,
320    ///     `Value::Int128`
321    ///   - `Value::UInt16`, `Value::UInt32`, `Value::UInt64`,
322    ///     `Value::UInt128`
323    ///   - `Value::String`, parsed as `u8`
324    /// - `u16`
325    ///   - `Value::UInt8`, `Value::UInt16`, `Value::UInt32`,
326    ///     `Value::UInt64`, `Value::UInt128`
327    ///   - `Value::Bool`
328    ///   - `Value::Char`
329    ///   - `Value::Int8`, `Value::Int16`, `Value::Int32`, `Value::Int64`,
330    ///     `Value::Int128`
331    ///   - `Value::String`, parsed as `u16`
332    /// - `u32`
333    ///   - `Value::UInt8`, `Value::UInt16`, `Value::UInt32`,
334    ///     `Value::UInt64`, `Value::UInt128`
335    ///   - `Value::Bool`
336    ///   - `Value::Char`
337    ///   - `Value::Int8`, `Value::Int16`, `Value::Int32`, `Value::Int64`,
338    ///     `Value::Int128`
339    ///   - `Value::String`, parsed as `u32`
340    /// - `u64`
341    ///   - `Value::UInt8`, `Value::UInt16`, `Value::UInt32`,
342    ///     `Value::UInt64`, `Value::UInt128`
343    ///   - `Value::Bool`
344    ///   - `Value::Char`
345    ///   - `Value::Int8`, `Value::Int16`, `Value::Int32`, `Value::Int64`,
346    ///     `Value::Int128`
347    ///   - `Value::String`, parsed as `u64`
348    /// - `u128`
349    ///   - `Value::UInt8`, `Value::UInt16`, `Value::UInt32`,
350    ///     `Value::UInt64`, `Value::UInt128`
351    ///   - `Value::Bool`
352    ///   - `Value::Char`
353    ///   - `Value::Int8`, `Value::Int16`, `Value::Int32`, `Value::Int64`,
354    ///     `Value::Int128`
355    ///   - `Value::String`, parsed as `u128`
356    /// - `f32`
357    ///   - `Value::Float32`, `Value::Float64`
358    ///   - `Value::Bool`
359    ///   - `Value::Char`
360    ///   - `Value::Int8`, `Value::Int16`, `Value::Int32`, `Value::Int64`,
361    ///     `Value::Int128`
362    ///   - `Value::UInt8`, `Value::UInt16`, `Value::UInt32`,
363    ///     `Value::UInt64`, `Value::UInt128`
364    ///   - `Value::String`, parsed as `f32`
365    ///   - `Value::BigInteger`, `Value::BigDecimal`
366    /// - `f64`
367    ///   - `Value::Float64`
368    ///   - `Value::Bool`
369    ///   - `Value::Char`
370    ///   - `Value::Int8`, `Value::Int16`, `Value::Int32`, `Value::Int64`,
371    ///     `Value::Int128`
372    ///   - `Value::UInt8`, `Value::UInt16`, `Value::UInt32`,
373    ///     `Value::UInt64`, `Value::UInt128`
374    ///   - `Value::Float32`
375    ///   - `Value::String`, parsed as `f64`
376    ///   - `Value::BigInteger`, `Value::BigDecimal`
377    /// - `String`
378    ///   - `Value::String`
379    ///   - `Value::Bool`, `Value::Char`
380    ///   - all integer and floating-point variants
381    ///   - `Value::Date`, `Value::Time`, `Value::DateTime`, `Value::Instant`
382    ///   - `Value::BigInteger`, `Value::BigDecimal`
383    ///   - `Value::IntSize`, `Value::UIntSize`
384    ///   - `Value::Duration`, formatted as `<nanoseconds>ns`
385    ///   - `Value::Url`
386    ///   - `Value::StringMap`, serialized as JSON text
387    ///   - `Value::Json`, serialized as JSON text
388    /// - `NaiveDate`
389    ///   - `Value::Date`
390    /// - `NaiveTime`
391    ///   - `Value::Time`
392    /// - `NaiveDateTime`
393    ///   - `Value::DateTime`
394    /// - `DateTime<Utc>`
395    ///   - `Value::Instant`
396    /// - `BigInt`
397    ///   - `Value::BigInteger`
398    /// - `BigDecimal`
399    ///   - `Value::BigDecimal`
400    /// - `isize`
401    ///   - `Value::IntSize`
402    /// - `usize`
403    ///   - `Value::UIntSize`
404    /// - `Duration`
405    ///   - `Value::Duration`
406    ///   - `Value::String`, parsed from `<nanoseconds>ns`
407    /// - `Url`
408    ///   - `Value::Url`
409    ///   - `Value::String`, parsed as URL text
410    /// - `HashMap<String, String>`
411    ///   - `Value::StringMap`
412    /// - `serde_json::Value`
413    ///   - `Value::Json`
414    ///   - `Value::String`, parsed as JSON text
415    ///   - `Value::StringMap`, converted to a JSON object
416    ///
417    /// Any target type not listed above is not supported by `Value::to<T>()`.
418    ///
419    /// # Type Parameters
420    ///
421    /// * `T` - The target type to convert to
422    ///
423    /// # Returns
424    ///
425    /// Returns the converted value on success, or an error if conversion is not
426    /// supported or fails.
427    ///
428    /// # Example
429    ///
430    /// ```rust
431    /// use qubit_value::Value;
432    ///
433    /// let value = Value::Int32(42);
434    ///
435    /// let num: i64 = value.to().unwrap();
436    /// assert_eq!(num, 42);
437    ///
438    /// let text: String = value.to().unwrap();
439    /// assert_eq!(text, "42");
440    /// ```
441    #[inline]
442    pub fn to<T>(&self) -> ValueResult<T>
443    where
444        Self: ValueConverter<T>,
445    {
446        <Self as ValueConverter<T>>::convert(self)
447    }
448
449    /// Generic setter method
450    ///
451    /// Automatically selects the correct setter method based on the target
452    /// type and replaces the current value.
453    ///
454    /// This operation updates the stored type to `T` when needed. It does not
455    /// perform runtime type-mismatch validation against the previous variant.
456    ///
457    /// # Supported Generic Types
458    ///
459    /// `Value::set<T>(value)` currently supports the following `T`:
460    ///
461    /// - `bool`
462    /// - `char`
463    /// - `i8`, `i16`, `i32`, `i64`, `i128`
464    /// - `u8`, `u16`, `u32`, `u64`, `u128`
465    /// - `f32`, `f64`
466    /// - `String`, `&str`
467    /// - `NaiveDate`, `NaiveTime`, `NaiveDateTime`, `DateTime<Utc>`
468    /// - `BigInt`, `BigDecimal`
469    /// - `isize`, `usize`
470    /// - `Duration`
471    /// - `Url`
472    /// - `HashMap<String, String>`
473    /// - `serde_json::Value`
474    ///
475    /// # Type Parameters
476    ///
477    /// * `T` - The target type to set
478    ///
479    /// # Parameters
480    ///
481    /// * `value` - The value to set
482    ///
483    /// # Returns
484    ///
485    /// If setting succeeds, returns `Ok(())`; otherwise returns an error
486    ///
487    /// # Example
488    ///
489    /// ```rust
490    /// use qubit_common::lang::DataType;
491    /// use qubit_value::Value;
492    ///
493    /// let mut value = Value::Empty(DataType::Int32);
494    ///
495    /// // Through type inference
496    /// value.set(42i32).unwrap();
497    /// assert_eq!(value.get_int32().unwrap(), 42);
498    ///
499    /// // Explicitly specify type parameter
500    /// value.set::<i32>(100).unwrap();
501    /// assert_eq!(value.get_int32().unwrap(), 100);
502    ///
503    /// // String type
504    /// let mut text = Value::Empty(DataType::String);
505    /// text.set("hello".to_string()).unwrap();
506    /// assert_eq!(text.get_string().unwrap(), "hello");
507    /// ```
508    #[inline]
509    pub fn set<T>(&mut self, value: T) -> ValueResult<()>
510    where
511        Self: ValueSetter<T>,
512    {
513        <Self as ValueSetter<T>>::set_value(self, value)
514    }
515
516    /// Get the data type of the value
517    ///
518    /// # Returns
519    ///
520    /// Returns the data type corresponding to this value
521    ///
522    /// # Example
523    ///
524    /// ```rust
525    /// use qubit_common::lang::DataType;
526    /// use qubit_value::Value;
527    ///
528    /// let value = Value::Int32(42);
529    /// assert_eq!(value.data_type(), DataType::Int32);
530    ///
531    /// let empty = Value::Empty(DataType::String);
532    /// assert_eq!(empty.data_type(), DataType::String);
533    /// ```
534    #[inline]
535    pub fn data_type(&self) -> DataType {
536        match self {
537            Value::Empty(dt) => *dt,
538            Value::Bool(_) => DataType::Bool,
539            Value::Char(_) => DataType::Char,
540            Value::Int8(_) => DataType::Int8,
541            Value::Int16(_) => DataType::Int16,
542            Value::Int32(_) => DataType::Int32,
543            Value::Int64(_) => DataType::Int64,
544            Value::Int128(_) => DataType::Int128,
545            Value::UInt8(_) => DataType::UInt8,
546            Value::UInt16(_) => DataType::UInt16,
547            Value::UInt32(_) => DataType::UInt32,
548            Value::UInt64(_) => DataType::UInt64,
549            Value::UInt128(_) => DataType::UInt128,
550            Value::Float32(_) => DataType::Float32,
551            Value::Float64(_) => DataType::Float64,
552            Value::String(_) => DataType::String,
553            Value::Date(_) => DataType::Date,
554            Value::Time(_) => DataType::Time,
555            Value::DateTime(_) => DataType::DateTime,
556            Value::Instant(_) => DataType::Instant,
557            Value::BigInteger(_) => DataType::BigInteger,
558            Value::BigDecimal(_) => DataType::BigDecimal,
559            Value::IntSize(_) => DataType::IntSize,
560            Value::UIntSize(_) => DataType::UIntSize,
561            Value::Duration(_) => DataType::Duration,
562            Value::Url(_) => DataType::Url,
563            Value::StringMap(_) => DataType::StringMap,
564            Value::Json(_) => DataType::Json,
565        }
566    }
567
568    /// Check if the value is empty
569    ///
570    /// # Returns
571    ///
572    /// Returns `true` if the value is empty
573    ///
574    /// # Example
575    ///
576    /// ```rust
577    /// use qubit_common::lang::DataType;
578    /// use qubit_value::Value;
579    ///
580    /// let value = Value::Int32(42);
581    /// assert!(!value.is_empty());
582    ///
583    /// let empty = Value::Empty(DataType::String);
584    /// assert!(empty.is_empty());
585    /// ```
586    #[inline]
587    pub fn is_empty(&self) -> bool {
588        matches!(self, Value::Empty(_))
589    }
590
591    /// Clear the value while preserving the type
592    ///
593    /// Sets the current value to empty but retains its data type.
594    ///
595    /// # Example
596    ///
597    /// ```rust
598    /// use qubit_common::lang::DataType;
599    /// use qubit_value::Value;
600    ///
601    /// let mut value = Value::Int32(42);
602    /// value.clear();
603    /// assert!(value.is_empty());
604    /// assert_eq!(value.data_type(), DataType::Int32);
605    /// ```
606    #[inline]
607    pub fn clear(&mut self) {
608        let dt = self.data_type();
609        *self = Value::Empty(dt);
610    }
611
612    /// Set the data type
613    ///
614    /// If the new type differs from the current type, clears the value
615    /// and sets the new type.
616    ///
617    /// # Parameters
618    ///
619    /// * `data_type` - The data type to set
620    ///
621    /// # Example
622    ///
623    /// ```rust
624    /// use qubit_common::lang::DataType;
625    /// use qubit_value::Value;
626    ///
627    /// let mut value = Value::Int32(42);
628    /// value.set_type(DataType::String);
629    /// assert!(value.is_empty());
630    /// assert_eq!(value.data_type(), DataType::String);
631    /// ```
632    #[inline]
633    pub fn set_type(&mut self, data_type: DataType) {
634        if self.data_type() != data_type {
635            *self = Value::Empty(data_type);
636        }
637    }
638}
639
640impl Default for Value {
641    #[inline]
642    fn default() -> Self {
643        Value::Empty(DataType::String)
644    }
645}