Skip to main content

qubit_value/value/
value.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//! # Single Value Container
11//!
12//! Provides type-safe storage and access functionality for single values.
13//!
14
15use bigdecimal::BigDecimal;
16use chrono::{
17    DateTime,
18    NaiveDate,
19    NaiveDateTime,
20    NaiveTime,
21    Utc,
22};
23use num_bigint::BigInt;
24use serde::{
25    Deserialize,
26    Serialize,
27};
28use std::collections::HashMap;
29use std::time::Duration;
30use url::Url;
31
32use qubit_datatype::{
33    DataConversionOptions,
34    DataConvertTo,
35    DataConverter,
36    DataType,
37};
38
39use crate::value_error::ValueResult;
40use crate::{
41    IntoValueDefault,
42    ValueError,
43};
44
45/// Single value container
46///
47/// Uses an enum to represent different types of values, providing
48/// type-safe value storage and access.
49///
50/// # Features
51///
52/// - Zero-cost abstraction with compile-time type checking
53/// - Supports multiple basic data types
54/// - Provides two sets of APIs for type checking and type conversion
55/// - Automatic memory management
56///
57/// # Example
58///
59/// ```rust
60/// use qubit_value::Value;
61///
62/// // Create an integer value
63/// let value = Value::Int32(42);
64/// assert_eq!(value.get_int32().unwrap(), 42);
65///
66/// // Type conversion
67/// let converted = value.to::<i64>().unwrap();
68/// assert_eq!(converted, 42i64);
69///
70/// // String value
71/// let text = Value::String("hello".to_string());
72/// assert_eq!(text.get_string().unwrap(), "hello");
73/// ```
74///
75///
76#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
77pub enum Value {
78    /// Empty value (has type but no value)
79    Empty(DataType),
80    /// Boolean value
81    Bool(bool),
82    /// Character value
83    Char(char),
84    /// 8-bit signed integer
85    Int8(i8),
86    /// 16-bit signed integer
87    Int16(i16),
88    /// 32-bit signed integer
89    Int32(i32),
90    /// 64-bit signed integer
91    Int64(i64),
92    /// 128-bit signed integer
93    Int128(i128),
94    /// 8-bit unsigned integer
95    UInt8(u8),
96    /// 16-bit unsigned integer
97    UInt16(u16),
98    /// 32-bit unsigned integer
99    UInt32(u32),
100    /// 64-bit unsigned integer
101    UInt64(u64),
102    /// 128-bit unsigned integer
103    UInt128(u128),
104    /// Platform-dependent signed integer (isize)
105    IntSize(isize),
106    /// Platform-dependent unsigned integer (usize)
107    UIntSize(usize),
108    /// 32-bit floating point number
109    Float32(f32),
110    /// 64-bit floating point number
111    Float64(f64),
112    /// Big integer type
113    BigInteger(BigInt),
114    /// Big decimal type
115    BigDecimal(BigDecimal),
116    /// String
117    String(String),
118    /// Date
119    Date(NaiveDate),
120    /// Time
121    Time(NaiveTime),
122    /// Date and time
123    DateTime(NaiveDateTime),
124    /// UTC instant
125    Instant(DateTime<Utc>),
126    /// Duration type (std::time::Duration)
127    Duration(Duration),
128    /// URL type (url::Url)
129    Url(Url),
130    /// String map type (HashMap<String, String>)
131    StringMap(HashMap<String, String>),
132    /// JSON value type (serde_json::Value)
133    Json(serde_json::Value),
134}
135
136// ============================================================================
137// Getter method generation macro
138// ============================================================================
139
140/// Unified getter generation macro
141///
142/// Supports two modes:
143/// 1. `copy:` - For types implementing the Copy trait, directly returns the value
144/// 2. `ref:` - For non-Copy types, returns a reference
145///
146/// # Documentation Comment Support
147///
148/// The macro automatically extracts preceding documentation comments, so
149/// you can add `///` comments before macro invocations.
150///
151///
152impl Value {
153    /// Generic constructor method
154    ///
155    /// Creates a `Value` from any supported type, avoiding direct use of
156    /// enum variants.
157    ///
158    /// # Supported Generic Types
159    ///
160    /// `Value::new<T>(value)` currently supports the following `T`:
161    ///
162    /// - `bool`
163    /// - `char`
164    /// - `i8`, `i16`, `i32`, `i64`, `i128`
165    /// - `u8`, `u16`, `u32`, `u64`, `u128`
166    /// - `f32`, `f64`
167    /// - `String`, `&str`
168    /// - `NaiveDate`, `NaiveTime`, `NaiveDateTime`, `DateTime<Utc>`
169    /// - `BigInt`, `BigDecimal`
170    /// - `isize`, `usize`
171    /// - `Duration`
172    /// - `Url`
173    /// - `HashMap<String, String>`
174    /// - `serde_json::Value`
175    ///
176    /// # Type Parameters
177    ///
178    /// * `T` - The type of the value to wrap
179    ///
180    /// # Returns
181    ///
182    /// Returns a `Value` wrapping the given value
183    ///
184    /// # Example
185    ///
186    /// ```rust
187    /// use qubit_value::Value;
188    ///
189    /// // Basic types
190    /// let v = Value::new(42i32);
191    /// assert_eq!(v.get_int32().unwrap(), 42);
192    ///
193    /// let v = Value::new(true);
194    /// assert_eq!(v.get_bool().unwrap(), true);
195    ///
196    /// // String
197    /// let v = Value::new("hello".to_string());
198    /// assert_eq!(v.get_string().unwrap(), "hello");
199    /// ```
200    #[inline]
201    pub fn new<T>(value: T) -> Self
202    where
203        T: Into<Self>,
204    {
205        value.into()
206    }
207
208    /// Generic getter method.
209    ///
210    /// Performs a strict typed read of the stored value as `T`.
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    /// Returns the stored value when its type matches `T`.
243    ///
244    /// # Errors
245    ///
246    /// Returns [`ValueError::NoValue`] when the value is empty with the
247    /// requested type, or [`ValueError::TypeMismatch`] when the stored type
248    /// differs from `T`.
249    ///
250    /// # Example
251    ///
252    /// ```rust
253    /// use qubit_value::Value;
254    ///
255    /// let value = Value::Int32(42);
256    ///
257    /// // Through type inference
258    /// let num: i32 = value.get().unwrap();
259    /// assert_eq!(num, 42);
260    ///
261    /// // Explicitly specify type parameter
262    /// let num = value.get::<i32>().unwrap();
263    /// assert_eq!(num, 42);
264    ///
265    /// // Different type
266    /// let text = Value::String("hello".to_string());
267    /// let s: String = text.get().unwrap();
268    /// assert_eq!(s, "hello");
269    ///
270    /// // Boolean value
271    /// let flag = Value::Bool(true);
272    /// let b: bool = flag.get().unwrap();
273    /// assert_eq!(b, true);
274    /// ```
275    #[inline]
276    pub fn get<T>(&self) -> ValueResult<T>
277    where
278        for<'a> T: TryFrom<&'a Self, Error = ValueError>,
279    {
280        T::try_from(self)
281    }
282
283    /// Generic getter method with a default value.
284    ///
285    /// Returns the supplied default only when this value is empty. Type
286    /// mismatches and conversion errors are still returned as errors.
287    #[inline]
288    pub fn get_or<T>(&self, default: impl IntoValueDefault<T>) -> ValueResult<T>
289    where
290        for<'a> T: TryFrom<&'a Self, Error = ValueError>,
291    {
292        match self.get() {
293            Err(ValueError::NoValue) => Ok(default.into_value_default()),
294            result => result,
295        }
296    }
297
298    /// Generic conversion method
299    ///
300    /// Converts the current value to the target type according to the shared
301    /// value conversion rules.
302    ///
303    /// # Supported Target Types And Source Variants
304    ///
305    /// `Value::to<T>()` currently supports the following target types:
306    ///
307    /// - `bool`
308    ///   - `Value::Bool`
309    ///   - `Value::Int8`, `Value::Int16`, `Value::Int32`, `Value::Int64`,
310    ///     `Value::Int128`
311    ///   - `Value::UInt8`, `Value::UInt16`, `Value::UInt32`,
312    ///     `Value::UInt64`, `Value::UInt128`
313    ///   - `Value::String`, parsed as `1`, `0`, or ASCII case-insensitive
314    ///     `true` / `false`
315    /// - `char`
316    ///   - `Value::Char`
317    /// - `i8`
318    ///   - `Value::Int8`
319    ///   - `Value::Bool`
320    ///   - `Value::Char`
321    ///   - all integer variants
322    ///   - `Value::Float32`, `Value::Float64`
323    ///   - `Value::String`, parsed as `i8`
324    ///   - `Value::BigInteger`, `Value::BigDecimal`
325    /// - `i16`
326    ///   - `Value::Int16`
327    ///   - `Value::Bool`
328    ///   - `Value::Char`
329    ///   - all integer variants
330    ///   - `Value::Float32`, `Value::Float64`
331    ///   - `Value::String`, parsed as `i16`
332    ///   - `Value::BigInteger`, `Value::BigDecimal`
333    /// - `i32`
334    ///   - `Value::Int32`
335    ///   - `Value::Bool`
336    ///   - `Value::Char`
337    ///   - `Value::Int8`, `Value::Int16`, `Value::Int64`, `Value::Int128`
338    ///   - `Value::UInt8`, `Value::UInt16`, `Value::UInt32`,
339    ///     `Value::UInt64`, `Value::UInt128`
340    ///   - `Value::Float32`, `Value::Float64`
341    ///   - `Value::String`, parsed as `i32`
342    ///   - `Value::BigInteger`, `Value::BigDecimal`
343    /// - `i64`
344    ///   - `Value::Int64`
345    ///   - `Value::Bool`
346    ///   - `Value::Char`
347    ///   - `Value::Int8`, `Value::Int16`, `Value::Int32`, `Value::Int128`
348    ///   - `Value::UInt8`, `Value::UInt16`, `Value::UInt32`,
349    ///     `Value::UInt64`, `Value::UInt128`
350    ///   - `Value::Float32`, `Value::Float64`
351    ///   - `Value::String`, parsed as `i64`
352    ///   - `Value::BigInteger`, `Value::BigDecimal`
353    /// - `i128`
354    ///   - `Value::Int128`
355    ///   - `Value::Bool`
356    ///   - `Value::Char`
357    ///   - all integer variants
358    ///   - `Value::Float32`, `Value::Float64`
359    ///   - `Value::String`, parsed as `i128`
360    ///   - `Value::BigInteger`, `Value::BigDecimal`
361    /// - `u8`
362    ///   - `Value::UInt8`
363    ///   - `Value::Bool`
364    ///   - `Value::Char`
365    ///   - `Value::Int8`, `Value::Int16`, `Value::Int32`, `Value::Int64`,
366    ///     `Value::Int128`
367    ///   - `Value::UInt16`, `Value::UInt32`, `Value::UInt64`,
368    ///     `Value::UInt128`
369    ///   - `Value::String`, parsed as `u8`
370    /// - `u16`
371    ///   - `Value::UInt8`, `Value::UInt16`, `Value::UInt32`,
372    ///     `Value::UInt64`, `Value::UInt128`
373    ///   - `Value::Bool`
374    ///   - `Value::Char`
375    ///   - `Value::Int8`, `Value::Int16`, `Value::Int32`, `Value::Int64`,
376    ///     `Value::Int128`
377    ///   - `Value::String`, parsed as `u16`
378    /// - `u32`
379    ///   - `Value::UInt8`, `Value::UInt16`, `Value::UInt32`,
380    ///     `Value::UInt64`, `Value::UInt128`
381    ///   - `Value::Bool`
382    ///   - `Value::Char`
383    ///   - `Value::Int8`, `Value::Int16`, `Value::Int32`, `Value::Int64`,
384    ///     `Value::Int128`
385    ///   - `Value::String`, parsed as `u32`
386    /// - `u64`
387    ///   - `Value::UInt8`, `Value::UInt16`, `Value::UInt32`,
388    ///     `Value::UInt64`, `Value::UInt128`
389    ///   - `Value::Bool`
390    ///   - `Value::Char`
391    ///   - `Value::Int8`, `Value::Int16`, `Value::Int32`, `Value::Int64`,
392    ///     `Value::Int128`
393    ///   - `Value::String`, parsed as `u64`
394    /// - `u128`
395    ///   - `Value::UInt8`, `Value::UInt16`, `Value::UInt32`,
396    ///     `Value::UInt64`, `Value::UInt128`
397    ///   - `Value::Bool`
398    ///   - `Value::Char`
399    ///   - `Value::Int8`, `Value::Int16`, `Value::Int32`, `Value::Int64`,
400    ///     `Value::Int128`
401    ///   - `Value::String`, parsed as `u128`
402    /// - `f32`
403    ///   - `Value::Float32`, `Value::Float64`
404    ///   - `Value::Bool`
405    ///   - `Value::Char`
406    ///   - `Value::Int8`, `Value::Int16`, `Value::Int32`, `Value::Int64`,
407    ///     `Value::Int128`
408    ///   - `Value::UInt8`, `Value::UInt16`, `Value::UInt32`,
409    ///     `Value::UInt64`, `Value::UInt128`
410    ///   - `Value::String`, parsed as `f32`
411    ///   - `Value::BigInteger`, `Value::BigDecimal`
412    /// - `f64`
413    ///   - `Value::Float64`
414    ///   - `Value::Bool`
415    ///   - `Value::Char`
416    ///   - `Value::Int8`, `Value::Int16`, `Value::Int32`, `Value::Int64`,
417    ///     `Value::Int128`
418    ///   - `Value::UInt8`, `Value::UInt16`, `Value::UInt32`,
419    ///     `Value::UInt64`, `Value::UInt128`
420    ///   - `Value::Float32`
421    ///   - `Value::String`, parsed as `f64`
422    ///   - `Value::BigInteger`, `Value::BigDecimal`
423    /// - `String`
424    ///   - `Value::String`
425    ///   - `Value::Bool`, `Value::Char`
426    ///   - all integer and floating-point variants
427    ///   - `Value::Date`, `Value::Time`, `Value::DateTime`, `Value::Instant`
428    ///   - `Value::BigInteger`, `Value::BigDecimal`
429    ///   - `Value::IntSize`, `Value::UIntSize`
430    ///   - `Value::Duration`, formatted with the configured duration unit.
431    ///     The default conversion options use milliseconds and append the
432    ///     unit suffix, for example `1500ms`.
433    ///   - `Value::Url`
434    ///   - `Value::StringMap`, serialized as JSON text
435    ///   - `Value::Json`, serialized as JSON text
436    /// - `NaiveDate`
437    ///   - `Value::Date`
438    /// - `NaiveTime`
439    ///   - `Value::Time`
440    /// - `NaiveDateTime`
441    ///   - `Value::DateTime`
442    /// - `DateTime<Utc>`
443    ///   - `Value::Instant`
444    /// - `BigInt`
445    ///   - `Value::BigInteger`
446    /// - `BigDecimal`
447    ///   - `Value::BigDecimal`
448    /// - `isize`
449    ///   - `Value::IntSize`
450    ///   - `Value::Bool`
451    ///   - `Value::Char`
452    ///   - all integer variants
453    ///   - `Value::Float32`, `Value::Float64`
454    ///   - `Value::String`, parsed as `isize`
455    ///   - `Value::BigInteger`, `Value::BigDecimal`
456    /// - `usize`
457    ///   - `Value::UIntSize`
458    ///   - `Value::Bool`
459    ///   - `Value::Char`
460    ///   - all integer variants
461    ///   - `Value::String`, parsed as `usize`
462    /// - `Duration`
463    ///   - `Value::Duration`
464    ///   - integer variants and `Value::BigInteger`, interpreted in the
465    ///     configured duration unit
466    ///   - `Value::String`, parsed as duration text. Explicit suffixes
467    ///     `ns`, `us`, `ms`, `s`, `m`, `h`, and `d` are supported; text
468    ///     without a suffix uses the configured duration unit.
469    /// - `Url`
470    ///   - `Value::Url`
471    ///   - `Value::String`, parsed as URL text
472    /// - `HashMap<String, String>`
473    ///   - `Value::StringMap`
474    /// - `serde_json::Value`
475    ///   - `Value::Json`
476    ///   - `Value::String`, parsed as JSON text
477    ///   - `Value::StringMap`, converted to a JSON object
478    ///
479    /// Any target type not listed above is not supported by `Value::to<T>()`.
480    ///
481    /// # Type Parameters
482    ///
483    /// * `T` - The target type to convert to
484    ///
485    /// # Returns
486    ///
487    /// Returns the converted value on success, or an error if conversion is not
488    /// supported or fails.
489    ///
490    /// # Example
491    ///
492    /// ```rust
493    /// use qubit_value::Value;
494    ///
495    /// let value = Value::Int32(42);
496    ///
497    /// let num: i64 = value.to().unwrap();
498    /// assert_eq!(num, 42);
499    ///
500    /// let text: String = value.to().unwrap();
501    /// assert_eq!(text, "42");
502    /// ```
503    #[inline]
504    pub fn to<T>(&self) -> ValueResult<T>
505    where
506        for<'a> DataConverter<'a>: DataConvertTo<T>,
507    {
508        self.to_with(&DataConversionOptions::default())
509    }
510
511    /// Converts this value to `T`, or returns `default` when it is empty.
512    ///
513    /// Conversion failures from non-empty values are preserved.
514    #[inline]
515    pub fn to_or<T>(&self, default: impl IntoValueDefault<T>) -> ValueResult<T>
516    where
517        for<'a> DataConverter<'a>: DataConvertTo<T>,
518    {
519        match self.to() {
520            Err(ValueError::NoValue) => Ok(default.into_value_default()),
521            result => result,
522        }
523    }
524
525    /// Converts this value to `T` using the provided conversion options.
526    ///
527    /// This method uses the shared [`qubit_datatype`] conversion layer directly,
528    /// so options such as string trimming, blank string handling, and boolean
529    /// aliases are applied consistently with other value containers.
530    ///
531    /// # Type Parameters
532    ///
533    /// * `T` - The target type to convert to.
534    ///
535    /// # Parameters
536    ///
537    /// * `options` - Conversion options forwarded to the shared converter.
538    ///
539    /// # Returns
540    ///
541    /// Returns the converted value on success.
542    ///
543    /// # Errors
544    ///
545    /// Returns a [`crate::ValueError`] when the value is missing, unsupported, or
546    /// invalid for `T` under the provided options.
547    #[inline]
548    pub fn to_with<T>(&self, options: &DataConversionOptions) -> ValueResult<T>
549    where
550        for<'a> DataConverter<'a>: DataConvertTo<T>,
551    {
552        super::value_converters::convert_with_data_converter_with(self, options)
553    }
554
555    /// Converts this value to `T` using conversion options, or returns
556    /// `default` when it is empty.
557    ///
558    /// Conversion failures from non-empty values are preserved.
559    #[inline]
560    pub fn to_or_with<T>(
561        &self,
562        default: impl IntoValueDefault<T>,
563        options: &DataConversionOptions,
564    ) -> ValueResult<T>
565    where
566        for<'a> DataConverter<'a>: DataConvertTo<T>,
567    {
568        match self.to_with(options) {
569            Err(ValueError::NoValue) => Ok(default.into_value_default()),
570            result => result,
571        }
572    }
573
574    /// Generic setter method
575    ///
576    /// Replaces the current value with any supported input value.
577    ///
578    /// This operation updates the stored type to `T` when needed. It does not
579    /// perform runtime type-mismatch validation against the previous variant.
580    ///
581    /// # Supported Generic Types
582    ///
583    /// `Value::set<T>(value)` currently supports the following `T`:
584    ///
585    /// - `bool`
586    /// - `char`
587    /// - `i8`, `i16`, `i32`, `i64`, `i128`
588    /// - `u8`, `u16`, `u32`, `u64`, `u128`
589    /// - `f32`, `f64`
590    /// - `String`, `&str`
591    /// - `NaiveDate`, `NaiveTime`, `NaiveDateTime`, `DateTime<Utc>`
592    /// - `BigInt`, `BigDecimal`
593    /// - `isize`, `usize`
594    /// - `Duration`
595    /// - `Url`
596    /// - `HashMap<String, String>`
597    /// - `serde_json::Value`
598    ///
599    /// # Type Parameters
600    ///
601    /// * `T` - Input type convertible into [`Value`].
602    ///
603    /// # Parameters
604    ///
605    /// * `value` - The value to set
606    ///
607    /// # Returns
608    ///
609    /// Always returns `Ok(())` for supported input types. Unsupported input
610    /// types fail to compile because they do not implement `Into<Value>`.
611    ///
612    /// # Example
613    ///
614    /// ```rust
615    /// use qubit_datatype::DataType;
616    /// use qubit_value::Value;
617    ///
618    /// let mut value = Value::Empty(DataType::Int32);
619    ///
620    /// // Through type inference
621    /// value.set(42i32).unwrap();
622    /// assert_eq!(value.get_int32().unwrap(), 42);
623    ///
624    /// // Explicitly specify type parameter
625    /// value.set::<i32>(100).unwrap();
626    /// assert_eq!(value.get_int32().unwrap(), 100);
627    ///
628    /// // String type
629    /// let mut text = Value::Empty(DataType::String);
630    /// text.set("hello".to_string()).unwrap();
631    /// assert_eq!(text.get_string().unwrap(), "hello");
632    /// ```
633    #[inline]
634    pub fn set<T>(&mut self, value: T) -> ValueResult<()>
635    where
636        T: Into<Self>,
637    {
638        *self = value.into();
639        Ok(())
640    }
641
642    /// Get the data type of the value
643    ///
644    /// # Returns
645    ///
646    /// Returns the data type corresponding to this value
647    ///
648    /// # Example
649    ///
650    /// ```rust
651    /// use qubit_datatype::DataType;
652    /// use qubit_value::Value;
653    ///
654    /// let value = Value::Int32(42);
655    /// assert_eq!(value.data_type(), DataType::Int32);
656    ///
657    /// let empty = Value::Empty(DataType::String);
658    /// assert_eq!(empty.data_type(), DataType::String);
659    /// ```
660    #[inline]
661    pub fn data_type(&self) -> DataType {
662        match self {
663            Value::Empty(dt) => *dt,
664            Value::Bool(_) => DataType::Bool,
665            Value::Char(_) => DataType::Char,
666            Value::Int8(_) => DataType::Int8,
667            Value::Int16(_) => DataType::Int16,
668            Value::Int32(_) => DataType::Int32,
669            Value::Int64(_) => DataType::Int64,
670            Value::Int128(_) => DataType::Int128,
671            Value::UInt8(_) => DataType::UInt8,
672            Value::UInt16(_) => DataType::UInt16,
673            Value::UInt32(_) => DataType::UInt32,
674            Value::UInt64(_) => DataType::UInt64,
675            Value::UInt128(_) => DataType::UInt128,
676            Value::Float32(_) => DataType::Float32,
677            Value::Float64(_) => DataType::Float64,
678            Value::String(_) => DataType::String,
679            Value::Date(_) => DataType::Date,
680            Value::Time(_) => DataType::Time,
681            Value::DateTime(_) => DataType::DateTime,
682            Value::Instant(_) => DataType::Instant,
683            Value::BigInteger(_) => DataType::BigInteger,
684            Value::BigDecimal(_) => DataType::BigDecimal,
685            Value::IntSize(_) => DataType::IntSize,
686            Value::UIntSize(_) => DataType::UIntSize,
687            Value::Duration(_) => DataType::Duration,
688            Value::Url(_) => DataType::Url,
689            Value::StringMap(_) => DataType::StringMap,
690            Value::Json(_) => DataType::Json,
691        }
692    }
693
694    /// Check if the value is empty
695    ///
696    /// # Returns
697    ///
698    /// Returns `true` if the value is empty
699    ///
700    /// # Example
701    ///
702    /// ```rust
703    /// use qubit_datatype::DataType;
704    /// use qubit_value::Value;
705    ///
706    /// let value = Value::Int32(42);
707    /// assert!(!value.is_empty());
708    ///
709    /// let empty = Value::Empty(DataType::String);
710    /// assert!(empty.is_empty());
711    /// ```
712    #[inline]
713    pub fn is_empty(&self) -> bool {
714        matches!(self, Value::Empty(_))
715    }
716
717    /// Clear the value while preserving the type
718    ///
719    /// Sets the current value to empty but retains its data type.
720    ///
721    /// # Example
722    ///
723    /// ```rust
724    /// use qubit_datatype::DataType;
725    /// use qubit_value::Value;
726    ///
727    /// let mut value = Value::Int32(42);
728    /// value.clear();
729    /// assert!(value.is_empty());
730    /// assert_eq!(value.data_type(), DataType::Int32);
731    /// ```
732    #[inline]
733    pub fn clear(&mut self) {
734        let dt = self.data_type();
735        *self = Value::Empty(dt);
736    }
737
738    /// Set the data type
739    ///
740    /// If the new type differs from the current type, clears the value
741    /// and sets the new type.
742    ///
743    /// # Parameters
744    ///
745    /// * `data_type` - The data type to set
746    ///
747    /// # Example
748    ///
749    /// ```rust
750    /// use qubit_datatype::DataType;
751    /// use qubit_value::Value;
752    ///
753    /// let mut value = Value::Int32(42);
754    /// value.set_type(DataType::String);
755    /// assert!(value.is_empty());
756    /// assert_eq!(value.data_type(), DataType::String);
757    /// ```
758    #[inline]
759    pub fn set_type(&mut self, data_type: DataType) {
760        if self.data_type() != data_type {
761            *self = Value::Empty(data_type);
762        }
763    }
764}
765
766impl Default for Value {
767    #[inline]
768    fn default() -> Self {
769        Value::Empty(DataType::String)
770    }
771}