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}