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#[derive(Debug, Clone, Default)]
38pub struct JsonValidatedDecodeOptionsBuilder {
39 /// Required root kind, when configured.
40 root_kind: Option<JsonRootKind>,
41 /// Token admission order for validated decoding.
42 admission_policy: JsonValidatedAdmissionPolicy,
43 /// Representation model used for preserved numbers.
44 number_model: JsonDecodeNumberModel,
45 /// Optional combined value-node and object-key-node limit.
46 max_value_and_key_nodes: Option<usize>,
47 /// Optional per-string-token source-byte limit.
48 max_encoded_string_bytes: Option<usize>,
49}
50
51impl JsonValidatedDecodeOptionsBuilder {
52 /// Selects the token admission order for validated decoding.
53 ///
54 /// # Parameters
55 ///
56 /// * `policy` - The admission order to use.
57 ///
58 /// # Returns
59 ///
60 /// The builder configured with the selected admission policy.
61 pub fn admission_policy(mut self, policy: JsonValidatedAdmissionPolicy) -> Self {
62 self.admission_policy = policy;
63 self
64 }
65 /// Requires a particular root kind.
66 ///
67 /// # Parameters
68 ///
69 /// * `kind` - Root kind required for a successfully decoded document.
70 ///
71 /// # Returns
72 ///
73 /// The builder configured with the required root kind.
74 pub fn root_kind(mut self, kind: JsonRootKind) -> Self {
75 self.root_kind = Some(kind);
76 self
77 }
78 /// Selects the number representation model.
79 ///
80 /// # Parameters
81 ///
82 /// * `model` - Number representation model used when numbers are preserved.
83 ///
84 /// # Returns
85 ///
86 /// The builder configured with the selected number model.
87 pub fn number_model(mut self, model: JsonDecodeNumberModel) -> Self {
88 self.number_model = model;
89 self
90 }
91 /// Limits value entries and decoded object-key entries per document.
92 ///
93 /// Every JSON value counts once, and every object key also counts once.
94 /// Zero is a valid limit and permits no counted entries.
95 ///
96 /// # Parameters
97 ///
98 /// * `maximum` - Maximum combined value and object-key node count.
99 ///
100 /// # Returns
101 ///
102 /// The builder with this per-document limit configured.
103 pub fn max_value_and_key_nodes(mut self, maximum: usize) -> Self {
104 self.max_value_and_key_nodes = Some(maximum);
105 self
106 }
107 /// Limits the source bytes inside each string token, excluding quotes.
108 /// Escape spelling is counted as it appears in the source, so `\u0061`
109 /// consumes six bytes. Zero permits only empty string token contents.
110 ///
111 /// # Parameters
112 ///
113 /// * `maximum` - Maximum number of source bytes inside each string token.
114 ///
115 /// # Returns
116 ///
117 /// The builder with this per-token limit configured.
118 pub fn max_encoded_string_bytes(mut self, maximum: usize) -> Self {
119 self.max_encoded_string_bytes = Some(maximum);
120 self
121 }
122 /// Builds the configured options.
123 ///
124 /// # Returns
125 ///
126 /// The options snapshot containing all configured settings.
127 pub fn build(self) -> JsonValidatedDecodeOptions {
128 JsonValidatedDecodeOptions {
129 root_kind: self.root_kind,
130 admission_policy: self.admission_policy,
131 number_model: self.number_model,
132 max_value_and_key_nodes: self.max_value_and_key_nodes,
133 max_encoded_string_bytes: self.max_encoded_string_bytes,
134 }
135 }
136}