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}