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 `bool`
294 /// - `char`
295 /// - `Value::Char`
296 /// - `i8`
297 /// - `Value::Int8`
298 /// - `Value::Bool`
299 /// - `Value::Char`
300 /// - all integer variants
301 /// - `Value::Float32`, `Value::Float64`
302 /// - `Value::String`, parsed as `i8`
303 /// - `Value::BigInteger`, `Value::BigDecimal`
304 /// - `i16`
305 /// - `Value::Int16`
306 /// - `Value::Bool`
307 /// - `Value::Char`
308 /// - all integer variants
309 /// - `Value::Float32`, `Value::Float64`
310 /// - `Value::String`, parsed as `i16`
311 /// - `Value::BigInteger`, `Value::BigDecimal`
312 /// - `i32`
313 /// - `Value::Int32`
314 /// - `Value::Bool`
315 /// - `Value::Char`
316 /// - `Value::Int8`, `Value::Int16`, `Value::Int64`, `Value::Int128`
317 /// - `Value::UInt8`, `Value::UInt16`, `Value::UInt32`,
318 /// `Value::UInt64`, `Value::UInt128`
319 /// - `Value::Float32`, `Value::Float64`
320 /// - `Value::String`, parsed as `i32`
321 /// - `Value::BigInteger`, `Value::BigDecimal`
322 /// - `i64`
323 /// - `Value::Int64`
324 /// - `Value::Bool`
325 /// - `Value::Char`
326 /// - `Value::Int8`, `Value::Int16`, `Value::Int32`, `Value::Int128`
327 /// - `Value::UInt8`, `Value::UInt16`, `Value::UInt32`,
328 /// `Value::UInt64`, `Value::UInt128`
329 /// - `Value::Float32`, `Value::Float64`
330 /// - `Value::String`, parsed as `i64`
331 /// - `Value::BigInteger`, `Value::BigDecimal`
332 /// - `i128`
333 /// - `Value::Int128`
334 /// - `Value::Bool`
335 /// - `Value::Char`
336 /// - all integer variants
337 /// - `Value::Float32`, `Value::Float64`
338 /// - `Value::String`, parsed as `i128`
339 /// - `Value::BigInteger`, `Value::BigDecimal`
340 /// - `u8`
341 /// - `Value::UInt8`
342 /// - `Value::Bool`
343 /// - `Value::Char`
344 /// - `Value::Int8`, `Value::Int16`, `Value::Int32`, `Value::Int64`,
345 /// `Value::Int128`
346 /// - `Value::UInt16`, `Value::UInt32`, `Value::UInt64`,
347 /// `Value::UInt128`
348 /// - `Value::String`, parsed as `u8`
349 /// - `u16`
350 /// - `Value::UInt8`, `Value::UInt16`, `Value::UInt32`,
351 /// `Value::UInt64`, `Value::UInt128`
352 /// - `Value::Bool`
353 /// - `Value::Char`
354 /// - `Value::Int8`, `Value::Int16`, `Value::Int32`, `Value::Int64`,
355 /// `Value::Int128`
356 /// - `Value::String`, parsed as `u16`
357 /// - `u32`
358 /// - `Value::UInt8`, `Value::UInt16`, `Value::UInt32`,
359 /// `Value::UInt64`, `Value::UInt128`
360 /// - `Value::Bool`
361 /// - `Value::Char`
362 /// - `Value::Int8`, `Value::Int16`, `Value::Int32`, `Value::Int64`,
363 /// `Value::Int128`
364 /// - `Value::String`, parsed as `u32`
365 /// - `u64`
366 /// - `Value::UInt8`, `Value::UInt16`, `Value::UInt32`,
367 /// `Value::UInt64`, `Value::UInt128`
368 /// - `Value::Bool`
369 /// - `Value::Char`
370 /// - `Value::Int8`, `Value::Int16`, `Value::Int32`, `Value::Int64`,
371 /// `Value::Int128`
372 /// - `Value::String`, parsed as `u64`
373 /// - `u128`
374 /// - `Value::UInt8`, `Value::UInt16`, `Value::UInt32`,
375 /// `Value::UInt64`, `Value::UInt128`
376 /// - `Value::Bool`
377 /// - `Value::Char`
378 /// - `Value::Int8`, `Value::Int16`, `Value::Int32`, `Value::Int64`,
379 /// `Value::Int128`
380 /// - `Value::String`, parsed as `u128`
381 /// - `f32`
382 /// - `Value::Float32`, `Value::Float64`
383 /// - `Value::Bool`
384 /// - `Value::Char`
385 /// - `Value::Int8`, `Value::Int16`, `Value::Int32`, `Value::Int64`,
386 /// `Value::Int128`
387 /// - `Value::UInt8`, `Value::UInt16`, `Value::UInt32`,
388 /// `Value::UInt64`, `Value::UInt128`
389 /// - `Value::String`, parsed as `f32`
390 /// - `Value::BigInteger`, `Value::BigDecimal`
391 /// - `f64`
392 /// - `Value::Float64`
393 /// - `Value::Bool`
394 /// - `Value::Char`
395 /// - `Value::Int8`, `Value::Int16`, `Value::Int32`, `Value::Int64`,
396 /// `Value::Int128`
397 /// - `Value::UInt8`, `Value::UInt16`, `Value::UInt32`,
398 /// `Value::UInt64`, `Value::UInt128`
399 /// - `Value::Float32`
400 /// - `Value::String`, parsed as `f64`
401 /// - `Value::BigInteger`, `Value::BigDecimal`
402 /// - `String`
403 /// - `Value::String`
404 /// - `Value::Bool`, `Value::Char`
405 /// - all integer and floating-point variants
406 /// - `Value::Date`, `Value::Time`, `Value::DateTime`, `Value::Instant`
407 /// - `Value::BigInteger`, `Value::BigDecimal`
408 /// - `Value::IntSize`, `Value::UIntSize`
409 /// - `Value::Duration`, formatted as `<nanoseconds>ns`
410 /// - `Value::Url`
411 /// - `Value::StringMap`, serialized as JSON text
412 /// - `Value::Json`, serialized as JSON text
413 /// - `NaiveDate`
414 /// - `Value::Date`
415 /// - `NaiveTime`
416 /// - `Value::Time`
417 /// - `NaiveDateTime`
418 /// - `Value::DateTime`
419 /// - `DateTime<Utc>`
420 /// - `Value::Instant`
421 /// - `BigInt`
422 /// - `Value::BigInteger`
423 /// - `BigDecimal`
424 /// - `Value::BigDecimal`
425 /// - `isize`
426 /// - `Value::IntSize`
427 /// - `Value::Bool`
428 /// - `Value::Char`
429 /// - all integer variants
430 /// - `Value::Float32`, `Value::Float64`
431 /// - `Value::String`, parsed as `isize`
432 /// - `Value::BigInteger`, `Value::BigDecimal`
433 /// - `usize`
434 /// - `Value::UIntSize`
435 /// - `Value::Bool`
436 /// - `Value::Char`
437 /// - all integer variants
438 /// - `Value::String`, parsed as `usize`
439 /// - `Duration`
440 /// - `Value::Duration`
441 /// - `Value::String`, parsed from `<nanoseconds>ns`
442 /// - `Url`
443 /// - `Value::Url`
444 /// - `Value::String`, parsed as URL text
445 /// - `HashMap<String, String>`
446 /// - `Value::StringMap`
447 /// - `serde_json::Value`
448 /// - `Value::Json`
449 /// - `Value::String`, parsed as JSON text
450 /// - `Value::StringMap`, converted to a JSON object
451 ///
452 /// Any target type not listed above is not supported by `Value::to<T>()`.
453 ///
454 /// # Type Parameters
455 ///
456 /// * `T` - The target type to convert to
457 ///
458 /// # Returns
459 ///
460 /// Returns the converted value on success, or an error if conversion is not
461 /// supported or fails.
462 ///
463 /// # Example
464 ///
465 /// ```rust
466 /// use qubit_value::Value;
467 ///
468 /// let value = Value::Int32(42);
469 ///
470 /// let num: i64 = value.to().unwrap();
471 /// assert_eq!(num, 42);
472 ///
473 /// let text: String = value.to().unwrap();
474 /// assert_eq!(text, "42");
475 /// ```
476 #[inline]
477 pub fn to<T>(&self) -> ValueResult<T>
478 where
479 Self: ValueConverter<T>,
480 {
481 <Self as ValueConverter<T>>::convert(self)
482 }
483
484 /// Generic setter method
485 ///
486 /// Automatically selects the correct setter method based on the target
487 /// type and replaces the current value.
488 ///
489 /// This operation updates the stored type to `T` when needed. It does not
490 /// perform runtime type-mismatch validation against the previous variant.
491 ///
492 /// # Supported Generic Types
493 ///
494 /// `Value::set<T>(value)` currently supports the following `T`:
495 ///
496 /// - `bool`
497 /// - `char`
498 /// - `i8`, `i16`, `i32`, `i64`, `i128`
499 /// - `u8`, `u16`, `u32`, `u64`, `u128`
500 /// - `f32`, `f64`
501 /// - `String`, `&str`
502 /// - `NaiveDate`, `NaiveTime`, `NaiveDateTime`, `DateTime<Utc>`
503 /// - `BigInt`, `BigDecimal`
504 /// - `isize`, `usize`
505 /// - `Duration`
506 /// - `Url`
507 /// - `HashMap<String, String>`
508 /// - `serde_json::Value`
509 ///
510 /// # Type Parameters
511 ///
512 /// * `T` - The target type to set
513 ///
514 /// # Parameters
515 ///
516 /// * `value` - The value to set
517 ///
518 /// # Returns
519 ///
520 /// If setting succeeds, returns `Ok(())`; otherwise returns an error
521 ///
522 /// # Example
523 ///
524 /// ```rust
525 /// use qubit_common::lang::DataType;
526 /// use qubit_value::Value;
527 ///
528 /// let mut value = Value::Empty(DataType::Int32);
529 ///
530 /// // Through type inference
531 /// value.set(42i32).unwrap();
532 /// assert_eq!(value.get_int32().unwrap(), 42);
533 ///
534 /// // Explicitly specify type parameter
535 /// value.set::<i32>(100).unwrap();
536 /// assert_eq!(value.get_int32().unwrap(), 100);
537 ///
538 /// // String type
539 /// let mut text = Value::Empty(DataType::String);
540 /// text.set("hello".to_string()).unwrap();
541 /// assert_eq!(text.get_string().unwrap(), "hello");
542 /// ```
543 #[inline]
544 pub fn set<T>(&mut self, value: T) -> ValueResult<()>
545 where
546 Self: ValueSetter<T>,
547 {
548 <Self as ValueSetter<T>>::set_value(self, value)
549 }
550
551 /// Get the data type of the value
552 ///
553 /// # Returns
554 ///
555 /// Returns the data type corresponding to this value
556 ///
557 /// # Example
558 ///
559 /// ```rust
560 /// use qubit_common::lang::DataType;
561 /// use qubit_value::Value;
562 ///
563 /// let value = Value::Int32(42);
564 /// assert_eq!(value.data_type(), DataType::Int32);
565 ///
566 /// let empty = Value::Empty(DataType::String);
567 /// assert_eq!(empty.data_type(), DataType::String);
568 /// ```
569 #[inline]
570 pub fn data_type(&self) -> DataType {
571 match self {
572 Value::Empty(dt) => *dt,
573 Value::Bool(_) => DataType::Bool,
574 Value::Char(_) => DataType::Char,
575 Value::Int8(_) => DataType::Int8,
576 Value::Int16(_) => DataType::Int16,
577 Value::Int32(_) => DataType::Int32,
578 Value::Int64(_) => DataType::Int64,
579 Value::Int128(_) => DataType::Int128,
580 Value::UInt8(_) => DataType::UInt8,
581 Value::UInt16(_) => DataType::UInt16,
582 Value::UInt32(_) => DataType::UInt32,
583 Value::UInt64(_) => DataType::UInt64,
584 Value::UInt128(_) => DataType::UInt128,
585 Value::Float32(_) => DataType::Float32,
586 Value::Float64(_) => DataType::Float64,
587 Value::String(_) => DataType::String,
588 Value::Date(_) => DataType::Date,
589 Value::Time(_) => DataType::Time,
590 Value::DateTime(_) => DataType::DateTime,
591 Value::Instant(_) => DataType::Instant,
592 Value::BigInteger(_) => DataType::BigInteger,
593 Value::BigDecimal(_) => DataType::BigDecimal,
594 Value::IntSize(_) => DataType::IntSize,
595 Value::UIntSize(_) => DataType::UIntSize,
596 Value::Duration(_) => DataType::Duration,
597 Value::Url(_) => DataType::Url,
598 Value::StringMap(_) => DataType::StringMap,
599 Value::Json(_) => DataType::Json,
600 }
601 }
602
603 /// Check if the value is empty
604 ///
605 /// # Returns
606 ///
607 /// Returns `true` if the value is empty
608 ///
609 /// # Example
610 ///
611 /// ```rust
612 /// use qubit_common::lang::DataType;
613 /// use qubit_value::Value;
614 ///
615 /// let value = Value::Int32(42);
616 /// assert!(!value.is_empty());
617 ///
618 /// let empty = Value::Empty(DataType::String);
619 /// assert!(empty.is_empty());
620 /// ```
621 #[inline]
622 pub fn is_empty(&self) -> bool {
623 matches!(self, Value::Empty(_))
624 }
625
626 /// Clear the value while preserving the type
627 ///
628 /// Sets the current value to empty but retains its data type.
629 ///
630 /// # Example
631 ///
632 /// ```rust
633 /// use qubit_common::lang::DataType;
634 /// use qubit_value::Value;
635 ///
636 /// let mut value = Value::Int32(42);
637 /// value.clear();
638 /// assert!(value.is_empty());
639 /// assert_eq!(value.data_type(), DataType::Int32);
640 /// ```
641 #[inline]
642 pub fn clear(&mut self) {
643 let dt = self.data_type();
644 *self = Value::Empty(dt);
645 }
646
647 /// Set the data type
648 ///
649 /// If the new type differs from the current type, clears the value
650 /// and sets the new type.
651 ///
652 /// # Parameters
653 ///
654 /// * `data_type` - The data type to set
655 ///
656 /// # Example
657 ///
658 /// ```rust
659 /// use qubit_common::lang::DataType;
660 /// use qubit_value::Value;
661 ///
662 /// let mut value = Value::Int32(42);
663 /// value.set_type(DataType::String);
664 /// assert!(value.is_empty());
665 /// assert_eq!(value.data_type(), DataType::String);
666 /// ```
667 #[inline]
668 pub fn set_type(&mut self, data_type: DataType) {
669 if self.data_type() != data_type {
670 *self = Value::Empty(data_type);
671 }
672 }
673}
674
675impl Default for Value {
676 #[inline]
677 fn default() -> Self {
678 Value::Empty(DataType::String)
679 }
680}