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::value_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
123#[doc(hidden)]
124pub use super::value_constructor::ValueConstructor;
125#[doc(hidden)]
126pub use super::value_converter::ValueConverter;
127#[doc(hidden)]
128pub use super::value_getter::ValueGetter;
129#[doc(hidden)]
130pub use super::value_setter::ValueSetter;
131
132// ============================================================================
133// Getter method generation macro
134// ============================================================================
135
136/// Unified getter generation macro
137///
138/// Supports two modes:
139/// 1. `copy:` - For types implementing the Copy trait, directly returns the value
140/// 2. `ref:` - For non-Copy types, returns a reference
141///
142/// # Documentation Comment Support
143///
144/// The macro automatically extracts preceding documentation comments, so
145/// you can add `///` comments before macro invocations.
146///
147/// # Author
148///
149/// Haixing Hu
150///
151impl Value {
152    /// Generic constructor method
153    ///
154    /// Creates a `Value` from any supported type, avoiding direct use of
155    /// enum variants.
156    ///
157    /// # Supported Generic Types
158    ///
159    /// `Value::new<T>(value)` currently supports the following `T`:
160    ///
161    /// - `bool`
162    /// - `char`
163    /// - `i8`, `i16`, `i32`, `i64`, `i128`
164    /// - `u8`, `u16`, `u32`, `u64`, `u128`
165    /// - `f32`, `f64`
166    /// - `String`, `&str`
167    /// - `NaiveDate`, `NaiveTime`, `NaiveDateTime`, `DateTime<Utc>`
168    /// - `BigInt`, `BigDecimal`
169    /// - `isize`, `usize`
170    /// - `Duration`
171    /// - `Url`
172    /// - `HashMap<String, String>`
173    /// - `serde_json::Value`
174    ///
175    /// # Type Parameters
176    ///
177    /// * `T` - The type of the value to wrap
178    ///
179    /// # Returns
180    ///
181    /// Returns a `Value` wrapping the given value
182    ///
183    /// # Example
184    ///
185    /// ```rust
186    /// use qubit_value::Value;
187    ///
188    /// // Basic types
189    /// let v = Value::new(42i32);
190    /// assert_eq!(v.get_int32().unwrap(), 42);
191    ///
192    /// let v = Value::new(true);
193    /// assert_eq!(v.get_bool().unwrap(), true);
194    ///
195    /// // String
196    /// let v = Value::new("hello".to_string());
197    /// assert_eq!(v.get_string().unwrap(), "hello");
198    /// ```
199    #[inline]
200    pub fn new<T>(value: T) -> Self
201    where
202        Self: ValueConstructor<T>,
203    {
204        <Self as ValueConstructor<T>>::from_type(value)
205    }
206
207    /// Generic getter method
208    ///
209    /// Automatically selects the correct getter method based on the target
210    /// type, performing strict type checking.
211    ///
212    /// `get<T>()` performs strict type matching. It does not do cross-type
213    /// conversion.
214    ///
215    /// For example, `Value::Int32(42).get::<i64>()` fails, while
216    /// `Value::Int32(42).to::<i64>()` succeeds.
217    ///
218    /// # Supported Generic Types
219    ///
220    /// `Value::get<T>()` currently supports the following `T`:
221    ///
222    /// - `bool`
223    /// - `char`
224    /// - `i8`, `i16`, `i32`, `i64`, `i128`
225    /// - `u8`, `u16`, `u32`, `u64`, `u128`
226    /// - `f32`, `f64`
227    /// - `String`
228    /// - `NaiveDate`, `NaiveTime`, `NaiveDateTime`, `DateTime<Utc>`
229    /// - `BigInt`, `BigDecimal`
230    /// - `isize`, `usize`
231    /// - `Duration`
232    /// - `Url`
233    /// - `HashMap<String, String>`
234    /// - `serde_json::Value`
235    ///
236    /// # Type Parameters
237    ///
238    /// * `T` - The target type to retrieve
239    ///
240    /// # Returns
241    ///
242    /// If types match, returns the value of the corresponding type;
243    /// otherwise returns an error
244    ///
245    /// # Example
246    ///
247    /// ```rust
248    /// use qubit_value::Value;
249    ///
250    /// let value = Value::Int32(42);
251    ///
252    /// // Through type inference
253    /// let num: i32 = value.get().unwrap();
254    /// assert_eq!(num, 42);
255    ///
256    /// // Explicitly specify type parameter
257    /// let num = value.get::<i32>().unwrap();
258    /// assert_eq!(num, 42);
259    ///
260    /// // Different type
261    /// let text = Value::String("hello".to_string());
262    /// let s: String = text.get().unwrap();
263    /// assert_eq!(s, "hello");
264    ///
265    /// // Boolean value
266    /// let flag = Value::Bool(true);
267    /// let b: bool = flag.get().unwrap();
268    /// assert_eq!(b, true);
269    /// ```
270    #[inline]
271    pub fn get<T>(&self) -> ValueResult<T>
272    where
273        Self: ValueGetter<T>,
274    {
275        <Self as ValueGetter<T>>::get_value(self)
276    }
277
278    /// Generic conversion method
279    ///
280    /// Converts the current value to the target type according to the conversion
281    /// rules defined by [`ValueConverter<T>`].
282    ///
283    /// # Supported Target Types And Source Variants
284    ///
285    /// `Value::to<T>()` currently supports the following target types:
286    ///
287    /// - `bool`
288    ///   - `Value::Bool`
289    ///   - `Value::Int8`, `Value::Int16`, `Value::Int32`, `Value::Int64`,
290    ///     `Value::Int128`
291    ///   - `Value::UInt8`, `Value::UInt16`, `Value::UInt32`,
292    ///     `Value::UInt64`, `Value::UInt128`
293    ///   - `Value::String`, parsed as `1`, `0`, or ASCII case-insensitive
294    ///     `true` / `false`
295    /// - `char`
296    ///   - `Value::Char`
297    /// - `i8`
298    ///   - `Value::Int8`
299    ///   - `Value::Bool`
300    ///   - `Value::Char`
301    ///   - all integer variants
302    ///   - `Value::Float32`, `Value::Float64`
303    ///   - `Value::String`, parsed as `i8`
304    ///   - `Value::BigInteger`, `Value::BigDecimal`
305    /// - `i16`
306    ///   - `Value::Int16`
307    ///   - `Value::Bool`
308    ///   - `Value::Char`
309    ///   - all integer variants
310    ///   - `Value::Float32`, `Value::Float64`
311    ///   - `Value::String`, parsed as `i16`
312    ///   - `Value::BigInteger`, `Value::BigDecimal`
313    /// - `i32`
314    ///   - `Value::Int32`
315    ///   - `Value::Bool`
316    ///   - `Value::Char`
317    ///   - `Value::Int8`, `Value::Int16`, `Value::Int64`, `Value::Int128`
318    ///   - `Value::UInt8`, `Value::UInt16`, `Value::UInt32`,
319    ///     `Value::UInt64`, `Value::UInt128`
320    ///   - `Value::Float32`, `Value::Float64`
321    ///   - `Value::String`, parsed as `i32`
322    ///   - `Value::BigInteger`, `Value::BigDecimal`
323    /// - `i64`
324    ///   - `Value::Int64`
325    ///   - `Value::Bool`
326    ///   - `Value::Char`
327    ///   - `Value::Int8`, `Value::Int16`, `Value::Int32`, `Value::Int128`
328    ///   - `Value::UInt8`, `Value::UInt16`, `Value::UInt32`,
329    ///     `Value::UInt64`, `Value::UInt128`
330    ///   - `Value::Float32`, `Value::Float64`
331    ///   - `Value::String`, parsed as `i64`
332    ///   - `Value::BigInteger`, `Value::BigDecimal`
333    /// - `i128`
334    ///   - `Value::Int128`
335    ///   - `Value::Bool`
336    ///   - `Value::Char`
337    ///   - all integer variants
338    ///   - `Value::Float32`, `Value::Float64`
339    ///   - `Value::String`, parsed as `i128`
340    ///   - `Value::BigInteger`, `Value::BigDecimal`
341    /// - `u8`
342    ///   - `Value::UInt8`
343    ///   - `Value::Bool`
344    ///   - `Value::Char`
345    ///   - `Value::Int8`, `Value::Int16`, `Value::Int32`, `Value::Int64`,
346    ///     `Value::Int128`
347    ///   - `Value::UInt16`, `Value::UInt32`, `Value::UInt64`,
348    ///     `Value::UInt128`
349    ///   - `Value::String`, parsed as `u8`
350    /// - `u16`
351    ///   - `Value::UInt8`, `Value::UInt16`, `Value::UInt32`,
352    ///     `Value::UInt64`, `Value::UInt128`
353    ///   - `Value::Bool`
354    ///   - `Value::Char`
355    ///   - `Value::Int8`, `Value::Int16`, `Value::Int32`, `Value::Int64`,
356    ///     `Value::Int128`
357    ///   - `Value::String`, parsed as `u16`
358    /// - `u32`
359    ///   - `Value::UInt8`, `Value::UInt16`, `Value::UInt32`,
360    ///     `Value::UInt64`, `Value::UInt128`
361    ///   - `Value::Bool`
362    ///   - `Value::Char`
363    ///   - `Value::Int8`, `Value::Int16`, `Value::Int32`, `Value::Int64`,
364    ///     `Value::Int128`
365    ///   - `Value::String`, parsed as `u32`
366    /// - `u64`
367    ///   - `Value::UInt8`, `Value::UInt16`, `Value::UInt32`,
368    ///     `Value::UInt64`, `Value::UInt128`
369    ///   - `Value::Bool`
370    ///   - `Value::Char`
371    ///   - `Value::Int8`, `Value::Int16`, `Value::Int32`, `Value::Int64`,
372    ///     `Value::Int128`
373    ///   - `Value::String`, parsed as `u64`
374    /// - `u128`
375    ///   - `Value::UInt8`, `Value::UInt16`, `Value::UInt32`,
376    ///     `Value::UInt64`, `Value::UInt128`
377    ///   - `Value::Bool`
378    ///   - `Value::Char`
379    ///   - `Value::Int8`, `Value::Int16`, `Value::Int32`, `Value::Int64`,
380    ///     `Value::Int128`
381    ///   - `Value::String`, parsed as `u128`
382    /// - `f32`
383    ///   - `Value::Float32`, `Value::Float64`
384    ///   - `Value::Bool`
385    ///   - `Value::Char`
386    ///   - `Value::Int8`, `Value::Int16`, `Value::Int32`, `Value::Int64`,
387    ///     `Value::Int128`
388    ///   - `Value::UInt8`, `Value::UInt16`, `Value::UInt32`,
389    ///     `Value::UInt64`, `Value::UInt128`
390    ///   - `Value::String`, parsed as `f32`
391    ///   - `Value::BigInteger`, `Value::BigDecimal`
392    /// - `f64`
393    ///   - `Value::Float64`
394    ///   - `Value::Bool`
395    ///   - `Value::Char`
396    ///   - `Value::Int8`, `Value::Int16`, `Value::Int32`, `Value::Int64`,
397    ///     `Value::Int128`
398    ///   - `Value::UInt8`, `Value::UInt16`, `Value::UInt32`,
399    ///     `Value::UInt64`, `Value::UInt128`
400    ///   - `Value::Float32`
401    ///   - `Value::String`, parsed as `f64`
402    ///   - `Value::BigInteger`, `Value::BigDecimal`
403    /// - `String`
404    ///   - `Value::String`
405    ///   - `Value::Bool`, `Value::Char`
406    ///   - all integer and floating-point variants
407    ///   - `Value::Date`, `Value::Time`, `Value::DateTime`, `Value::Instant`
408    ///   - `Value::BigInteger`, `Value::BigDecimal`
409    ///   - `Value::IntSize`, `Value::UIntSize`
410    ///   - `Value::Duration`, formatted as `<nanoseconds>ns`
411    ///   - `Value::Url`
412    ///   - `Value::StringMap`, serialized as JSON text
413    ///   - `Value::Json`, serialized as JSON text
414    /// - `NaiveDate`
415    ///   - `Value::Date`
416    /// - `NaiveTime`
417    ///   - `Value::Time`
418    /// - `NaiveDateTime`
419    ///   - `Value::DateTime`
420    /// - `DateTime<Utc>`
421    ///   - `Value::Instant`
422    /// - `BigInt`
423    ///   - `Value::BigInteger`
424    /// - `BigDecimal`
425    ///   - `Value::BigDecimal`
426    /// - `isize`
427    ///   - `Value::IntSize`
428    ///   - `Value::Bool`
429    ///   - `Value::Char`
430    ///   - all integer variants
431    ///   - `Value::Float32`, `Value::Float64`
432    ///   - `Value::String`, parsed as `isize`
433    ///   - `Value::BigInteger`, `Value::BigDecimal`
434    /// - `usize`
435    ///   - `Value::UIntSize`
436    ///   - `Value::Bool`
437    ///   - `Value::Char`
438    ///   - all integer variants
439    ///   - `Value::String`, parsed as `usize`
440    /// - `Duration`
441    ///   - `Value::Duration`
442    ///   - `Value::String`, parsed from `<nanoseconds>ns`
443    /// - `Url`
444    ///   - `Value::Url`
445    ///   - `Value::String`, parsed as URL text
446    /// - `HashMap<String, String>`
447    ///   - `Value::StringMap`
448    /// - `serde_json::Value`
449    ///   - `Value::Json`
450    ///   - `Value::String`, parsed as JSON text
451    ///   - `Value::StringMap`, converted to a JSON object
452    ///
453    /// Any target type not listed above is not supported by `Value::to<T>()`.
454    ///
455    /// # Type Parameters
456    ///
457    /// * `T` - The target type to convert to
458    ///
459    /// # Returns
460    ///
461    /// Returns the converted value on success, or an error if conversion is not
462    /// supported or fails.
463    ///
464    /// # Example
465    ///
466    /// ```rust
467    /// use qubit_value::Value;
468    ///
469    /// let value = Value::Int32(42);
470    ///
471    /// let num: i64 = value.to().unwrap();
472    /// assert_eq!(num, 42);
473    ///
474    /// let text: String = value.to().unwrap();
475    /// assert_eq!(text, "42");
476    /// ```
477    #[inline]
478    pub fn to<T>(&self) -> ValueResult<T>
479    where
480        Self: ValueConverter<T>,
481    {
482        <Self as ValueConverter<T>>::convert(self)
483    }
484
485    /// Generic setter method
486    ///
487    /// Automatically selects the correct setter method based on the target
488    /// type and replaces the current value.
489    ///
490    /// This operation updates the stored type to `T` when needed. It does not
491    /// perform runtime type-mismatch validation against the previous variant.
492    ///
493    /// # Supported Generic Types
494    ///
495    /// `Value::set<T>(value)` currently supports the following `T`:
496    ///
497    /// - `bool`
498    /// - `char`
499    /// - `i8`, `i16`, `i32`, `i64`, `i128`
500    /// - `u8`, `u16`, `u32`, `u64`, `u128`
501    /// - `f32`, `f64`
502    /// - `String`, `&str`
503    /// - `NaiveDate`, `NaiveTime`, `NaiveDateTime`, `DateTime<Utc>`
504    /// - `BigInt`, `BigDecimal`
505    /// - `isize`, `usize`
506    /// - `Duration`
507    /// - `Url`
508    /// - `HashMap<String, String>`
509    /// - `serde_json::Value`
510    ///
511    /// # Type Parameters
512    ///
513    /// * `T` - The target type to set
514    ///
515    /// # Parameters
516    ///
517    /// * `value` - The value to set
518    ///
519    /// # Returns
520    ///
521    /// If setting succeeds, returns `Ok(())`; otherwise returns an error
522    ///
523    /// # Example
524    ///
525    /// ```rust
526    /// use qubit_common::lang::DataType;
527    /// use qubit_value::Value;
528    ///
529    /// let mut value = Value::Empty(DataType::Int32);
530    ///
531    /// // Through type inference
532    /// value.set(42i32).unwrap();
533    /// assert_eq!(value.get_int32().unwrap(), 42);
534    ///
535    /// // Explicitly specify type parameter
536    /// value.set::<i32>(100).unwrap();
537    /// assert_eq!(value.get_int32().unwrap(), 100);
538    ///
539    /// // String type
540    /// let mut text = Value::Empty(DataType::String);
541    /// text.set("hello".to_string()).unwrap();
542    /// assert_eq!(text.get_string().unwrap(), "hello");
543    /// ```
544    #[inline]
545    pub fn set<T>(&mut self, value: T) -> ValueResult<()>
546    where
547        Self: ValueSetter<T>,
548    {
549        <Self as ValueSetter<T>>::set_value(self, value)
550    }
551
552    /// Get the data type of the value
553    ///
554    /// # Returns
555    ///
556    /// Returns the data type corresponding to this value
557    ///
558    /// # Example
559    ///
560    /// ```rust
561    /// use qubit_common::lang::DataType;
562    /// use qubit_value::Value;
563    ///
564    /// let value = Value::Int32(42);
565    /// assert_eq!(value.data_type(), DataType::Int32);
566    ///
567    /// let empty = Value::Empty(DataType::String);
568    /// assert_eq!(empty.data_type(), DataType::String);
569    /// ```
570    #[inline]
571    pub fn data_type(&self) -> DataType {
572        match self {
573            Value::Empty(dt) => *dt,
574            Value::Bool(_) => DataType::Bool,
575            Value::Char(_) => DataType::Char,
576            Value::Int8(_) => DataType::Int8,
577            Value::Int16(_) => DataType::Int16,
578            Value::Int32(_) => DataType::Int32,
579            Value::Int64(_) => DataType::Int64,
580            Value::Int128(_) => DataType::Int128,
581            Value::UInt8(_) => DataType::UInt8,
582            Value::UInt16(_) => DataType::UInt16,
583            Value::UInt32(_) => DataType::UInt32,
584            Value::UInt64(_) => DataType::UInt64,
585            Value::UInt128(_) => DataType::UInt128,
586            Value::Float32(_) => DataType::Float32,
587            Value::Float64(_) => DataType::Float64,
588            Value::String(_) => DataType::String,
589            Value::Date(_) => DataType::Date,
590            Value::Time(_) => DataType::Time,
591            Value::DateTime(_) => DataType::DateTime,
592            Value::Instant(_) => DataType::Instant,
593            Value::BigInteger(_) => DataType::BigInteger,
594            Value::BigDecimal(_) => DataType::BigDecimal,
595            Value::IntSize(_) => DataType::IntSize,
596            Value::UIntSize(_) => DataType::UIntSize,
597            Value::Duration(_) => DataType::Duration,
598            Value::Url(_) => DataType::Url,
599            Value::StringMap(_) => DataType::StringMap,
600            Value::Json(_) => DataType::Json,
601        }
602    }
603
604    /// Check if the value is empty
605    ///
606    /// # Returns
607    ///
608    /// Returns `true` if the value is empty
609    ///
610    /// # Example
611    ///
612    /// ```rust
613    /// use qubit_common::lang::DataType;
614    /// use qubit_value::Value;
615    ///
616    /// let value = Value::Int32(42);
617    /// assert!(!value.is_empty());
618    ///
619    /// let empty = Value::Empty(DataType::String);
620    /// assert!(empty.is_empty());
621    /// ```
622    #[inline]
623    pub fn is_empty(&self) -> bool {
624        matches!(self, Value::Empty(_))
625    }
626
627    /// Clear the value while preserving the type
628    ///
629    /// Sets the current value to empty but retains its data type.
630    ///
631    /// # Example
632    ///
633    /// ```rust
634    /// use qubit_common::lang::DataType;
635    /// use qubit_value::Value;
636    ///
637    /// let mut value = Value::Int32(42);
638    /// value.clear();
639    /// assert!(value.is_empty());
640    /// assert_eq!(value.data_type(), DataType::Int32);
641    /// ```
642    #[inline]
643    pub fn clear(&mut self) {
644        let dt = self.data_type();
645        *self = Value::Empty(dt);
646    }
647
648    /// Set the data type
649    ///
650    /// If the new type differs from the current type, clears the value
651    /// and sets the new type.
652    ///
653    /// # Parameters
654    ///
655    /// * `data_type` - The data type to set
656    ///
657    /// # Example
658    ///
659    /// ```rust
660    /// use qubit_common::lang::DataType;
661    /// use qubit_value::Value;
662    ///
663    /// let mut value = Value::Int32(42);
664    /// value.set_type(DataType::String);
665    /// assert!(value.is_empty());
666    /// assert_eq!(value.data_type(), DataType::String);
667    /// ```
668    #[inline]
669    pub fn set_type(&mut self, data_type: DataType) {
670        if self.data_type() != data_type {
671            *self = Value::Empty(data_type);
672        }
673    }
674}
675
676impl Default for Value {
677    #[inline]
678    fn default() -> Self {
679        Value::Empty(DataType::String)
680    }
681}