1use crate::service::AwsServiceError;
6use http::StatusCode;
7
8pub fn validate_string_length(
10 field: &str,
11 value: &str,
12 min: usize,
13 max: usize,
14) -> Result<(), AwsServiceError> {
15 let len = value.len();
16 if len < min || len > max {
17 return Err(AwsServiceError::aws_error(
18 StatusCode::BAD_REQUEST,
19 "ValidationException",
20 format!(
21 "Value at '{}' failed to satisfy constraint: \
22 Member must have length between {} and {}",
23 field, min, max,
24 ),
25 ));
26 }
27 Ok(())
28}
29
30pub fn validate_range_i64(
32 field: &str,
33 value: i64,
34 min: i64,
35 max: i64,
36) -> Result<(), AwsServiceError> {
37 if value < min || value > max {
38 return Err(AwsServiceError::aws_error(
39 StatusCode::BAD_REQUEST,
40 "ValidationException",
41 format!(
42 "Value '{}' at '{}' failed to satisfy constraint: \
43 Member must have value between {} and {}",
44 value, field, min, max,
45 ),
46 ));
47 }
48 Ok(())
49}
50
51pub fn validate_enum(field: &str, value: &str, allowed: &[&str]) -> Result<(), AwsServiceError> {
53 if !allowed.contains(&value) {
54 return Err(AwsServiceError::aws_error(
55 StatusCode::BAD_REQUEST,
56 "ValidationException",
57 format!(
58 "Value '{}' at '{}' failed to satisfy constraint: \
59 Member must satisfy enum value set: [{}]",
60 value,
61 field,
62 allowed.join(", "),
63 ),
64 ));
65 }
66 Ok(())
67}
68
69pub fn validate_required(field: &str, value: &serde_json::Value) -> Result<(), AwsServiceError> {
71 if value.is_null() {
72 return Err(AwsServiceError::aws_error(
73 StatusCode::BAD_REQUEST,
74 "ValidationException",
75 format!("{} is required", field),
76 ));
77 }
78 Ok(())
79}
80
81pub fn validate_optional_string_length(
83 field: &str,
84 value: Option<&str>,
85 min: usize,
86 max: usize,
87) -> Result<(), AwsServiceError> {
88 if let Some(v) = value {
89 validate_string_length(field, v, min, max)?;
90 }
91 Ok(())
92}
93
94pub fn validate_optional_string_length_value(
101 field: &str,
102 value: &serde_json::Value,
103 min: usize,
104 max: usize,
105) -> Result<(), AwsServiceError> {
106 if value.is_null() {
107 return Ok(());
108 }
109 let s = value.as_str().ok_or_else(|| {
110 AwsServiceError::aws_error(
111 StatusCode::BAD_REQUEST,
112 "SerializationException",
113 format!("Value for '{}' must be a string", field),
114 )
115 })?;
116 validate_string_length(field, s, min, max)
117}
118
119pub fn validate_optional_range_i64(
121 field: &str,
122 value: Option<i64>,
123 min: i64,
124 max: i64,
125) -> Result<(), AwsServiceError> {
126 if let Some(v) = value {
127 validate_range_i64(field, v, min, max)?;
128 }
129 Ok(())
130}
131
132pub fn validate_optional_json_range(
138 field: &str,
139 value: &serde_json::Value,
140 min: i64,
141 max: i64,
142) -> Result<(), AwsServiceError> {
143 if value.is_null() {
144 return Ok(());
145 }
146 let n = value.as_i64().ok_or_else(|| {
147 AwsServiceError::aws_error(
148 StatusCode::BAD_REQUEST,
149 "ValidationException",
150 format!(
151 "Value at '{}' failed to satisfy constraint: \
152 Member must have value between {} and {}",
153 field, min, max,
154 ),
155 )
156 })?;
157 validate_range_i64(field, n, min, max)
158}
159
160pub fn parse_optional_i64_param(
166 field: &str,
167 value: Option<&str>,
168) -> Result<Option<i64>, AwsServiceError> {
169 match value {
170 None => Ok(None),
171 Some(s) => {
172 let n = s.parse::<i64>().map_err(|_| {
173 AwsServiceError::aws_error(
174 StatusCode::BAD_REQUEST,
175 "ValidationException",
176 format!(
177 "Value '{}' at '{}' failed to satisfy constraint: \
178 Member must be a number",
179 s, field,
180 ),
181 )
182 })?;
183 Ok(Some(n))
184 }
185 }
186}
187
188pub fn validate_optional_enum(
190 field: &str,
191 value: Option<&str>,
192 allowed: &[&str],
193) -> Result<(), AwsServiceError> {
194 if let Some(v) = value {
195 validate_enum(field, v, allowed)?;
196 }
197 Ok(())
198}
199
200pub fn validate_optional_enum_value(
205 field: &str,
206 value: &serde_json::Value,
207 allowed: &[&str],
208) -> Result<(), AwsServiceError> {
209 if value.is_null() {
210 return Ok(());
211 }
212 let s = value.as_str().ok_or_else(|| {
213 AwsServiceError::aws_error(
214 StatusCode::BAD_REQUEST,
215 "SerializationException",
216 format!("Value for '{}' must be a string", field),
217 )
218 })?;
219 validate_enum(field, s, allowed)
220}
221
222#[cfg(test)]
223mod tests {
224 use super::*;
225
226 #[test]
227 fn validate_optional_json_range_rejects_non_integer() {
228 let val = serde_json::json!("abc");
229 let result = validate_optional_json_range("limit", &val, 1, 100);
230 assert!(result.is_err());
231 }
232
233 #[test]
234 fn validate_optional_json_range_rejects_large_unsigned() {
235 let val = serde_json::json!(u64::MAX);
236 let result = validate_optional_json_range("limit", &val, 1, 1000);
237 assert!(result.is_err());
238 }
239
240 #[test]
241 fn validate_optional_json_range_allows_null() {
242 let val = serde_json::Value::Null;
243 let result = validate_optional_json_range("limit", &val, 1, 100);
244 assert!(result.is_ok());
245 }
246
247 #[test]
248 fn validate_optional_json_range_validates_range() {
249 let val = serde_json::json!(0);
250 let result = validate_optional_json_range("limit", &val, 1, 100);
251 assert!(result.is_err());
252
253 let val = serde_json::json!(50);
254 let result = validate_optional_json_range("limit", &val, 1, 100);
255 assert!(result.is_ok());
256 }
257
258 #[test]
259 fn parse_optional_i64_param_rejects_non_numeric() {
260 let result = parse_optional_i64_param("maxItems", Some("abc"));
261 assert!(result.is_err());
262 }
263
264 #[test]
265 fn parse_optional_i64_param_allows_none() {
266 let result = parse_optional_i64_param("maxItems", None);
267 assert!(result.is_ok());
268 assert_eq!(result.unwrap(), None);
269 }
270
271 #[test]
272 fn parse_optional_i64_param_parses_valid_number() {
273 let result = parse_optional_i64_param("maxItems", Some("42"));
274 assert!(result.is_ok());
275 assert_eq!(result.unwrap(), Some(42));
276 }
277}