1use crate::Error;
10
11#[derive(Debug, Clone)]
13#[must_use]
14pub struct ODataLimits {
15 pub max_top: usize,
17 pub max_orderby_fields: usize,
19 pub max_filter_length: usize,
21 pub require_signed_cursors: bool,
23 pub cursor_hmac_key: Option<Vec<u8>>,
25}
26
27impl Default for ODataLimits {
28 fn default() -> Self {
29 Self {
30 max_top: 1000,
31 max_orderby_fields: 5,
32 max_filter_length: 2000,
33 require_signed_cursors: false,
34 cursor_hmac_key: None,
35 }
36 }
37}
38
39impl ODataLimits {
40 pub fn new() -> Self {
42 Self::default()
43 }
44
45 pub fn with_max_top(mut self, max_top: usize) -> Self {
47 self.max_top = max_top;
48 self
49 }
50
51 pub fn with_max_orderby_fields(mut self, max: usize) -> Self {
53 self.max_orderby_fields = max;
54 self
55 }
56
57 pub fn with_max_filter_length(mut self, max: usize) -> Self {
59 self.max_filter_length = max;
60 self
61 }
62
63 pub fn with_signed_cursors(mut self, key: Vec<u8>) -> Self {
65 self.require_signed_cursors = true;
66 self.cursor_hmac_key = Some(key);
67 self
68 }
69
70 pub fn validate_top(&self, top: usize) -> Result<(), Error> {
75 if top > self.max_top {
76 return Err(Error::InvalidLimit);
77 }
78 Ok(())
79 }
80
81 pub fn validate_filter(&self, filter: &str) -> Result<(), Error> {
86 if filter.len() > self.max_filter_length {
87 return Err(Error::InvalidFilter(format!(
88 "Filter expression exceeds maximum length of {} characters",
89 self.max_filter_length
90 )));
91 }
92 Ok(())
93 }
94
95 pub fn validate_orderby_count(&self, count: usize) -> Result<(), Error> {
100 if count > self.max_orderby_fields {
101 return Err(Error::InvalidOrderByField(format!(
102 "Too many orderby fields (max: {})",
103 self.max_orderby_fields
104 )));
105 }
106 Ok(())
107 }
108}
109
110#[cfg(test)]
111#[cfg_attr(coverage_nightly, coverage(off))]
112mod tests {
113 use super::*;
114
115 #[test]
116 fn test_default_limits() {
117 let limits = ODataLimits::default();
118 assert_eq!(limits.max_top, 1000);
119 assert_eq!(limits.max_orderby_fields, 5);
120 assert_eq!(limits.max_filter_length, 2000);
121 assert!(!limits.require_signed_cursors);
122 }
123
124 #[test]
125 fn test_validate_top_ok() {
126 let limits = ODataLimits::default();
127 assert!(limits.validate_top(500).is_ok());
128 assert!(limits.validate_top(1000).is_ok());
129 }
130
131 #[test]
132 fn test_validate_top_exceeds() {
133 let limits = ODataLimits::default();
134 assert!(limits.validate_top(1001).is_err());
135 }
136
137 #[test]
138 fn test_validate_filter_ok() {
139 let limits = ODataLimits::default();
140 assert!(limits.validate_filter("name eq 'John'").is_ok());
141 }
142
143 #[test]
144 fn test_validate_filter_too_long() {
145 let limits = ODataLimits::default();
146 let long_filter = "x".repeat(2001);
147 assert!(limits.validate_filter(&long_filter).is_err());
148 }
149
150 #[test]
151 fn test_validate_orderby_count_ok() {
152 let limits = ODataLimits::default();
153 assert!(limits.validate_orderby_count(3).is_ok());
154 assert!(limits.validate_orderby_count(5).is_ok());
155 }
156
157 #[test]
158 fn test_validate_orderby_count_exceeds() {
159 let limits = ODataLimits::default();
160 assert!(limits.validate_orderby_count(6).is_err());
161 }
162
163 #[test]
164 fn test_custom_limits() {
165 let limits = ODataLimits::new()
166 .with_max_top(100)
167 .with_max_orderby_fields(3)
168 .with_max_filter_length(500);
169
170 assert_eq!(limits.max_top, 100);
171 assert_eq!(limits.max_orderby_fields, 3);
172 assert_eq!(limits.max_filter_length, 500);
173 }
174}