reliakit_csv/limits.rs
1//! Resource limits applied while reading CSV.
2
3/// Bounds applied by [`read_str`](crate::read_str) to defend against
4/// adversarial input.
5///
6/// Every limit is checked while reading; exceeding one stops the read with a
7/// [`CsvErrorKind::LimitExceeded`](crate::CsvErrorKind::LimitExceeded). Build a
8/// profile with [`conservative`](Self::conservative) (the default) or
9/// [`permissive`](Self::permissive), then tune individual limits with the
10/// `with_*` methods.
11#[derive(Debug, Clone, Copy, PartialEq, Eq)]
12pub struct CsvLimits {
13 max_input_bytes: usize,
14 max_records: usize,
15 max_fields_per_record: usize,
16 max_field_bytes: usize,
17}
18
19impl CsvLimits {
20 /// Conservative limits suitable for untrusted input:
21 /// 1 MiB total, 65 536 records, 1 024 fields per record, 65 536 bytes per
22 /// field.
23 pub const fn conservative() -> Self {
24 Self {
25 max_input_bytes: 1 << 20,
26 max_records: 1 << 16,
27 max_fields_per_record: 1 << 10,
28 max_field_bytes: 1 << 16,
29 }
30 }
31
32 /// Permissive limits for trusted input where large documents are expected:
33 /// 256 MiB total, ~16.7 M records, 65 536 fields per record, 16 MiB per
34 /// field.
35 pub const fn permissive() -> Self {
36 Self {
37 max_input_bytes: 1 << 28,
38 max_records: 1 << 24,
39 max_fields_per_record: 1 << 16,
40 max_field_bytes: 1 << 24,
41 }
42 }
43
44 /// The maximum number of input bytes.
45 pub const fn max_input_bytes(&self) -> usize {
46 self.max_input_bytes
47 }
48
49 /// The maximum number of records.
50 pub const fn max_records(&self) -> usize {
51 self.max_records
52 }
53
54 /// The maximum number of fields in any one record.
55 pub const fn max_fields_per_record(&self) -> usize {
56 self.max_fields_per_record
57 }
58
59 /// The maximum number of bytes in any one field (after unescaping).
60 pub const fn max_field_bytes(&self) -> usize {
61 self.max_field_bytes
62 }
63
64 /// Returns a copy with `max_input_bytes` set.
65 pub const fn with_max_input_bytes(mut self, value: usize) -> Self {
66 self.max_input_bytes = value;
67 self
68 }
69
70 /// Returns a copy with `max_records` set.
71 pub const fn with_max_records(mut self, value: usize) -> Self {
72 self.max_records = value;
73 self
74 }
75
76 /// Returns a copy with `max_fields_per_record` set.
77 pub const fn with_max_fields_per_record(mut self, value: usize) -> Self {
78 self.max_fields_per_record = value;
79 self
80 }
81
82 /// Returns a copy with `max_field_bytes` set.
83 pub const fn with_max_field_bytes(mut self, value: usize) -> Self {
84 self.max_field_bytes = value;
85 self
86 }
87}
88
89impl Default for CsvLimits {
90 fn default() -> Self {
91 Self::conservative()
92 }
93}