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