qubit_metadata/
metadata_limits.rs1use qubit_budget::ResourceLimit;
11use qubit_budget::json::JsonDecodeLimits;
12use qubit_budget::json::JsonEncodeLimits;
13use qubit_budget::json::JsonResource;
14use qubit_budget::json::JsonValueLimits;
15use serde::de::Error as _;
16
17use crate::metadata_limits_builder::MetadataLimitsBuilder;
18
19pub const DEFAULT_MAX_JSON_BYTES: usize = 1_048_576;
21
22pub const DEFAULT_MAX_METADATA_ENTRIES: usize = 4_096;
24
25pub const DEFAULT_MAX_SCHEMA_FIELDS: usize = 4_096;
27
28pub const DEFAULT_MAX_KEY_BYTES: usize = 256;
30
31#[must_use]
50#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
51pub struct MetadataLimits {
52 json_decode: JsonDecodeLimits,
54 json_encode: JsonEncodeLimits,
56 max_metadata_entries: usize,
58 max_schema_fields: usize,
60 max_key_bytes: usize,
62}
63
64impl MetadataLimits {
65 #[inline(always)]
67 #[must_use = "the builder must be configured or used to build metadata limits"]
68 pub fn builder() -> MetadataLimitsBuilder {
69 MetadataLimitsBuilder::default()
70 }
71
72 #[cfg(debug_assertions)]
76 #[doc(hidden)]
77 pub fn debug_only_invalid_domain_limits(
78 max_metadata_entries: usize,
79 max_schema_fields: usize,
80 max_key_bytes: usize,
81 ) -> Self {
82 MetadataLimits::from_builder(
83 MetadataLimitsBuilder::default()
84 .max_metadata_entries(max_metadata_entries)
85 .max_schema_fields(max_schema_fields)
86 .max_key_bytes(max_key_bytes),
87 )
88 }
89
90 #[inline]
92 pub(crate) fn from_builder(builder: MetadataLimitsBuilder) -> Self {
93 Self {
94 json_decode: builder.json_decode,
95 json_encode: builder.json_encode,
96 max_metadata_entries: builder.max_metadata_entries,
97 max_schema_fields: builder.max_schema_fields,
98 max_key_bytes: builder.max_key_bytes,
99 }
100 }
101
102 #[inline(always)]
104 #[must_use]
105 pub const fn json_decode(&self) -> JsonDecodeLimits {
106 self.json_decode
107 }
108
109 #[inline(always)]
111 #[must_use]
112 pub const fn json_encode(&self) -> JsonEncodeLimits {
113 self.json_encode
114 }
115
116 #[inline(always)]
118 #[must_use]
119 pub const fn max_metadata_entries(&self) -> usize {
120 self.max_metadata_entries
121 }
122
123 #[inline(always)]
125 #[must_use]
126 pub const fn max_schema_fields(&self) -> usize {
127 self.max_schema_fields
128 }
129
130 #[inline(always)]
132 #[must_use]
133 pub const fn max_key_bytes(&self) -> usize {
134 self.max_key_bytes
135 }
136
137 pub fn validate(&self) -> Result<(), serde_json::Error> {
139 if self.max_metadata_entries > DEFAULT_MAX_METADATA_ENTRIES {
140 return Err(serde_json::Error::custom(format!(
141 "metadata entries limit {} exceeds {}",
142 self.max_metadata_entries, DEFAULT_MAX_METADATA_ENTRIES,
143 )));
144 }
145 if self.max_schema_fields > DEFAULT_MAX_SCHEMA_FIELDS {
146 return Err(serde_json::Error::custom(format!(
147 "schema fields limit {} exceeds {}",
148 self.max_schema_fields, DEFAULT_MAX_SCHEMA_FIELDS,
149 )));
150 }
151 if self.max_key_bytes > DEFAULT_MAX_KEY_BYTES {
152 return Err(serde_json::Error::custom(format!(
153 "metadata key limit {} exceeds {}",
154 self.max_key_bytes, DEFAULT_MAX_KEY_BYTES,
155 )));
156 }
157 Ok(())
158 }
159}
160
161impl Default for MetadataLimits {
162 fn default() -> Self {
163 Self::builder()
164 .build()
165 .expect("default metadata limits satisfy protocol hard caps")
166 }
167}
168
169pub fn default_json_value_limits() -> JsonValueLimits {
171 JsonValueLimits::<JsonResource, usize>::builder()
172 .max_depth(64_usize)
173 .max_nodes(100_000_usize)
174 .max_sequence_items(4_096_usize)
175 .max_map_entries(json_quantity(DEFAULT_MAX_METADATA_ENTRIES))
176 .max_key_bytes(256 * 1024_usize)
177 .max_string_bytes(256 * 1024_usize)
178 .max_number_bytes(4_096_usize)
179 .max_payload_bytes(json_quantity(DEFAULT_MAX_JSON_BYTES))
180 .build()
181}
182
183pub fn default_json_decode_limits() -> JsonDecodeLimits {
185 JsonDecodeLimits::builder()
186 .input_bytes_limit(ResourceLimit::new(
187 JsonResource::InputBytes,
188 json_quantity(DEFAULT_MAX_JSON_BYTES),
189 ))
190 .value_limits(default_json_value_limits())
191 .build()
192}
193
194pub fn default_json_encode_limits() -> JsonEncodeLimits {
196 JsonEncodeLimits::builder()
197 .output_bytes_limit(ResourceLimit::new(
198 JsonResource::OutputBytes,
199 json_quantity(DEFAULT_MAX_JSON_BYTES),
200 ))
201 .value_limits(default_json_value_limits())
202 .build()
203}
204
205fn json_quantity(value: usize) -> usize {
207 value
208}