Skip to main content

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