cadmpeg_ir/decode/
policy.rs1use schemars::JsonSchema;
5use serde::{Deserialize, Serialize};
6
7const MIB: u64 = 1024 * 1024;
8const GIB: u64 = 1024 * MIB;
9
10#[derive(Debug, Clone, Copy, PartialEq, Eq, Default, Serialize, Deserialize, JsonSchema)]
12#[serde(rename_all = "snake_case")]
13pub enum DecodeMode {
14 Strict,
16 #[default]
18 Salvage,
19}
20
21#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
23pub struct ResourceLimits {
24 pub max_input_bytes: u64,
26 pub max_decompressed_bytes_total: u64,
28 pub max_decompressed_bytes_per_expand: u64,
30}
31
32impl ResourceLimits {
33 pub const fn desktop() -> Self {
35 Self {
36 max_input_bytes: 4 * GIB,
37 max_decompressed_bytes_total: 8 * GIB,
38 max_decompressed_bytes_per_expand: 2 * GIB,
39 }
40 }
41
42 pub const fn service() -> Self {
44 Self {
45 max_input_bytes: 256 * MIB,
46 max_decompressed_bytes_total: GIB,
47 max_decompressed_bytes_per_expand: 256 * MIB,
48 }
49 }
50}
51
52impl Default for ResourceLimits {
53 fn default() -> Self {
54 Self::desktop()
55 }
56}
57
58#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
60pub struct DecodePolicy {
61 pub mode: DecodeMode,
63 pub limits: ResourceLimits,
65}
66
67impl DecodePolicy {
68 pub const fn desktop() -> Self {
70 Self {
71 mode: DecodeMode::Salvage,
72 limits: ResourceLimits::desktop(),
73 }
74 }
75
76 pub const fn service() -> Self {
78 Self {
79 mode: DecodeMode::Salvage,
80 limits: ResourceLimits::service(),
81 }
82 }
83}
84
85impl Default for DecodePolicy {
86 fn default() -> Self {
87 Self::desktop()
88 }
89}
90
91#[derive(Debug, Clone, Copy, PartialEq, Eq, Default, Serialize, Deserialize, JsonSchema)]
93pub struct InspectOptions {
94 pub limits: ResourceLimits,
96}
97
98pub(crate) const DECOMPRESSED_TOTAL_BASE: u64 = 16 * MIB;
99pub(crate) const DECOMPRESSED_TOTAL_PER_INPUT_BYTE: u64 = 1000;
100pub(crate) const DECOMPRESSED_PER_EXPAND_BASE: u64 = 16 * MIB;
101pub(crate) const DECOMPRESSED_PER_EXPAND_PER_INPUT_BYTE: u64 = 256;
102
103#[cfg(test)]
104mod tests {
105 use super::*;
106
107 #[test]
108 fn desktop_ceilings_are_explicit() {
109 let d = ResourceLimits::desktop();
110 assert_eq!(d.max_input_bytes, 4 * GIB);
111 assert_eq!(d.max_decompressed_bytes_total, 8 * GIB);
112 assert_eq!(d.max_decompressed_bytes_per_expand, 2 * GIB);
113 }
114
115 #[test]
116 fn service_ceilings_are_explicit() {
117 let s = ResourceLimits::service();
118 assert_eq!(s.max_input_bytes, 256 * MIB);
119 assert_eq!(s.max_decompressed_bytes_total, GIB);
120 assert_eq!(s.max_decompressed_bytes_per_expand, 256 * MIB);
121 }
122}