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}