Skip to main content

qubit_value/
lib.rs

1// =============================================================================
2//    Copyright (c) 2025 - 2026 Haixing Hu.
3//
4//    SPDX-License-Identifier: Apache-2.0
5//
6//    Licensed under the Apache License, Version 2.0.
7// =============================================================================
8//! # Value Processing Framework
9//!
10//! Provides type-safe value storage and access functionality, supporting single
11//! values, collections, explicit scalar-or-collection shape, and named values.
12//!
13//! # Public API Overview
14//!
15//! - [`Value`] stores one typed scalar, including an explicit `Unset(DataType)`
16//!   state.
17//! - [`MultiValues`] stores one homogeneous typed collection.
18//! - [`ValueRef`] and [`MultiValuesRef`] expose borrowed semantic views while
19//!   keeping runtime storage private.
20//! - [`ValueContainer`] preserves whether storage is scalar or collection.
21//! - [`NamedValue`] and [`NamedMultiValues`] provide name wrappers.
22//! - [`ValueWireV1`] and [`ValueWirePayloadV1`] name explicit Serde DTOs.
23//! - [`ValueWireRefV1`] and [`ValueWirePayloadRefV1`] serialize borrowed
24//!   values.
25//!
26//! # Core behavior
27//!
28//! - [`Value::get`] and [`MultiValues::get`] perform strict typed reads.
29//! - [`ValueContainer`] preserves whether the source supplied a scalar or an
30//!   explicit collection, even when the collection contains one item.
31//! - `to` methods use `qubit-datatype` conversion policy and resource limits.
32//! - Optional type families and conversion methods are available only when the
33//!   corresponding crate features are enabled; all-features documentation shows
34//!   the superset of those APIs.
35//! - [`Value::is_unset`] and [`ValueContainer::is_unset`] indicate that no
36//!   concrete value is stored.
37//! - [`MultiValues::is_unset`] distinguishes no collection from a concrete
38//!   collection; [`MultiValues::is_empty`] reports only that its length is
39//!   zero.
40//! - Generic `set` replaces a value infallibly; [`MultiValues::add`] remains
41//!   fallible because appended values must have the same data type.
42//! - Serde uses the strict, type-preserving [`ValueWireV1`] envelope. Its
43//!   canonical JSON representation is byte-stable for the same value under the
44//!   supported `serde_json` version and configuration. String-map keys and
45//!   nested JSON object keys are emitted in lexicographic order. Other Serde
46//!   formats are supported as representations, but are outside this byte-level
47//!   stability contract. With the `natural-json` feature, `to_json_value`
48//!   provides a separate natural JSON projection with the same ordering.
49//! - Version one rejects externally tagged representations.
50//! - Non-finite floats may exist in memory, but V1 Serde and natural JSON
51//!   reject them because JSON has no `NaN` or infinity number literals.
52//! - JSON numbers follow `qubit-json`'s explicit range contract: negative
53//!   integers fit `i64`, non-negative integers fit `u64`, and fractional or
54//!   exponential values are finite `f64`. Wider exact values use the crate's
55//!   explicit string-based integer and decimal wire representations.
56//!
57//! # Usage Examples
58//!
59//! ## Single Value Operations
60//!
61//! ```rust
62//! use qubit_value::Value;
63//!
64//! // Create and access a single value
65//! let value = Value::Int32(42);
66//! assert_eq!(value.get_int32().unwrap(), 42);
67//!
68//! // Strict generic access
69//! let number: i32 = value.get().unwrap();
70//! assert_eq!(number, 42);
71//! ```
72//!
73//! ## Multiple Values Operations
74//!
75//! ```rust
76//! use qubit_value::MultiValues;
77//!
78//! // Create and access multiple values
79//! let mut values = MultiValues::Int32(vec![1, 2, 3]);
80//! assert_eq!(values.len(), 3);
81//!
82//! // Add values
83//! values.add(4).unwrap();
84//! assert_eq!(values.get_int32s().unwrap(), &[1, 2, 3, 4]);
85//! ```
86//!
87//! ## Named Value Operations
88//!
89//! ```rust
90//! use qubit_value::{NamedValue, Value};
91//!
92//! // Create a named value
93//! let config = NamedValue::new("port", Value::Int32(8080));
94//! assert_eq!(config.name(), "port");
95//! assert_eq!(config.value().get_int32().unwrap(), 8080);
96//! ```
97//!
98//! ## Explicit Shape Operations
99//!
100//! ```rust
101//! use qubit_value::ValueContainer;
102//!
103//! let scalar = ValueContainer::from(42_i32);
104//! let collection = ValueContainer::from(vec![42_i32]);
105//! assert!(scalar.is_scalar());
106//! assert!(collection.is_collection());
107//! ```
108
109// Sub-modules
110mod finite_float;
111mod identity;
112mod into_value_default;
113#[macro_use]
114mod value_type_table;
115#[cfg(any(feature = "natural-json", all(feature = "converter", feature = "json")))]
116mod json;
117mod multi_values;
118mod named_multi_values;
119mod named_value;
120mod numeric_comparison_error;
121mod strict_value_read;
122mod value;
123mod value_container;
124mod value_error;
125mod value_missing;
126mod value_missing_reason;
127mod value_wire;
128mod wide_integer;
129mod wire;
130
131// Public exports
132pub use self::into_value_default::IntoValueDefault;
133pub use self::multi_values::MultiValues;
134pub use self::multi_values::MultiValuesRef;
135pub use self::named_multi_values::NamedMultiValues;
136pub use self::named_value::NamedValue;
137pub use self::numeric_comparison_error::NumericComparisonError;
138pub use self::strict_value_read::StrictValueRead;
139pub use self::value::Value;
140pub use self::value::ValueRef;
141pub use self::value_container::ValueContainer;
142pub use self::value_error::ValueError;
143pub use self::value_error::ValueResult;
144pub use self::value_missing::ValueMissing;
145pub use self::value_missing_reason::ValueMissingReason;
146#[cfg(feature = "json")]
147pub use self::value_wire::ValueWireDecodeError;
148pub use self::value_wire::ValueWireEncodeError;
149#[cfg(feature = "json")]
150pub use self::value_wire::ValueWireEncodePreflight;
151pub use self::value_wire::ValueWirePayloadRefV1;
152pub use self::value_wire::ValueWirePayloadV1;
153pub use self::value_wire::ValueWirePayloadV1Seed;
154pub use self::value_wire::ValueWireRefV1;
155pub use self::value_wire::ValueWireV1;
156pub use self::value_wire::ValueWireV1Seed;