Skip to main content

qubit_json/decode/
json_decode_number_model.rs

1// =============================================================================
2//    Copyright (c) 2026 Haixing Hu.
3//
4//    SPDX-License-Identifier: Apache-2.0
5//
6//    Licensed under the Apache License, Version 2.0.
7// =============================================================================
8//! Number representations accepted by JSON decoding.
9
10/// Controls lexical admission of syntactically valid JSON number tokens.
11///
12/// Typed decoding still lets Serde construct the requested target type, so its
13/// numeric representation can depend on that type and the active Serde
14/// features. Validated decoding constructs its owned value according to this
15/// model and the selected number policy.
16///
17/// # Examples
18///
19/// The default model rejects an integer above `u64::MAX`. The finite fallback
20/// admits it as an `f64`, which rounds this value and loses integer precision.
21/// This example uses a controlled input and an unlimited decoder for
22/// illustration; use finite limits for untrusted input. Typed decoding still
23/// lets the target type and active features determine its representation. Use
24/// a string or a domain-specific format when exact large integers are needed.
25/// See [`JsonValidatedDecodeOptions`](crate::decode::JsonValidatedDecodeOptions)
26/// and the [JSON number contract](https://github.com/qubit-ltd/rs-json/blob/main/doc/number_contract.md).
27///
28/// ```
29/// use std::convert::Infallible;
30///
31/// use qubit_json::decode::JsonDecodeErrorKind;
32/// use qubit_json::decode::JsonDecodeNumberModel;
33/// use qubit_json::decode::JsonDecoder;
34/// use qubit_json::decode::JsonNumberPolicy;
35/// use qubit_json::decode::JsonValidatedDecodeError;
36/// use qubit_json::decode::JsonValidatedDecodeOptions;
37///
38/// let input = "18446744073709551617";
39/// let strict = JsonValidatedDecodeOptions::builder().build();
40/// let error = JsonDecoder::unlimited()
41///     .decode_unique_validated_str(input, &strict, |_, _| {
42///         Ok::<_, Infallible>(JsonNumberPolicy::Preserve)
43///     })
44///     .expect_err("the default model rejects integers above u64::MAX");
45/// match error {
46///     JsonValidatedDecodeError::Decode { error, .. } => {
47///         assert_eq!(error.kind(), JsonDecodeErrorKind::InvalidJson);
48///     }
49///     other => panic!("unexpected error: {other:?}"),
50/// }
51///
52/// let fallback = JsonValidatedDecodeOptions::builder()
53///     .number_model(JsonDecodeNumberModel::Integer64WithFiniteFallback)
54///     .build();
55/// let owner = JsonDecoder::unlimited()
56///     .decode_unique_validated_str(input, &fallback, |_, _| {
57///         Ok::<_, Infallible>(JsonNumberPolicy::Preserve)
58///     })
59///     .expect("finite fallback admits the token with rounding");
60/// assert!(owner.as_value().is_f64());
61/// assert_eq!(owner.as_value().as_f64(), Some(18446744073709551616_f64));
62/// ```
63#[non_exhaustive]
64#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
65pub enum JsonDecodeNumberModel {
66    /// Accept signed and unsigned 64-bit integers and finite floating values.
67    #[default]
68    Integer64,
69    /// Also admit out-of-range integer tokens when they convert to finite
70    /// `f64` values.
71    ///
72    /// Validated decoding with `JsonNumberPolicy::Preserve` materializes these
73    /// tokens as finite `f64`; typed decoding leaves their representation to
74    /// Serde for the requested target type.
75    Integer64WithFiniteFallback,
76}