Skip to main content

qubit_metadata/
metadata_limits_builder.rs

1// =============================================================================
2//    Copyright (c) 2025 - 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 [`crate::MetadataLimits`].
9
10use qubit_budget::json::JsonDecodeLimits;
11use qubit_budget::json::JsonEncodeLimits;
12
13use crate::metadata_limits::DEFAULT_MAX_KEY_BYTES;
14use crate::metadata_limits::DEFAULT_MAX_METADATA_ENTRIES;
15use crate::metadata_limits::DEFAULT_MAX_SCHEMA_FIELDS;
16use crate::metadata_limits::MetadataLimits;
17use crate::metadata_limits::default_json_decode_limits;
18use crate::metadata_limits::default_json_encode_limits;
19
20/// Builder for [`MetadataLimits`].
21///
22/// # Examples
23///
24/// ```
25/// use qubit_metadata::MetadataLimits;
26///
27/// # fn main() -> Result<(), serde_json::Error> {
28/// let limits = MetadataLimits::builder().max_metadata_entries(128).build()?;
29/// assert_eq!(limits.max_metadata_entries(), 128);
30/// # Ok(())
31/// # }
32/// ```
33#[must_use]
34#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
35pub struct MetadataLimitsBuilder {
36    /// Receiver-controlled JSON budgets applied while decoding untrusted input.
37    pub(crate) json_decode: JsonDecodeLimits,
38    /// Preflight and output budgets applied while encoding metadata documents.
39    pub(crate) json_encode: JsonEncodeLimits,
40    /// Cardinality ceiling shared by metadata wire-map operations.
41    pub(crate) max_metadata_entries: usize,
42    /// Cardinality ceiling shared by schema wire-map operations.
43    pub(crate) max_schema_fields: usize,
44    /// UTF-8 byte ceiling shared by metadata and schema keys.
45    pub(crate) max_key_bytes: usize,
46}
47
48impl MetadataLimitsBuilder {
49    /// Replaces the JSON decoding profile.
50    #[inline(always)]
51    #[must_use = "the configured builder must be used to build metadata limits"]
52    pub fn json_decode(mut self, limits: JsonDecodeLimits) -> Self {
53        self.json_decode = limits;
54        self
55    }
56
57    /// Replaces the JSON encoding profile.
58    #[inline(always)]
59    #[must_use = "the configured builder must be used to build metadata limits"]
60    pub fn json_encode(mut self, limits: JsonEncodeLimits) -> Self {
61        self.json_encode = limits;
62        self
63    }
64
65    /// Sets the metadata-entry domain limit.
66    #[inline(always)]
67    #[must_use = "the configured builder must be used to build metadata limits"]
68    pub const fn max_metadata_entries(mut self, maximum: usize) -> Self {
69        self.max_metadata_entries = maximum;
70        self
71    }
72
73    /// Sets the schema-field domain limit.
74    #[inline(always)]
75    #[must_use = "the configured builder must be used to build metadata limits"]
76    pub const fn max_schema_fields(mut self, maximum: usize) -> Self {
77        self.max_schema_fields = maximum;
78        self
79    }
80
81    /// Sets the metadata/schema key-byte domain limit.
82    #[inline(always)]
83    #[must_use = "the configured builder must be used to build metadata limits"]
84    pub const fn max_key_bytes(mut self, maximum: usize) -> Self {
85        self.max_key_bytes = maximum;
86        self
87    }
88
89    /// Builds validated metadata limits by consuming this builder.
90    ///
91    /// # Errors
92    ///
93    /// Returns a configuration error when a domain limit exceeds its protocol
94    /// hard cap, matching [`crate::FilterLimitsBuilder::build`] validation
95    /// timing.
96    #[inline]
97    #[must_use = "the metadata limit validation result must be handled"]
98    pub fn build(self) -> Result<MetadataLimits, serde_json::Error> {
99        let limits = MetadataLimits::from_builder(self);
100        limits.validate()?;
101        Ok(limits)
102    }
103}
104
105impl Default for MetadataLimitsBuilder {
106    fn default() -> Self {
107        Self {
108            json_decode: default_json_decode_limits(),
109            json_encode: default_json_encode_limits(),
110            max_metadata_entries: DEFAULT_MAX_METADATA_ENTRIES,
111            max_schema_fields: DEFAULT_MAX_SCHEMA_FIELDS,
112            max_key_bytes: DEFAULT_MAX_KEY_BYTES,
113        }
114    }
115}