Skip to main content

nwep/
error.rs

1use crate::ffi;
2use std::ffi::CStr;
3use std::fmt;
4
5/// `ERR_CONFIG_FILE_NOT_FOUND` indicates the specified configuration file does
6/// not exist on disk.
7pub const ERR_CONFIG_FILE_NOT_FOUND: i32 = ffi::NWEP_ERR_CONFIG_FILE_NOT_FOUND;
8
9/// `ERR_CONFIG_PARSE_ERROR` indicates the configuration file exists but could
10/// not be parsed (e.g., malformed syntax).
11pub const ERR_CONFIG_PARSE_ERROR: i32 = ffi::NWEP_ERR_CONFIG_PARSE_ERROR;
12
13/// `ERR_CONFIG_INVALID_VALUE` indicates a configuration key was present but its
14/// value failed validation (e.g., out-of-range integer, invalid address).
15pub const ERR_CONFIG_INVALID_VALUE: i32 = ffi::NWEP_ERR_CONFIG_INVALID_VALUE;
16
17/// `ERR_CONFIG_MISSING_REQUIRED` indicates a required configuration key was
18/// absent from the configuration file or builder.
19pub const ERR_CONFIG_MISSING_REQUIRED: i32 = ffi::NWEP_ERR_CONFIG_MISSING_REQUIRED;
20
21/// `ERR_CONFIG_VALIDATION_FAILED` indicates the configuration passed individual
22/// field checks but failed cross-field or semantic validation.
23pub const ERR_CONFIG_VALIDATION_FAILED: i32 = ffi::NWEP_ERR_CONFIG_VALIDATION_FAILED;
24
25/// `ERR_NETWORK_CONN_FAILED` indicates that a QUIC connection attempt to the
26/// remote peer was rejected or could not be established.
27pub const ERR_NETWORK_CONN_FAILED: i32 = ffi::NWEP_ERR_NETWORK_CONN_FAILED;
28
29/// `ERR_NETWORK_CONN_CLOSED` indicates the remote peer closed the connection
30/// unexpectedly.
31pub const ERR_NETWORK_CONN_CLOSED: i32 = ffi::NWEP_ERR_NETWORK_CONN_CLOSED;
32
33/// `ERR_NETWORK_TIMEOUT` indicates an operation did not complete within the
34/// configured deadline.
35pub const ERR_NETWORK_TIMEOUT: i32 = ffi::NWEP_ERR_NETWORK_TIMEOUT;
36
37/// `ERR_NETWORK_ADDR_IN_USE` indicates the requested local address/port was
38/// already bound by another socket.
39pub const ERR_NETWORK_ADDR_IN_USE: i32 = ffi::NWEP_ERR_NETWORK_ADDR_IN_USE;
40
41/// `ERR_NETWORK_ADDR_INVALID` indicates the supplied address string or
42/// `sockaddr` could not be parsed or is structurally invalid.
43pub const ERR_NETWORK_ADDR_INVALID: i32 = ffi::NWEP_ERR_NETWORK_ADDR_INVALID;
44
45/// `ERR_NETWORK_SOCKET` indicates a low-level socket operation (bind, listen,
46/// send, recv) returned an OS error.
47pub const ERR_NETWORK_SOCKET: i32 = ffi::NWEP_ERR_NETWORK_SOCKET;
48
49/// `ERR_NETWORK_TLS` indicates a TLS-level error occurred during or after the
50/// QUIC handshake (certificate validation, alert, etc.).
51pub const ERR_NETWORK_TLS: i32 = ffi::NWEP_ERR_NETWORK_TLS;
52
53/// `ERR_NETWORK_QUIC` indicates a QUIC transport error that is not otherwise
54/// classified (stream reset, connection error frame, etc.).
55pub const ERR_NETWORK_QUIC: i32 = ffi::NWEP_ERR_NETWORK_QUIC;
56
57/// `ERR_NETWORK_NO_SERVERS` indicates a client pool operation found no healthy
58/// server endpoints available to connect to.
59pub const ERR_NETWORK_NO_SERVERS: i32 = ffi::NWEP_ERR_NETWORK_NO_SERVERS;
60
61/// `ERR_CRYPTO_KEY_GEN_FAILED` indicates Ed25519 or BLS key generation failed,
62/// typically due to an internal OpenSSL error.
63pub const ERR_CRYPTO_KEY_GEN_FAILED: i32 = ffi::NWEP_ERR_CRYPTO_KEY_GEN_FAILED;
64
65/// `ERR_CRYPTO_SIGN_FAILED` indicates a signing operation over a message or
66/// transcript failed.
67pub const ERR_CRYPTO_SIGN_FAILED: i32 = ffi::NWEP_ERR_CRYPTO_SIGN_FAILED;
68
69/// `ERR_CRYPTO_VERIFY_FAILED` indicates a signature verification failed because
70/// the signature did not match the message or public key.
71pub const ERR_CRYPTO_VERIFY_FAILED: i32 = ffi::NWEP_ERR_CRYPTO_VERIFY_FAILED;
72
73/// `ERR_CRYPTO_HASH_FAILED` indicates a cryptographic hash operation (SHA-256,
74/// etc.) returned an internal error.
75pub const ERR_CRYPTO_HASH_FAILED: i32 = ffi::NWEP_ERR_CRYPTO_HASH_FAILED;
76
77/// `ERR_CRYPTO_INVALID_KEY` indicates a key structure is malformed, zero, or
78/// otherwise unusable.
79pub const ERR_CRYPTO_INVALID_KEY: i32 = ffi::NWEP_ERR_CRYPTO_INVALID_KEY;
80
81/// `ERR_CRYPTO_INVALID_SIG` indicates a signature byte sequence is structurally
82/// invalid (wrong length, bad encoding) before verification is even attempted.
83pub const ERR_CRYPTO_INVALID_SIG: i32 = ffi::NWEP_ERR_CRYPTO_INVALID_SIG;
84
85/// `ERR_CRYPTO_CERT_ERROR` indicates a TLS certificate operation failed (e.g.,
86/// self-signed certificate generation or DER encoding error).
87pub const ERR_CRYPTO_CERT_ERROR: i32 = ffi::NWEP_ERR_CRYPTO_CERT_ERROR;
88
89/// `ERR_CRYPTO_PUBKEY_MISMATCH` indicates the public key presented by a peer
90/// does not match the expected or stored public key.
91pub const ERR_CRYPTO_PUBKEY_MISMATCH: i32 = ffi::NWEP_ERR_CRYPTO_PUBKEY_MISMATCH;
92
93/// `ERR_CRYPTO_NODEID_MISMATCH` indicates the node ID derived from a presented
94/// public key does not match the expected node ID.
95pub const ERR_CRYPTO_NODEID_MISMATCH: i32 = ffi::NWEP_ERR_CRYPTO_NODEID_MISMATCH;
96
97/// `ERR_CRYPTO_CHALLENGE_FAILED` indicates a challenge-response authentication
98/// exchange did not produce a valid response.
99pub const ERR_CRYPTO_CHALLENGE_FAILED: i32 = ffi::NWEP_ERR_CRYPTO_CHALLENGE_FAILED;
100
101/// `ERR_CRYPTO_SERVER_SIG_INVALID` indicates the handshake transcript signature
102/// provided by the server failed verification on the client side.
103pub const ERR_CRYPTO_SERVER_SIG_INVALID: i32 = ffi::NWEP_ERR_CRYPTO_SERVER_SIG_INVALID;
104
105/// `ERR_CRYPTO_CLIENT_SIG_INVALID` indicates the handshake transcript signature
106/// provided by the client failed verification on the server side.
107pub const ERR_CRYPTO_CLIENT_SIG_INVALID: i32 = ffi::NWEP_ERR_CRYPTO_CLIENT_SIG_INVALID;
108
109/// `ERR_CRYPTO_AUTH_TIMEOUT` indicates the mutual authentication handshake did
110/// not complete within the required time window.
111pub const ERR_CRYPTO_AUTH_TIMEOUT: i32 = ffi::NWEP_ERR_CRYPTO_AUTH_TIMEOUT;
112
113/// `ERR_PROTO_INVALID_MESSAGE` indicates a received frame could not be decoded
114/// as a valid NWEP message.
115pub const ERR_PROTO_INVALID_MESSAGE: i32 = ffi::NWEP_ERR_PROTO_INVALID_MESSAGE;
116
117/// `ERR_PROTO_INVALID_METHOD` indicates the `:method` header contains a string
118/// that is not a recognized NWEP method name.
119pub const ERR_PROTO_INVALID_METHOD: i32 = ffi::NWEP_ERR_PROTO_INVALID_METHOD;
120
121/// `ERR_PROTO_INVALID_HEADER` indicates a header name or value fails structural
122/// validation (e.g., contains a NUL byte, exceeds size limits).
123pub const ERR_PROTO_INVALID_HEADER: i32 = ffi::NWEP_ERR_PROTO_INVALID_HEADER;
124
125/// `ERR_PROTO_MSG_TOO_LARGE` indicates a message body exceeds the negotiated
126/// `max-message-size` for the connection.
127pub const ERR_PROTO_MSG_TOO_LARGE: i32 = ffi::NWEP_ERR_PROTO_MSG_TOO_LARGE;
128
129/// `ERR_PROTO_STREAM_ERROR` indicates a QUIC stream was reset or encountered an
130/// error during a protocol-level read or write.
131pub const ERR_PROTO_STREAM_ERROR: i32 = ffi::NWEP_ERR_PROTO_STREAM_ERROR;
132
133/// `ERR_PROTO_INVALID_STATUS` indicates the `:status` header contains a string
134/// that is not a recognized NWEP status code.
135pub const ERR_PROTO_INVALID_STATUS: i32 = ffi::NWEP_ERR_PROTO_INVALID_STATUS;
136
137/// `ERR_PROTO_CONNECT_REQUIRED` indicates an operation was attempted before the
138/// `connect` handshake completed on the connection.
139pub const ERR_PROTO_CONNECT_REQUIRED: i32 = ffi::NWEP_ERR_PROTO_CONNECT_REQUIRED;
140
141/// `ERR_PROTO_TOO_MANY_HEADERS` indicates a message contains more headers than
142/// the [`crate::types::MAX_HEADERS`] limit allows.
143pub const ERR_PROTO_TOO_MANY_HEADERS: i32 = ffi::NWEP_ERR_PROTO_TOO_MANY_HEADERS;
144
145/// `ERR_PROTO_HEADER_TOO_LARGE` indicates a single header name or value exceeds
146/// the [`crate::types::MAX_HEADER_SIZE`] byte limit.
147pub const ERR_PROTO_HEADER_TOO_LARGE: i32 = ffi::NWEP_ERR_PROTO_HEADER_TOO_LARGE;
148
149/// `ERR_PROTO_0RTT_REJECTED` indicates the server rejected the client's attempt
150/// to send data in QUIC 0-RTT (early data), requiring a retry on a fresh
151/// connection.
152pub const ERR_PROTO_0RTT_REJECTED: i32 = ffi::NWEP_ERR_PROTO_0RTT_REJECTED;
153
154/// `ERR_PROTO_MISSING_HEADER` indicates a required pseudo-header (`:method`,
155/// `:path`, `:status`, etc.) was absent from the message.
156pub const ERR_PROTO_MISSING_HEADER: i32 = ffi::NWEP_ERR_PROTO_MISSING_HEADER;
157
158/// `ERR_PROTO_ROLE_MISMATCH` indicates an operation was routed to a server
159/// whose role does not handle the requested path or method.
160pub const ERR_PROTO_ROLE_MISMATCH: i32 = ffi::NWEP_ERR_PROTO_ROLE_MISMATCH;
161
162/// `ERR_PROTO_UNAUTHORIZED` indicates the authenticated client identity is not
163/// permitted to perform the requested operation.
164pub const ERR_PROTO_UNAUTHORIZED: i32 = ffi::NWEP_ERR_PROTO_UNAUTHORIZED;
165
166/// `ERR_PROTO_PATH_NOT_FOUND` indicates no handler was registered for the
167/// requested `:path`.
168pub const ERR_PROTO_PATH_NOT_FOUND: i32 = ffi::NWEP_ERR_PROTO_PATH_NOT_FOUND;
169
170/// `ERR_PROTO_VERSION_MISMATCH` indicates the `:version` presented by the
171/// remote peer is incompatible with this implementation.
172pub const ERR_PROTO_VERSION_MISMATCH: i32 = ffi::NWEP_ERR_PROTO_VERSION_MISMATCH;
173
174/// `ERR_IDENTITY_INVALID_NODEID` indicates a node ID byte sequence is
175/// structurally invalid (wrong length, all-zero, etc.).
176pub const ERR_IDENTITY_INVALID_NODEID: i32 = ffi::NWEP_ERR_IDENTITY_INVALID_NODEID;
177
178/// `ERR_IDENTITY_INVALID_ADDR` indicates a network address associated with an
179/// identity record could not be parsed or is invalid.
180pub const ERR_IDENTITY_INVALID_ADDR: i32 = ffi::NWEP_ERR_IDENTITY_INVALID_ADDR;
181
182/// `ERR_IDENTITY_AUTH_FAILED` indicates the identity authentication exchange
183/// (challenge/response) did not succeed.
184pub const ERR_IDENTITY_AUTH_FAILED: i32 = ffi::NWEP_ERR_IDENTITY_AUTH_FAILED;
185
186/// `ERR_IDENTITY_CHALLENGE_EXPIRED` indicates the challenge nonce is no longer
187/// valid because its time window has passed.
188pub const ERR_IDENTITY_CHALLENGE_EXPIRED: i32 = ffi::NWEP_ERR_IDENTITY_CHALLENGE_EXPIRED;
189
190/// `ERR_IDENTITY_NO_RECOVERY` indicates no recovery shares are stored for this
191/// identity, making key recovery impossible.
192pub const ERR_IDENTITY_NO_RECOVERY: i32 = ffi::NWEP_ERR_IDENTITY_NO_RECOVERY;
193
194/// `ERR_IDENTITY_RECOVERY_MISMATCH` indicates the shares provided for recovery
195/// reconstruct a key that does not match the stored public key.
196pub const ERR_IDENTITY_RECOVERY_MISMATCH: i32 = ffi::NWEP_ERR_IDENTITY_RECOVERY_MISMATCH;
197
198/// `ERR_IDENTITY_INVALID_SHARE` indicates a Shamir secret-sharing share is
199/// malformed or has an invalid index.
200pub const ERR_IDENTITY_INVALID_SHARE: i32 = ffi::NWEP_ERR_IDENTITY_INVALID_SHARE;
201
202/// `ERR_IDENTITY_SHARE_COMBINE` indicates the Shamir share combination step
203/// failed, likely due to insufficient or inconsistent shares.
204pub const ERR_IDENTITY_SHARE_COMBINE: i32 = ffi::NWEP_ERR_IDENTITY_SHARE_COMBINE;
205
206/// `ERR_IDENTITY_INVALID_THRESHOLD` indicates a Shamir threshold value is
207/// outside the allowed range (must be between 2 and the share count).
208pub const ERR_IDENTITY_INVALID_THRESHOLD: i32 = ffi::NWEP_ERR_IDENTITY_INVALID_THRESHOLD;
209
210/// `ERR_IDENTITY_ROTATION_IN_PROGRESS` indicates a key rotation is already
211/// underway for this identity; concurrent rotations are not permitted.
212pub const ERR_IDENTITY_ROTATION_IN_PROGRESS: i32 = ffi::NWEP_ERR_IDENTITY_ROTATION_IN_PROGRESS;
213
214/// `ERR_IDENTITY_KEY_MISMATCH` indicates the presented signing key does not
215/// match the key recorded in the identity log for this node.
216pub const ERR_IDENTITY_KEY_MISMATCH: i32 = ffi::NWEP_ERR_IDENTITY_KEY_MISMATCH;
217
218/// `ERR_IDENTITY_REVOKED` indicates the identity has been explicitly revoked
219/// and may no longer authenticate.
220pub const ERR_IDENTITY_REVOKED: i32 = ffi::NWEP_ERR_IDENTITY_REVOKED;
221
222/// `ERR_STORAGE_FILE_NOT_FOUND` indicates a required data file or directory
223/// does not exist at the expected path.
224pub const ERR_STORAGE_FILE_NOT_FOUND: i32 = ffi::NWEP_ERR_STORAGE_FILE_NOT_FOUND;
225
226/// `ERR_STORAGE_READ_ERROR` indicates an I/O error occurred while reading from
227/// storage.
228pub const ERR_STORAGE_READ_ERROR: i32 = ffi::NWEP_ERR_STORAGE_READ_ERROR;
229
230/// `ERR_STORAGE_WRITE_ERROR` indicates an I/O error occurred while writing to
231/// storage.
232pub const ERR_STORAGE_WRITE_ERROR: i32 = ffi::NWEP_ERR_STORAGE_WRITE_ERROR;
233
234/// `ERR_STORAGE_PERMISSION` indicates a file system permission error prevented
235/// reading or writing the target path.
236pub const ERR_STORAGE_PERMISSION: i32 = ffi::NWEP_ERR_STORAGE_PERMISSION;
237
238/// `ERR_STORAGE_DISK_FULL` indicates there is insufficient disk space to
239/// complete a write operation.
240pub const ERR_STORAGE_DISK_FULL: i32 = ffi::NWEP_ERR_STORAGE_DISK_FULL;
241
242/// `ERR_STORAGE_KEY_NOT_FOUND` indicates a lookup by key returned no matching
243/// record in the storage backend.
244pub const ERR_STORAGE_KEY_NOT_FOUND: i32 = ffi::NWEP_ERR_STORAGE_KEY_NOT_FOUND;
245
246/// `ERR_STORAGE_INDEX_OUT_OF_RANGE` indicates a numeric index (e.g., log entry
247/// sequence number) is beyond the bounds of the stored data.
248pub const ERR_STORAGE_INDEX_OUT_OF_RANGE: i32 = ffi::NWEP_ERR_STORAGE_INDEX_OUT_OF_RANGE;
249
250/// `ERR_STORAGE_CORRUPTED` indicates stored data failed integrity verification
251/// (bad checksum, truncated file, etc.).
252pub const ERR_STORAGE_CORRUPTED: i32 = ffi::NWEP_ERR_STORAGE_CORRUPTED;
253
254/// `ERR_TRUST_PARSE_ERROR` indicates a trust log entry or checkpoint document
255/// could not be decoded from its serialized form.
256pub const ERR_TRUST_PARSE_ERROR: i32 = ffi::NWEP_ERR_TRUST_PARSE_ERROR;
257
258/// `ERR_TRUST_INVALID_ENTRY` indicates a trust log entry is structurally valid
259/// but semantically incorrect (e.g., invalid field combination).
260pub const ERR_TRUST_INVALID_ENTRY: i32 = ffi::NWEP_ERR_TRUST_INVALID_ENTRY;
261
262/// `ERR_TRUST_INVALID_SIG` indicates a trust log entry or checkpoint carries a
263/// signature that fails cryptographic verification.
264pub const ERR_TRUST_INVALID_SIG: i32 = ffi::NWEP_ERR_TRUST_INVALID_SIG;
265
266/// `ERR_TRUST_QUORUM_NOT_REACHED` indicates that an operation requiring a BLS
267/// threshold quorum did not collect enough valid signatures.
268pub const ERR_TRUST_QUORUM_NOT_REACHED: i32 = ffi::NWEP_ERR_TRUST_QUORUM_NOT_REACHED;
269
270/// `ERR_TRUST_INVALID_PROOF` indicates a Merkle inclusion proof presented for a
271/// log entry is structurally invalid or does not verify against the root.
272pub const ERR_TRUST_INVALID_PROOF: i32 = ffi::NWEP_ERR_TRUST_INVALID_PROOF;
273
274/// `ERR_TRUST_ENTRY_NOT_FOUND` indicates the requested log entry does not exist
275/// in the local or remote trust log.
276pub const ERR_TRUST_ENTRY_NOT_FOUND: i32 = ffi::NWEP_ERR_TRUST_ENTRY_NOT_FOUND;
277
278/// `ERR_TRUST_CHECKPOINT_STALE` indicates a checkpoint's sequence number is
279/// older than the current local state, making it unsafe to apply.
280pub const ERR_TRUST_CHECKPOINT_STALE: i32 = ffi::NWEP_ERR_TRUST_CHECKPOINT_STALE;
281
282/// `ERR_TRUST_ANCHOR_UNKNOWN` indicates a checkpoint or proof references an
283/// anchor node ID that is not recognized in the local anchor set.
284pub const ERR_TRUST_ANCHOR_UNKNOWN: i32 = ffi::NWEP_ERR_TRUST_ANCHOR_UNKNOWN;
285
286/// `ERR_TRUST_DUPLICATE_BINDING` indicates an attempt to register a public-key
287/// binding that already exists in the trust log.
288pub const ERR_TRUST_DUPLICATE_BINDING: i32 = ffi::NWEP_ERR_TRUST_DUPLICATE_BINDING;
289
290/// `ERR_TRUST_NODE_NOT_FOUND` indicates a node ID lookup in the trust log
291/// returned no matching entry.
292pub const ERR_TRUST_NODE_NOT_FOUND: i32 = ffi::NWEP_ERR_TRUST_NODE_NOT_FOUND;
293
294/// `ERR_TRUST_ALREADY_REVOKED` indicates an attempt to revoke a node that has
295/// already been revoked.
296pub const ERR_TRUST_ALREADY_REVOKED: i32 = ffi::NWEP_ERR_TRUST_ALREADY_REVOKED;
297
298/// `ERR_TRUST_INVALID_AUTH` indicates the authorization proof accompanying a
299/// trust operation (e.g., key rotation) failed verification.
300pub const ERR_TRUST_INVALID_AUTH: i32 = ffi::NWEP_ERR_TRUST_INVALID_AUTH;
301
302/// `ERR_TRUST_UNAUTHORIZED` indicates the requesting node is not authorized to
303/// perform the trust operation (e.g., insufficient role).
304pub const ERR_TRUST_UNAUTHORIZED: i32 = ffi::NWEP_ERR_TRUST_UNAUTHORIZED;
305
306/// `ERR_TRUST_TYPE_NOT_ALLOWED` indicates the requested trust entry type is not
307/// permitted in the current context (e.g., anchor-only operations on a regular
308/// server).
309pub const ERR_TRUST_TYPE_NOT_ALLOWED: i32 = ffi::NWEP_ERR_TRUST_TYPE_NOT_ALLOWED;
310
311/// `ERR_TRUST_KEY_MISMATCH` indicates the signing key in a trust log entry does
312/// not match the key previously recorded for that node.
313pub const ERR_TRUST_KEY_MISMATCH: i32 = ffi::NWEP_ERR_TRUST_KEY_MISMATCH;
314
315/// `ERR_TRUST_STORAGE` indicates a storage-layer error occurred while reading
316/// or writing the trust log, wrapping a lower-level `ERR_STORAGE_*` condition.
317pub const ERR_TRUST_STORAGE: i32 = ffi::NWEP_ERR_TRUST_STORAGE;
318
319/// `ERR_TRUST_LOG_CORRUPTED` indicates the trust log's internal consistency
320/// check failed (e.g., broken hash chain or Merkle tree mismatch).
321pub const ERR_TRUST_LOG_CORRUPTED: i32 = ffi::NWEP_ERR_TRUST_LOG_CORRUPTED;
322
323/// `ERR_TRUST_EQUIVOCATION` indicates two conflicting entries were detected for
324/// the same log position, which is evidence of a double-signing attack.
325pub const ERR_TRUST_EQUIVOCATION: i32 = ffi::NWEP_ERR_TRUST_EQUIVOCATION;
326
327/// `ERR_INTERNAL_UNKNOWN` indicates an unexpected internal error with no more
328/// specific classification.
329pub const ERR_INTERNAL_UNKNOWN: i32 = ffi::NWEP_ERR_INTERNAL_UNKNOWN;
330
331/// `ERR_INTERNAL_NOT_IMPLEMENTED` indicates an operation or code path is not
332/// yet implemented in the current build of the library.
333pub const ERR_INTERNAL_NOT_IMPLEMENTED: i32 = ffi::NWEP_ERR_INTERNAL_NOT_IMPLEMENTED;
334
335/// `ERR_INTERNAL_INVALID_STATE` indicates the library's internal state machine
336/// reached an unexpected or inconsistent state.
337pub const ERR_INTERNAL_INVALID_STATE: i32 = ffi::NWEP_ERR_INTERNAL_INVALID_STATE;
338
339/// `ERR_INTERNAL_NULL_PTR` indicates the library received or produced a null
340/// pointer where a valid pointer was required.
341pub const ERR_INTERNAL_NULL_PTR: i32 = ffi::NWEP_ERR_INTERNAL_NULL_PTR;
342
343/// `ERR_INTERNAL_NOMEM` indicates a dynamic memory allocation failed inside the
344/// C library.
345pub const ERR_INTERNAL_NOMEM: i32 = ffi::NWEP_ERR_INTERNAL_NOMEM;
346
347/// `ERR_INTERNAL_INVALID_ARG` indicates a function was called with an argument
348/// value that the C library considers invalid.
349pub const ERR_INTERNAL_INVALID_ARG: i32 = ffi::NWEP_ERR_INTERNAL_INVALID_ARG;
350
351/// `ERR_INTERNAL_CALLBACK_FAILURE` indicates a user-supplied callback returned
352/// an error or panicked in a context where the library cannot propagate it.
353pub const ERR_INTERNAL_CALLBACK_FAILURE: i32 = ffi::NWEP_ERR_INTERNAL_CALLBACK_FAILURE;
354
355/// `ERR_INTERNAL_NOBUF` indicates an internal buffer is too small to hold the
356/// produced output (the operation should be retried with a larger buffer).
357pub const ERR_INTERNAL_NOBUF: i32 = ffi::NWEP_ERR_INTERNAL_NOBUF;
358
359/// `ErrorCategory` classifies an [`Error`] into the NWEP subsystem that
360/// produced it.
361///
362/// Each variant corresponds to a group of error codes sharing the same
363/// `NWEP_ERR_CAT_*` C constant. The category is determined automatically when
364/// constructing an [`Error`] via [`Error::from_code`].
365///
366/// The `Display` implementation produces the lowercase subsystem name (e.g.,
367/// `"network"`, `"crypto"`) which is suitable for logging and structured
368/// output.
369#[derive(Debug, Clone, PartialEq, Eq)]
370pub enum ErrorCategory {
371    /// `None` indicates no error (code zero) or an unrecognized category.
372    None,
373    /// `Config` groups errors related to configuration file parsing and
374    /// validation.
375    Config,
376    /// `Network` groups errors related to QUIC/UDP transport and socket
377    /// operations.
378    Network,
379    /// `Crypto` groups errors related to key generation, signing, verification,
380    /// and TLS certificate handling.
381    Crypto,
382    /// `Protocol` groups errors related to the NWEP application-layer protocol
383    /// framing, headers, and method/status validation.
384    Protocol,
385    /// `Identity` groups errors related to node identity records, challenge
386    /// authentication, and Shamir secret sharing.
387    Identity,
388    /// `Storage` groups errors related to file I/O, key-value lookups, and
389    /// data integrity.
390    Storage,
391    /// `Trust` groups errors related to the distributed trust log, Merkle
392    /// proofs, BLS checkpoints, and equivocation detection.
393    Trust,
394    /// `Internal` groups errors that indicate bugs or unimplemented code paths
395    /// inside the C library itself.
396    Internal,
397}
398
399impl fmt::Display for ErrorCategory {
400    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
401        let s = match self {
402            ErrorCategory::None => "none",
403            ErrorCategory::Config => "config",
404            ErrorCategory::Network => "network",
405            ErrorCategory::Crypto => "crypto",
406            ErrorCategory::Protocol => "protocol",
407            ErrorCategory::Identity => "identity",
408            ErrorCategory::Storage => "storage",
409            ErrorCategory::Trust => "trust",
410            ErrorCategory::Internal => "internal",
411        };
412        f.write_str(s)
413    }
414}
415
416/// Converts a raw FFI `nwep_error_category` discriminant into the Rust
417/// [`ErrorCategory`] enum. Unknown discriminants map to [`ErrorCategory::None`].
418fn category_from_ffi(cat: ffi::nwep_error_category) -> ErrorCategory {
419    match cat {
420        ffi::nwep_error_category_NWEP_ERR_CAT_CONFIG => ErrorCategory::Config,
421        ffi::nwep_error_category_NWEP_ERR_CAT_NETWORK => ErrorCategory::Network,
422        ffi::nwep_error_category_NWEP_ERR_CAT_CRYPTO => ErrorCategory::Crypto,
423        ffi::nwep_error_category_NWEP_ERR_CAT_PROTOCOL => ErrorCategory::Protocol,
424        ffi::nwep_error_category_NWEP_ERR_CAT_IDENTITY => ErrorCategory::Identity,
425        ffi::nwep_error_category_NWEP_ERR_CAT_STORAGE => ErrorCategory::Storage,
426        ffi::nwep_error_category_NWEP_ERR_CAT_TRUST => ErrorCategory::Trust,
427        ffi::nwep_error_category_NWEP_ERR_CAT_INTERNAL => ErrorCategory::Internal,
428        _ => ErrorCategory::None,
429    }
430}
431
432/// `Error` is the main error type returned by fallible NWEP operations.
433///
434/// An `Error` is constructed from a non-zero integer error code returned by the
435/// C library. The constructor calls back into the C library to resolve the
436/// human-readable message, category, and fatality flag, so no further lookups
437/// are needed by callers.
438///
439/// # Fatal errors
440///
441/// When [`Error::fatal`] is `true` the connection or server context that
442/// produced the error is no longer usable and must be dropped. Non-fatal errors
443/// (e.g., [`ERR_NETWORK_TIMEOUT`] on a single request) may be retried without
444/// tearing down the connection.
445///
446/// # Display format
447///
448/// ```text
449/// [network:1003] connection timed out
450/// ```
451///
452/// The format is `[<category>:<code>] <message>`, which makes it easy to grep
453/// logs by subsystem or numeric code.
454///
455/// # Example
456///
457/// ```rust
458/// use nwep::error::{Error, ERR_CRYPTO_VERIFY_FAILED};
459///
460/// let err = Error::from_code(ERR_CRYPTO_VERIFY_FAILED);
461/// assert_eq!(err.category, nwep::error::ErrorCategory::Crypto);
462/// eprintln!("{err}");
463/// ```
464#[derive(Debug, Clone)]
465pub struct Error {
466    /// `code` is the raw integer error code as returned by the C library.
467    /// Zero is never a valid error code; `Error` values are only constructed
468    /// for non-zero codes.
469    pub code: i32,
470
471    /// `category` identifies the NWEP subsystem that produced this error.
472    /// Use it for coarse-grained error handling (e.g., distinguishing network
473    /// transients from crypto failures).
474    pub category: ErrorCategory,
475
476    /// `fatal` is `true` when the C library considers the connection or context
477    /// unrecoverable. Callers must drop the associated [`crate::Client`] or
478    /// [`crate::Server`] when this flag is set.
479    pub fatal: bool,
480
481    /// `message` is the English-language description of the error retrieved
482    /// from the C library via `nwep_strerror`. Falls back to `"unknown error"`
483    /// if the C library returns a null pointer.
484    pub message: String,
485}
486
487impl Error {
488    /// `from_code` constructs an [`Error`] by querying the C library for the
489    /// human-readable message, fatality status, and category associated with
490    /// `code`.
491    ///
492    /// This is the primary constructor and is called automatically by the
493    /// internal [`check`] and [`check_ssize`] helpers whenever a C function
494    /// returns a non-zero error code.
495    ///
496    /// # Example
497    ///
498    /// ```rust
499    /// use nwep::error::{Error, ERR_NETWORK_TIMEOUT};
500    ///
501    /// let err = Error::from_code(ERR_NETWORK_TIMEOUT);
502    /// println!("{}", err.message);
503    /// ```
504    pub fn from_code(code: i32) -> Self {
505        let message = unsafe {
506            let ptr = ffi::nwep_strerror(code);
507            if ptr.is_null() {
508                String::from("unknown error")
509            } else {
510                CStr::from_ptr(ptr).to_string_lossy().into_owned()
511            }
512        };
513        let fatal = unsafe { ffi::nwep_err_is_fatal(code) != 0 };
514        let cat_ffi = unsafe { ffi::nwep_err_category(code) };
515        let category = category_from_ffi(cat_ffi);
516        Error {
517            code,
518            category,
519            fatal,
520            message,
521        }
522    }
523
524    /// `to_status` maps this error's code to the corresponding NWEP protocol
525    /// status string (e.g., `"unauthorized"`, `"not_found"`).
526    ///
527    /// The returned string is a `'static` reference into the C library's string
528    /// table, so it is valid for the lifetime of the process. If the C library
529    /// returns a null pointer the fallback value `"internal_error"` is
530    /// returned.
531    ///
532    /// This is useful when an error needs to be communicated back to a remote
533    /// client as a protocol-level status code in a response header.
534    ///
535    /// # Example
536    ///
537    /// ```rust
538    /// use nwep::error::{Error, ERR_NETWORK_CONN_FAILED};
539    ///
540    /// let err = Error::from_code(ERR_NETWORK_CONN_FAILED);
541    /// assert_eq!(err.to_status(), "internal_error");
542    /// ```
543    pub fn to_status(&self) -> &'static str {
544        unsafe {
545            let ptr = ffi::nwep_err_to_status(self.code);
546            if ptr.is_null() {
547                "internal_error"
548            } else {
549                CStr::from_ptr(ptr).to_str().unwrap_or("internal_error")
550            }
551        }
552    }
553}
554
555impl fmt::Display for Error {
556    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
557        write!(f, "[{}:{}] {}", self.category, self.code, self.message)
558    }
559}
560
561impl std::error::Error for Error {}
562
563/// `check` converts a C library return code into a Rust `Result`.
564///
565/// Returns `Ok(())` when `code` is zero and `Err(Error::from_code(code))`
566/// otherwise. This is the standard adapter used throughout the crate whenever a
567/// C function signals success/failure via its return value.
568pub(crate) fn check(code: i32) -> Result<(), Error> {
569    if code == 0 {
570        Ok(())
571    } else {
572        Err(Error::from_code(code))
573    }
574}
575
576/// `check_ssize` converts a C library signed-size return value into a Rust
577/// `Result<usize, Error>`.
578///
579/// Non-negative values indicate the number of bytes transferred and are
580/// returned as `Ok(n as usize)`. Negative values are error codes and are
581/// converted via [`Error::from_code`]. This mirrors the POSIX convention where
582/// `ssize_t` functions return `-errno` on failure.
583pub(crate) fn check_ssize(n: ffi::nwep_ssize) -> Result<usize, Error> {
584    if n >= 0 {
585        Ok(n as usize)
586    } else {
587        Err(Error::from_code(n as i32))
588    }
589}