1use crate::types::{QrError, QrResult, Version};
4
5pub const DEFAULT_MAX_DATA_LENGTH: usize = 7_089;
11
12pub const DEFAULT_MAX_RENDER_SIZE: (u32, u32) = (4_096, 4_096);
14
15#[derive(Clone, Copy, Debug, PartialEq, Eq)]
23#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
24pub struct ResourceLimits {
25 pub max_data_length: usize,
27 pub max_version: Version,
29 pub max_render_size: (u32, u32),
31}
32
33impl Default for ResourceLimits {
34 fn default() -> Self {
35 Self {
36 max_data_length: DEFAULT_MAX_DATA_LENGTH,
37 max_version: Version::Normal(40),
38 max_render_size: DEFAULT_MAX_RENDER_SIZE,
39 }
40 }
41}
42
43impl ResourceLimits {
44 #[must_use]
46 pub const fn new(max_data_length: usize, max_version: Version, max_render_size: (u32, u32)) -> Self {
47 Self { max_data_length, max_version, max_render_size }
48 }
49
50 pub fn validate(self) -> QrResult<()> {
56 let valid_version = matches!(self.max_version, Version::Normal(1..=40));
57 let valid_render_size = self.max_render_size.0 != 0 && self.max_render_size.1 != 0;
58 if valid_version && valid_render_size { Ok(()) } else { Err(QrError::InvalidResourceLimits) }
59 }
60}
61
62#[cfg(test)]
63mod tests {
64 use super::{DEFAULT_MAX_DATA_LENGTH, DEFAULT_MAX_RENDER_SIZE, ResourceLimits};
65 use crate::types::Version;
66
67 #[test]
68 fn default_budget_is_bounded() {
69 let limits = ResourceLimits::default();
70 assert_eq!(limits.max_data_length, DEFAULT_MAX_DATA_LENGTH);
71 assert_eq!(limits.max_version, Version::Normal(40));
72 assert_eq!(limits.max_render_size, DEFAULT_MAX_RENDER_SIZE);
73 assert!(limits.validate().is_ok());
74 }
75
76 #[test]
77 fn invalid_budget_is_rejected() {
78 assert!(ResourceLimits::new(1, Version::Micro(4), (1, 1)).validate().is_err());
79 assert!(ResourceLimits::new(1, Version::Normal(1), (0, 1)).validate().is_err());
80 }
81}