1use crate::{Error, Result};
4
5pub const DEFAULT_IO_CHUNK: usize = 256 * 1024;
7pub const MAX_IO_CHUNK: usize = 1024 * 1024;
9#[derive(Clone, Copy, Debug, Eq, PartialEq)]
15pub struct Limits {
16 pub io_chunk_bytes: usize,
18 pub max_input_bytes: u64,
20 pub max_output_bytes: u64,
22 pub max_allocation_bytes: u64,
26 pub max_pages: u32,
28 pub max_bookmarks: u32,
30 pub max_image_pixels: u64,
32 pub max_symbols: u32,
35}
36
37impl Default for Limits {
38 fn default() -> Self {
39 Self {
40 io_chunk_bytes: DEFAULT_IO_CHUNK,
41 max_input_bytes: 8 * 1024 * 1024 * 1024,
42 max_output_bytes: 16 * 1024 * 1024 * 1024,
43 max_allocation_bytes: 64 * 1024 * 1024,
44 max_pages: 100_000,
45 max_bookmarks: 100_000,
46 max_image_pixels: 12_000_000,
47 max_symbols: 8192,
48 }
49 }
50}
51
52impl Limits {
53 pub fn validate(&self) -> Result<()> {
55 if self.io_chunk_bytes == 0 {
56 return Err(Error::invalid("I/O chunk size must be nonzero"));
57 }
58 if self.io_chunk_bytes > MAX_IO_CHUNK {
59 return Err(Error::limit(
60 "I/O chunk bytes",
61 MAX_IO_CHUNK as u64,
62 self.io_chunk_bytes as u64,
63 ));
64 }
65 self.check_allocation(self.io_chunk_bytes as u64)
66 }
67
68 pub fn check_allocation(&self, bytes: u64) -> Result<()> {
70 if bytes > self.max_allocation_bytes {
71 return Err(Error::limit(
72 "allocation bytes",
73 self.max_allocation_bytes,
74 bytes,
75 ));
76 }
77 Ok(())
78 }
79
80 pub(crate) fn allocation_refused(&self, resource: &'static str, attempted: u64) -> Error {
83 Error::limit(resource, self.max_allocation_bytes, attempted)
84 }
85
86 pub fn check_input_size(&self, bytes: u64) -> Result<()> {
88 if bytes > self.max_input_bytes {
89 return Err(Error::limit("input bytes", self.max_input_bytes, bytes));
90 }
91 Ok(())
92 }
93
94 pub fn check_pages(&self, count: u32) -> Result<()> {
96 if count > self.max_pages {
97 return Err(Error::limit(
98 "pages",
99 u64::from(self.max_pages),
100 u64::from(count),
101 ));
102 }
103 Ok(())
104 }
105
106 pub fn check_image_pixels(&self, pixels: u64) -> Result<()> {
108 if pixels > self.max_image_pixels {
109 return Err(Error::limit("image pixels", self.max_image_pixels, pixels));
110 }
111 Ok(())
112 }
113
114 pub fn check_symbols(&self, symbols: u64) -> Result<()> {
116 if symbols > u64::from(self.max_symbols) {
117 return Err(Error::limit(
118 "symbols",
119 u64::from(self.max_symbols),
120 symbols,
121 ));
122 }
123 Ok(())
124 }
125
126 pub fn check_bookmarks(&self, count: u32) -> Result<()> {
128 if count > self.max_bookmarks {
129 return Err(Error::limit(
130 "bookmarks",
131 u64::from(self.max_bookmarks),
132 u64::from(count),
133 ));
134 }
135 Ok(())
136 }
137}