modkit_odata/
problem_mapping.rs1use crate::Error;
8use crate::errors::ErrorCode;
9use modkit_errors::problem::Problem;
10
11impl From<Error> for Problem {
12 fn from(err: Error) -> Self {
13 use Error::{
14 CursorInvalidBase64, CursorInvalidDirection, CursorInvalidFields, CursorInvalidJson,
15 CursorInvalidKeys, CursorInvalidVersion, Db, FilterMismatch, InvalidCursor,
16 InvalidFilter, InvalidLimit, InvalidOrderByField, OrderMismatch, OrderWithCursor,
17 ParsingUnavailable,
18 };
19
20 match err {
21 InvalidFilter(msg) => ErrorCode::odata_errors_invalid_filter_v1()
23 .as_problem(format!("Invalid $filter: {msg}")),
24
25 InvalidOrderByField(field) => ErrorCode::odata_errors_invalid_orderby_v1()
27 .as_problem(format!("Unsupported $orderby field: {field}")),
28
29 InvalidCursor => {
31 ErrorCode::odata_errors_invalid_cursor_v1().as_problem("invalid cursor")
32 }
33
34 CursorInvalidBase64 => ErrorCode::odata_errors_invalid_cursor_v1()
35 .as_problem("invalid cursor: invalid base64url encoding"),
36
37 CursorInvalidJson => ErrorCode::odata_errors_invalid_cursor_v1()
38 .as_problem("invalid cursor: malformed JSON"),
39
40 CursorInvalidVersion => ErrorCode::odata_errors_invalid_cursor_v1()
41 .as_problem("invalid cursor: unsupported version"),
42
43 CursorInvalidKeys => ErrorCode::odata_errors_invalid_cursor_v1()
44 .as_problem("invalid cursor: empty or invalid keys"),
45
46 CursorInvalidFields => ErrorCode::odata_errors_invalid_cursor_v1()
47 .as_problem("invalid cursor: empty or invalid fields"),
48
49 CursorInvalidDirection => ErrorCode::odata_errors_invalid_cursor_v1()
50 .as_problem("invalid cursor: invalid sort direction"),
51
52 OrderMismatch => ErrorCode::odata_errors_invalid_orderby_v1()
54 .as_problem("Order mismatch between cursor and query"),
55
56 FilterMismatch => ErrorCode::odata_errors_invalid_filter_v1()
57 .as_problem("Filter mismatch between cursor and query"),
58
59 InvalidLimit => {
60 ErrorCode::odata_errors_invalid_filter_v1().as_problem("Invalid limit parameter")
61 }
62
63 OrderWithCursor => ErrorCode::odata_errors_invalid_cursor_v1()
64 .as_problem("Cannot specify both $orderby and cursor parameters"),
65
66 Db(_msg) => {
68 ErrorCode::odata_errors_internal_v1()
70 .as_problem("An internal error occurred while processing the OData query")
71 }
72
73 ParsingUnavailable(msg) => ErrorCode::odata_errors_internal_v1()
75 .as_problem(format!("OData parsing unavailable: {msg}")),
76 }
77 }
78}
79
80#[cfg(test)]
81#[cfg_attr(coverage_nightly, coverage(off))]
82mod tests {
83 use super::*;
84
85 #[test]
86 fn test_filter_error_converts_to_problem() {
87 use http::StatusCode;
88
89 let err = Error::InvalidFilter("malformed".to_owned());
90 let problem: Problem = err.into();
91
92 assert_eq!(problem.status, StatusCode::UNPROCESSABLE_ENTITY);
93 assert_eq!(problem.title, "Invalid Filter");
94 assert!(problem.detail.contains("malformed"));
95 assert!(problem.code.contains("odata"));
96 assert!(problem.code.contains("invalid_filter"));
97 }
98
99 #[test]
100 fn test_orderby_error_converts_to_problem() {
101 use http::StatusCode;
102
103 let err = Error::InvalidOrderByField("unknown".to_owned());
104 let problem: Problem = err.into();
105
106 assert_eq!(problem.status, StatusCode::UNPROCESSABLE_ENTITY);
107 assert_eq!(problem.title, "Invalid OrderBy");
108 assert!(problem.code.contains("odata"));
109 assert!(problem.code.contains("invalid_orderby"));
110 }
111
112 #[test]
113 fn test_cursor_error_converts_to_problem() {
114 use http::StatusCode;
115
116 let err = Error::CursorInvalidBase64;
117 let problem: Problem = err.into();
118
119 assert_eq!(problem.status, StatusCode::UNPROCESSABLE_ENTITY);
120 assert_eq!(problem.title, "Invalid Cursor");
121 assert!(problem.code.contains("odata"));
122 assert!(problem.code.contains("invalid_cursor"));
123 }
124}