Skip to main content

tfparser_core/loader/
limits.rs

1//! Loader resource limits.
2//!
3//! Defaults match [12-hcl-loader.md § 3.5] and [70-security.md § 3.2]. The
4//! loader checks each cap as it walks; breaching one emits a
5//! [`crate::Diagnostic`] (file skipped) for the per-file caps and
6//! [`crate::Error::Limit`] (fatal) for caps the caller could only have
7//! noticed by allowing unbounded work first.
8//!
9//! [12-hcl-loader.md § 3.5]: ../../../specs/12-hcl-loader.md
10//! [70-security.md § 3.2]: ../../../specs/70-security.md
11
12use typed_builder::TypedBuilder;
13
14/// Per-file caps enforced by the loader.
15#[derive(Clone, Copy, Debug, PartialEq, Eq, TypedBuilder)]
16#[non_exhaustive]
17pub struct LoaderLimits {
18    /// Maximum byte size for any individual file. Default: 4 MiB.
19    #[builder(default = 4 * 1024 * 1024)]
20    pub max_file_bytes: u32,
21
22    /// Maximum top-level-or-nested block count per file. Default: 10 000.
23    #[builder(default = 10_000)]
24    pub max_blocks_per_file: u32,
25
26    /// Maximum nested expression depth (objects, lists, conditionals,
27    /// templates). Default: 64.
28    #[builder(default = 64)]
29    pub max_attr_depth: u32,
30
31    /// Maximum number of parts in a `TemplateConcat` lowering output.
32    /// Default: 1024.
33    #[builder(default = 1024)]
34    pub max_template_parts: u32,
35}
36
37impl Default for LoaderLimits {
38    fn default() -> Self {
39        Self::builder().build()
40    }
41}
42
43#[cfg(test)]
44#[allow(clippy::unwrap_used)]
45mod tests {
46    use super::*;
47
48    #[test]
49    fn test_defaults_match_spec() {
50        let l = LoaderLimits::default();
51        assert_eq!(l.max_file_bytes, 4 * 1024 * 1024);
52        assert_eq!(l.max_blocks_per_file, 10_000);
53        assert_eq!(l.max_attr_depth, 64);
54        assert_eq!(l.max_template_parts, 1024);
55    }
56
57    #[test]
58    fn test_builder_overrides() {
59        let l = LoaderLimits::builder()
60            .max_file_bytes(1024_u32)
61            .max_blocks_per_file(2_u32)
62            .build();
63        assert_eq!(l.max_file_bytes, 1024);
64        assert_eq!(l.max_blocks_per_file, 2);
65        // Other fields keep their defaults.
66        assert_eq!(l.max_attr_depth, 64);
67    }
68}