1const KIB: u64 = 1024;
2const MIB: u64 = 1024 * KIB;
3
4#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
5#[non_exhaustive]
6pub enum IconRegistryResourceLimitId {
7 MaxPacks,
8 MaxPackBytes,
9 MaxInputBytes,
10 MaxJsonDepth,
11 MaxJsonMembers,
12 MaxJsonKeyBytes,
13 MaxPrefixBytes,
14 MaxNameBytes,
15 MaxBodyBytes,
16 MaxRetainedBodyBytes,
17 MaxIconEntries,
18 MaxAliasEntries,
19 MaxTotalEntries,
20 MaxAliasEdges,
21 MaxAliasDepth,
22 MaxAliasFanout,
23 MaxBuildWorkUnits,
24 MaxXmlElementsPerBody,
25 MaxXmlDepthPerBody,
26 MaxIdRewriteEditsPerBody,
27 MaxRetainedXmlPlanBytes,
28 MaxCoordinateMagnitude,
29}
30
31impl IconRegistryResourceLimitId {
32 pub const ALL: &'static [Self] = &[
33 Self::MaxPacks,
34 Self::MaxPackBytes,
35 Self::MaxInputBytes,
36 Self::MaxJsonDepth,
37 Self::MaxJsonMembers,
38 Self::MaxJsonKeyBytes,
39 Self::MaxPrefixBytes,
40 Self::MaxNameBytes,
41 Self::MaxBodyBytes,
42 Self::MaxRetainedBodyBytes,
43 Self::MaxIconEntries,
44 Self::MaxAliasEntries,
45 Self::MaxTotalEntries,
46 Self::MaxAliasEdges,
47 Self::MaxAliasDepth,
48 Self::MaxAliasFanout,
49 Self::MaxBuildWorkUnits,
50 Self::MaxXmlElementsPerBody,
51 Self::MaxXmlDepthPerBody,
52 Self::MaxIdRewriteEditsPerBody,
53 Self::MaxRetainedXmlPlanBytes,
54 Self::MaxCoordinateMagnitude,
55 ];
56
57 pub const fn stable_id(self) -> &'static str {
58 match self {
59 Self::MaxPacks => "max_icon_registry_packs",
60 Self::MaxPackBytes => "max_icon_pack_bytes",
61 Self::MaxInputBytes => "max_icon_registry_input_bytes",
62 Self::MaxJsonDepth => "max_icon_registry_json_depth",
63 Self::MaxJsonMembers => "max_icon_registry_json_members",
64 Self::MaxJsonKeyBytes => "max_icon_registry_json_key_bytes",
65 Self::MaxPrefixBytes => "max_icon_registry_prefix_bytes",
66 Self::MaxNameBytes => "max_icon_registry_name_bytes",
67 Self::MaxBodyBytes => "max_icon_body_bytes",
68 Self::MaxRetainedBodyBytes => "max_icon_registry_retained_body_bytes",
69 Self::MaxIconEntries => "max_icon_registry_icon_entries",
70 Self::MaxAliasEntries => "max_icon_registry_alias_entries",
71 Self::MaxTotalEntries => "max_icon_registry_entries",
72 Self::MaxAliasEdges => "max_icon_registry_alias_edges",
73 Self::MaxAliasDepth => "max_icon_registry_alias_depth",
74 Self::MaxAliasFanout => "max_icon_registry_alias_fanout",
75 Self::MaxBuildWorkUnits => "max_icon_registry_build_work_units",
76 Self::MaxXmlElementsPerBody => "max_icon_xml_elements_per_body",
77 Self::MaxXmlDepthPerBody => "max_icon_xml_depth_per_body",
78 Self::MaxIdRewriteEditsPerBody => "max_icon_id_rewrite_edits_per_body",
79 Self::MaxRetainedXmlPlanBytes => "max_icon_registry_retained_xml_plan_bytes",
80 Self::MaxCoordinateMagnitude => "max_icon_coordinate_magnitude",
81 }
82 }
83
84 pub const fn fixed_value(self) -> u64 {
85 match self {
86 Self::MaxPacks => 16,
87 Self::MaxPackBytes => 16 * MIB,
88 Self::MaxInputBytes => 32 * MIB,
89 Self::MaxJsonDepth => 32,
90 Self::MaxJsonMembers => 1_000_000,
91 Self::MaxJsonKeyBytes => 1_024,
92 Self::MaxPrefixBytes => 64,
93 Self::MaxNameBytes => 128,
94 Self::MaxBodyBytes => 256 * KIB,
95 Self::MaxRetainedBodyBytes => 32 * MIB,
96 Self::MaxIconEntries => 32_768,
97 Self::MaxAliasEntries => 32_768,
98 Self::MaxTotalEntries => 65_536,
99 Self::MaxAliasEdges => 32_768,
100 Self::MaxAliasDepth => 64,
101 Self::MaxAliasFanout => 1_024,
102 Self::MaxBuildWorkUnits => 4_000_000,
103 Self::MaxXmlElementsPerBody => 4_096,
104 Self::MaxXmlDepthPerBody => crate::resources::MAX_PORTABLE_ICON_BODY_XML_DEPTH as u64,
107 Self::MaxIdRewriteEditsPerBody => 16_384,
108 Self::MaxRetainedXmlPlanBytes => 16 * MIB,
109 Self::MaxCoordinateMagnitude => 1_000_000,
110 }
111 }
112
113 #[must_use]
114 pub const fn descriptor(self) -> &'static IconRegistryResourceLimitDescriptor {
115 &ICON_REGISTRY_RESOURCE_LIMIT_DESCRIPTORS[self as usize]
116 }
117}
118
119#[derive(Debug, Clone, Copy, PartialEq, Eq)]
120#[non_exhaustive]
121pub struct IconRegistryResourceLimitDescriptor {
122 pub id: IconRegistryResourceLimitId,
123 pub stable_id: &'static str,
124 pub phase: &'static str,
125 pub unit: &'static str,
126 pub description: &'static str,
127 pub default_value: u64,
128 pub hard_maximum: u64,
129 pub caller_configurable: bool,
130}
131
132const fn descriptor(
133 id: IconRegistryResourceLimitId,
134 phase: &'static str,
135 unit: &'static str,
136 description: &'static str,
137) -> IconRegistryResourceLimitDescriptor {
138 let value = id.fixed_value();
139 IconRegistryResourceLimitDescriptor {
140 id,
141 stable_id: id.stable_id(),
142 phase,
143 unit,
144 description,
145 default_value: value,
146 hard_maximum: value,
147 caller_configurable: false,
148 }
149}
150
151pub const ICON_REGISTRY_RESOURCE_LIMIT_DESCRIPTORS: &[IconRegistryResourceLimitDescriptor] = &[
152 descriptor(
153 IconRegistryResourceLimitId::MaxPacks,
154 "icon_registry_input",
155 "packs",
156 "Maximum IconifyJSON packs admitted by one immutable registry",
157 ),
158 descriptor(
159 IconRegistryResourceLimitId::MaxPackBytes,
160 "icon_registry_input",
161 "bytes",
162 "Maximum encoded bytes admitted from one IconifyJSON pack",
163 ),
164 descriptor(
165 IconRegistryResourceLimitId::MaxInputBytes,
166 "icon_registry_input",
167 "bytes",
168 "Maximum aggregate encoded bytes admitted by one registry",
169 ),
170 descriptor(
171 IconRegistryResourceLimitId::MaxJsonDepth,
172 "icon_registry_parse",
173 "levels",
174 "Maximum JSON nesting depth inspected while ingesting packs",
175 ),
176 descriptor(
177 IconRegistryResourceLimitId::MaxJsonMembers,
178 "icon_registry_parse",
179 "members",
180 "Maximum aggregate JSON map members and sequence items inspected",
181 ),
182 descriptor(
183 IconRegistryResourceLimitId::MaxJsonKeyBytes,
184 "icon_registry_parse",
185 "bytes",
186 "Maximum decoded bytes in any IconifyJSON object key, including unknown extensions",
187 ),
188 descriptor(
189 IconRegistryResourceLimitId::MaxPrefixBytes,
190 "icon_registry_parse",
191 "bytes",
192 "Maximum admitted Iconify prefix or registration-name bytes",
193 ),
194 descriptor(
195 IconRegistryResourceLimitId::MaxNameBytes,
196 "icon_registry_parse",
197 "bytes",
198 "Maximum admitted Iconify icon or alias name bytes",
199 ),
200 descriptor(
201 IconRegistryResourceLimitId::MaxBodyBytes,
202 "icon_registry_xml",
203 "bytes",
204 "Maximum decoded SVG fragment bytes retained for one direct icon",
205 ),
206 descriptor(
207 IconRegistryResourceLimitId::MaxRetainedBodyBytes,
208 "icon_registry_retain",
209 "bytes",
210 "Maximum aggregate decoded direct-icon SVG body bytes retained",
211 ),
212 descriptor(
213 IconRegistryResourceLimitId::MaxIconEntries,
214 "icon_registry_parse",
215 "entries",
216 "Maximum direct icon entries admitted by one registry",
217 ),
218 descriptor(
219 IconRegistryResourceLimitId::MaxAliasEntries,
220 "icon_registry_alias",
221 "entries",
222 "Maximum alias entries admitted by one registry",
223 ),
224 descriptor(
225 IconRegistryResourceLimitId::MaxTotalEntries,
226 "icon_registry_alias",
227 "entries",
228 "Maximum resolved direct icon and alias entries published",
229 ),
230 descriptor(
231 IconRegistryResourceLimitId::MaxAliasEdges,
232 "icon_registry_alias",
233 "edges",
234 "Maximum parent edges inspected by alias resolution",
235 ),
236 descriptor(
237 IconRegistryResourceLimitId::MaxAliasDepth,
238 "icon_registry_alias",
239 "levels",
240 "Maximum resolved alias parent-chain depth",
241 ),
242 descriptor(
243 IconRegistryResourceLimitId::MaxAliasFanout,
244 "icon_registry_alias",
245 "aliases",
246 "Maximum aliases that may directly reference one parent",
247 ),
248 descriptor(
249 IconRegistryResourceLimitId::MaxBuildWorkUnits,
250 "icon_registry_build",
251 "work_units",
252 "Maximum deterministic parse, XML, and alias-resolution work",
253 ),
254 descriptor(
255 IconRegistryResourceLimitId::MaxXmlElementsPerBody,
256 "icon_registry_xml",
257 "elements",
258 "Maximum XML elements in one direct icon SVG fragment",
259 ),
260 descriptor(
261 IconRegistryResourceLimitId::MaxXmlDepthPerBody,
262 "icon_registry_xml",
263 "levels",
264 "Maximum XML element nesting depth in one direct icon fragment",
265 ),
266 descriptor(
267 IconRegistryResourceLimitId::MaxIdRewriteEditsPerBody,
268 "icon_registry_xml",
269 "edits",
270 "Maximum XML ID declaration and reference rewrites planned for one icon body",
271 ),
272 descriptor(
273 IconRegistryResourceLimitId::MaxRetainedXmlPlanBytes,
274 "icon_registry_retain",
275 "bytes",
276 "Maximum aggregate retained XML rewrite and defs-plan bytes",
277 ),
278 descriptor(
279 IconRegistryResourceLimitId::MaxCoordinateMagnitude,
280 "icon_registry_geometry",
281 "coordinate_units",
282 "Maximum absolute view-box coordinate or positive dimension",
283 ),
284];
285
286pub const fn icon_registry_resource_limit_descriptors()
287-> &'static [IconRegistryResourceLimitDescriptor] {
288 ICON_REGISTRY_RESOURCE_LIMIT_DESCRIPTORS
289}
290
291#[derive(Debug, Clone, Copy)]
292pub(super) struct IconRegistryBuildLimits {
293 pub max_packs: usize,
294 pub max_pack_bytes: usize,
295 pub max_input_bytes: usize,
296 pub max_json_depth: usize,
297 pub max_json_members: usize,
298 pub max_json_key_bytes: usize,
299 pub max_prefix_bytes: usize,
300 pub max_name_bytes: usize,
301 pub max_body_bytes: usize,
302 pub max_retained_body_bytes: usize,
303 pub max_icon_entries: usize,
304 pub max_alias_entries: usize,
305 pub max_total_entries: usize,
306 pub max_alias_edges: usize,
307 pub max_alias_depth: usize,
308 pub max_alias_fanout: usize,
309 pub max_build_work_units: usize,
310 pub max_xml_elements_per_body: usize,
311 pub max_xml_depth_per_body: usize,
312 pub max_id_rewrite_edits_per_body: usize,
313 pub max_retained_xml_plan_bytes: usize,
314 pub max_coordinate_magnitude: f64,
315}
316
317impl IconRegistryBuildLimits {
318 pub const fn fixed() -> Self {
319 Self {
320 max_packs: IconRegistryResourceLimitId::MaxPacks.fixed_value() as usize,
321 max_pack_bytes: IconRegistryResourceLimitId::MaxPackBytes.fixed_value() as usize,
322 max_input_bytes: IconRegistryResourceLimitId::MaxInputBytes.fixed_value() as usize,
323 max_json_depth: IconRegistryResourceLimitId::MaxJsonDepth.fixed_value() as usize,
324 max_json_members: IconRegistryResourceLimitId::MaxJsonMembers.fixed_value() as usize,
325 max_json_key_bytes: IconRegistryResourceLimitId::MaxJsonKeyBytes.fixed_value() as usize,
326 max_prefix_bytes: IconRegistryResourceLimitId::MaxPrefixBytes.fixed_value() as usize,
327 max_name_bytes: IconRegistryResourceLimitId::MaxNameBytes.fixed_value() as usize,
328 max_body_bytes: IconRegistryResourceLimitId::MaxBodyBytes.fixed_value() as usize,
329 max_retained_body_bytes: IconRegistryResourceLimitId::MaxRetainedBodyBytes.fixed_value()
330 as usize,
331 max_icon_entries: IconRegistryResourceLimitId::MaxIconEntries.fixed_value() as usize,
332 max_alias_entries: IconRegistryResourceLimitId::MaxAliasEntries.fixed_value() as usize,
333 max_total_entries: IconRegistryResourceLimitId::MaxTotalEntries.fixed_value() as usize,
334 max_alias_edges: IconRegistryResourceLimitId::MaxAliasEdges.fixed_value() as usize,
335 max_alias_depth: IconRegistryResourceLimitId::MaxAliasDepth.fixed_value() as usize,
336 max_alias_fanout: IconRegistryResourceLimitId::MaxAliasFanout.fixed_value() as usize,
337 max_build_work_units: IconRegistryResourceLimitId::MaxBuildWorkUnits.fixed_value()
338 as usize,
339 max_xml_elements_per_body: IconRegistryResourceLimitId::MaxXmlElementsPerBody
340 .fixed_value() as usize,
341 max_xml_depth_per_body: IconRegistryResourceLimitId::MaxXmlDepthPerBody.fixed_value()
342 as usize,
343 max_id_rewrite_edits_per_body: IconRegistryResourceLimitId::MaxIdRewriteEditsPerBody
344 .fixed_value() as usize,
345 max_retained_xml_plan_bytes: IconRegistryResourceLimitId::MaxRetainedXmlPlanBytes
346 .fixed_value() as usize,
347 max_coordinate_magnitude: IconRegistryResourceLimitId::MaxCoordinateMagnitude
348 .fixed_value() as f64,
349 }
350 }
351}