1use crate::strings::alloc_c_string;
11use kglite::api::KgErrorCode;
12use std::ffi::c_char;
13
14#[repr(u32)]
20#[derive(Debug, Clone, Copy, PartialEq, Eq)]
21pub enum KgliteStatusCode {
22 Ok = 0,
23
24 CypherSyntax = 1,
26 CypherTimeout = 2,
27 CypherExecution = 3,
28 CypherTypeMismatch = 4,
29 Schema = 5,
30 Validation = 6,
31 Expr = 7,
32 NodeNotFound = 8,
33 ConnectionNotFound = 9,
34 PropertyNotFound = 10,
35 FileNotFound = 11,
36 FileFormat = 12,
37 FileIo = 13,
38 InvalidArgument = 14,
39 MissingArgument = 15,
40 Internal = 16,
41
42 InvalidUtf8 = 100,
48 NullPointer = 101,
51}
52
53impl KgliteStatusCode {
54 pub(crate) fn from_kg_error_code(code: KgErrorCode) -> Self {
58 match code {
59 KgErrorCode::CypherSyntax => Self::CypherSyntax,
60 KgErrorCode::CypherTimeout => Self::CypherTimeout,
61 KgErrorCode::CypherExecution => Self::CypherExecution,
62 KgErrorCode::CypherTypeMismatch => Self::CypherTypeMismatch,
63 KgErrorCode::Schema => Self::Schema,
64 KgErrorCode::Validation => Self::Validation,
65 KgErrorCode::Expr => Self::Expr,
66 KgErrorCode::NodeNotFound => Self::NodeNotFound,
67 KgErrorCode::ConnectionNotFound => Self::ConnectionNotFound,
68 KgErrorCode::PropertyNotFound => Self::PropertyNotFound,
69 KgErrorCode::FileNotFound => Self::FileNotFound,
70 KgErrorCode::FileFormat => Self::FileFormat,
71 KgErrorCode::FileIo => Self::FileIo,
72 KgErrorCode::InvalidArgument => Self::InvalidArgument,
73 KgErrorCode::MissingArgument => Self::MissingArgument,
74 KgErrorCode::Internal => Self::Internal,
75 }
76 }
77
78 pub(crate) fn to_kg_error_code(self) -> Option<KgErrorCode> {
83 Some(match self {
84 Self::Ok | Self::InvalidUtf8 | Self::NullPointer => return None,
85 Self::CypherSyntax => KgErrorCode::CypherSyntax,
86 Self::CypherTimeout => KgErrorCode::CypherTimeout,
87 Self::CypherExecution => KgErrorCode::CypherExecution,
88 Self::CypherTypeMismatch => KgErrorCode::CypherTypeMismatch,
89 Self::Schema => KgErrorCode::Schema,
90 Self::Validation => KgErrorCode::Validation,
91 Self::Expr => KgErrorCode::Expr,
92 Self::NodeNotFound => KgErrorCode::NodeNotFound,
93 Self::ConnectionNotFound => KgErrorCode::ConnectionNotFound,
94 Self::PropertyNotFound => KgErrorCode::PropertyNotFound,
95 Self::FileNotFound => KgErrorCode::FileNotFound,
96 Self::FileFormat => KgErrorCode::FileFormat,
97 Self::FileIo => KgErrorCode::FileIo,
98 Self::InvalidArgument => KgErrorCode::InvalidArgument,
99 Self::MissingArgument => KgErrorCode::MissingArgument,
100 Self::Internal => KgErrorCode::Internal,
101 })
102 }
103}
104
105#[no_mangle]
112pub extern "C" fn kglite_status_code_name(code: KgliteStatusCode) -> *const c_char {
113 let s = match code {
114 KgliteStatusCode::Ok => return std::ptr::null(),
115 KgliteStatusCode::InvalidUtf8 => "InvalidUtf8",
116 KgliteStatusCode::NullPointer => "NullPointer",
117 other => match other.to_kg_error_code() {
118 Some(kg) => kg.as_str(),
119 None => return std::ptr::null(),
120 },
121 };
122 alloc_c_string(s)
123}
124
125#[no_mangle]
135pub extern "C" fn kglite_status_code_neo4j_status(code: KgliteStatusCode) -> *const c_char {
136 match code.to_kg_error_code() {
137 Some(kg) => alloc_c_string(kg.neo4j_status_code()),
138 None => std::ptr::null(),
139 }
140}
141
142#[no_mangle]
149pub extern "C" fn kglite_status_code_http_status(code: KgliteStatusCode) -> u16 {
150 match code {
151 KgliteStatusCode::Ok => 0,
152 KgliteStatusCode::InvalidUtf8 | KgliteStatusCode::NullPointer => 400,
153 other => match other.to_kg_error_code() {
154 Some(kg) => kg.http_status_code(),
155 None => 500,
156 },
157 }
158}
159
160#[cfg(test)]
161mod tests {
162 use super::*;
163
164 #[test]
165 fn every_kg_error_code_round_trips() {
166 for code in [
169 KgErrorCode::CypherSyntax,
170 KgErrorCode::CypherTimeout,
171 KgErrorCode::CypherExecution,
172 KgErrorCode::CypherTypeMismatch,
173 KgErrorCode::Schema,
174 KgErrorCode::Validation,
175 KgErrorCode::Expr,
176 KgErrorCode::NodeNotFound,
177 KgErrorCode::ConnectionNotFound,
178 KgErrorCode::PropertyNotFound,
179 KgErrorCode::FileNotFound,
180 KgErrorCode::FileFormat,
181 KgErrorCode::FileIo,
182 KgErrorCode::InvalidArgument,
183 KgErrorCode::MissingArgument,
184 KgErrorCode::Internal,
185 ] {
186 let c = KgliteStatusCode::from_kg_error_code(code);
187 let back = c.to_kg_error_code();
188 assert_eq!(back, Some(code), "round-trip failed for {code:?}");
189 }
190 }
191
192 #[test]
193 fn http_status_helpers_match_core() {
194 assert_eq!(
196 kglite_status_code_http_status(KgliteStatusCode::CypherSyntax),
197 400
198 );
199 assert_eq!(
200 kglite_status_code_http_status(KgliteStatusCode::NodeNotFound),
201 404
202 );
203 assert_eq!(
204 kglite_status_code_http_status(KgliteStatusCode::Internal),
205 500
206 );
207 assert_eq!(kglite_status_code_http_status(KgliteStatusCode::Ok), 0);
208 }
209}