Skip to main content

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}