Skip to main content

qubit_json/decode/
json_validated_decode_options_builder.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//! Builder for validated JSON decode configuration.
9
10use super::JsonDecodeNumberModel;
11use super::JsonRootKind;
12use super::JsonValidatedAdmissionPolicy;
13use super::JsonValidatedDecodeOptions;
14
15/// Builds [`JsonValidatedDecodeOptions`].
16///
17/// Unset optional settings impose no additional limit. A configured zero is a
18/// valid bound and permits zero counted nodes or zero source bytes.
19///
20/// # Examples
21///
22/// ```
23/// use qubit_json::decode::{JsonDecoder, JsonNumberPolicy, JsonValidatedDecodeOptions};
24///
25/// let options = JsonValidatedDecodeOptions::builder()
26///     .max_value_and_key_nodes(3)
27///     .max_encoded_string_bytes(8)
28///     .build();
29/// let value = JsonDecoder::unlimited().decode_unique_validated_str(
30///     r#"{"id":42}"#,
31///     &options,
32///     |_path, _token| Ok::<_, std::convert::Infallible>(JsonNumberPolicy::ExactSafeInteger),
33/// )?;
34/// assert_eq!(value.as_value()["id"].as_i64(), Some(42));
35/// # Ok::<(), Box<dyn std::error::Error>>(())
36/// ```
37#[must_use = "the builder must be used to configure decode options"]
38#[derive(Debug, Clone, Default)]
39pub struct JsonValidatedDecodeOptionsBuilder {
40    /// Required root kind, when configured.
41    root_kind: Option<JsonRootKind>,
42    /// Token admission order for validated decoding.
43    admission_policy: JsonValidatedAdmissionPolicy,
44    /// Representation model used for preserved numbers.
45    number_model: JsonDecodeNumberModel,
46    /// Optional combined value-node and object-key-node limit.
47    max_value_and_key_nodes: Option<usize>,
48    /// Optional per-string-token source-byte limit.
49    max_encoded_string_bytes: Option<usize>,
50}
51
52impl JsonValidatedDecodeOptionsBuilder {
53    /// Selects the token admission order for validated decoding.
54    ///
55    /// # Parameters
56    ///
57    /// * `policy` - The admission order to use.
58    ///
59    /// # Returns
60    ///
61    /// The builder configured with the selected admission policy.
62    pub fn admission_policy(mut self, policy: JsonValidatedAdmissionPolicy) -> Self {
63        self.admission_policy = policy;
64        self
65    }
66    /// Requires a particular root kind.
67    ///
68    /// # Parameters
69    ///
70    /// * `kind` - Root kind required for a successfully decoded document.
71    ///
72    /// # Returns
73    ///
74    /// The builder configured with the required root kind.
75    pub fn root_kind(mut self, kind: JsonRootKind) -> Self {
76        self.root_kind = Some(kind);
77        self
78    }
79    /// Selects the number representation model.
80    ///
81    /// # Parameters
82    ///
83    /// * `model` - Number representation model used when numbers are preserved.
84    ///
85    /// # Returns
86    ///
87    /// The builder configured with the selected number model.
88    pub fn number_model(mut self, model: JsonDecodeNumberModel) -> Self {
89        self.number_model = model;
90        self
91    }
92    /// Limits value entries and decoded object-key entries per document.
93    ///
94    /// Every JSON value counts once, and every object key also counts once.
95    /// Zero is a valid limit and permits no counted entries.
96    ///
97    /// # Parameters
98    ///
99    /// * `maximum` - Maximum combined value and object-key node count.
100    ///
101    /// # Returns
102    ///
103    /// The builder with this per-document limit configured.
104    pub fn max_value_and_key_nodes(mut self, maximum: usize) -> Self {
105        self.max_value_and_key_nodes = Some(maximum);
106        self
107    }
108    /// Limits the source bytes inside each string token, excluding quotes.
109    /// Escape spelling is counted as it appears in the source, so `\u0061`
110    /// consumes six bytes. Zero permits only empty string token contents.
111    ///
112    /// # Parameters
113    ///
114    /// * `maximum` - Maximum number of source bytes inside each string token.
115    ///
116    /// # Returns
117    ///
118    /// The builder with this per-token limit configured.
119    pub fn max_encoded_string_bytes(mut self, maximum: usize) -> Self {
120        self.max_encoded_string_bytes = Some(maximum);
121        self
122    }
123    /// Builds the configured options.
124    ///
125    /// # Returns
126    ///
127    /// The options snapshot containing all configured settings.
128    #[must_use]
129    pub fn build(self) -> JsonValidatedDecodeOptions {
130        JsonValidatedDecodeOptions {
131            root_kind: self.root_kind,
132            admission_policy: self.admission_policy,
133            number_model: self.number_model,
134            max_value_and_key_nodes: self.max_value_and_key_nodes,
135            max_encoded_string_bytes: self.max_encoded_string_bytes,
136        }
137    }
138}