1use super::*;
2
3#[macro_export]
5macro_rules! apibail_not_initialized {
6 () => {
7 return Err(VeilidAPIError::not_initialized())
8 };
9}
10
11#[macro_export]
13macro_rules! apibail_timeout {
14 () => {
15 return Err(VeilidAPIError::timeout())
16 };
17}
18
19#[macro_export]
21macro_rules! apibail_try_again {
22 ($x:expr) => {
23 return Err(VeilidAPIError::try_again($x))
24 };
25 ($fmt:literal, $($args:tt)*) => {
26 return Err(VeilidAPIError::try_again( format!($fmt, $($args)*) ))
27 };
28}
29
30#[macro_export]
32macro_rules! apibail_generic {
33 ($x:expr) => {
34 return Err(VeilidAPIError::generic($x))
35 };
36 ($fmt:literal, $($args:tt)*) => {
37 return Err(VeilidAPIError::generic( format!($fmt, $($args)*) ))
38 };
39}
40
41#[macro_export]
43macro_rules! apibail_internal {
44 ($x:expr) => {
45 return Err(VeilidAPIError::internal($x))
46 };
47 ($fmt:literal, $($args:tt)*) => {
48 return Err(VeilidAPIError::internal( format!($fmt, $($args)*) ))
49 };
50}
51
52#[macro_export]
54macro_rules! apibail_parse_error {
55 ($x:expr, $y:expr) => {
56 return Err(VeilidAPIError::parse_error($x, $y))
57 };
58}
59
60#[macro_export]
62macro_rules! apibail_missing_argument {
63 ($x:expr, $y:expr) => {
64 return Err(VeilidAPIError::missing_argument($x, $y))
65 };
66}
67
68#[macro_export]
70macro_rules! apibail_invalid_argument {
71 ($x:expr, $y:expr, $z:expr) => {
72 return Err(VeilidAPIError::invalid_argument($x, $y, $z))
73 };
74}
75
76#[macro_export]
78macro_rules! apibail_no_connection {
79 ($x:expr) => {
80 return Err(VeilidAPIError::no_connection($x))
81 };
82 ($fmt:literal, $($args: tt)* ) => {
83 return Err(VeilidAPIError::no_connection( format!($fmt, arg $($args)*) ))
84 };
85
86}
87
88#[macro_export]
90macro_rules! apibail_key_not_found {
91 ($x:expr) => {
92 return Err(VeilidAPIError::key_not_found($x))
93 };
94}
95
96#[macro_export]
98macro_rules! apibail_invalid_target {
99 ($x:expr) => {
100 return Err(VeilidAPIError::invalid_target($x))
101 };
102}
103
104#[macro_export]
106macro_rules! apibail_transaction_not_found {
107 ($x:expr) => {
108 return Err(VeilidAPIError::transaction_not_found($x))
109 };
110 ($fmt:literal, $($args:tt)*) => {
111 return Err(VeilidAPIError::transaction_not_found( format!($fmt, $($args)*) ))
112 };
113}
114
115#[macro_export]
117macro_rules! apibail_already_initialized {
118 () => {
119 return Err(VeilidAPIError::already_initialized())
120 };
121}
122
123#[apply(api_data_enum!)]
125#[api(eq, ord, ts(into_wasm_abi))]
126#[derive(ThisError)]
127#[serde(tag = "kind")]
128pub enum VeilidAPIError {
129 #[error("Not initialized")]
131 NotInitialized,
132 #[error("Already initialized")]
134 AlreadyInitialized,
135 #[error("Timeout")]
137 Timeout,
138 #[error("TryAgain: {message}")]
140 TryAgain {
141 message: String,
143 },
144 #[error("Invalid target: {message}")]
146 InvalidTarget {
147 message: String,
149 },
150 #[error("No connection: {message}")]
152 NoConnection {
153 message: String,
155 },
156 #[error("Shutdown")]
158 Shutdown,
159 #[error("Key not found: {key}")]
161 KeyNotFound {
162 #[cfg_attr(feature = "schemars", schemars(with = "String"))]
164 key: OpaqueRecordKey,
165 },
166 #[error("Internal: {message}")]
168 Internal {
169 message: String,
171 },
172 #[error("Unimplemented: {message}")]
174 Unimplemented {
175 message: String,
177 },
178 #[error("Parse error: '{message}' with value '{value}'")]
180 ParseError {
181 message: String,
183 value: String,
185 },
186 #[error("Invalid argument: '{context}' for '{argument}' with value '{value}'")]
188 InvalidArgument {
189 context: String,
191 argument: String,
193 value: String,
195 },
196 #[error("Missing argument: '{context}' for '{argument}'")]
198 MissingArgument {
199 context: String,
201 argument: String,
203 },
204 #[error("Generic: {message}")]
206 Generic {
207 message: String,
209 },
210 #[error("Transaction not found: {message}")]
212 TransactionNotFound {
213 message: String,
215 },
216}
217
218impl VeilidAPIError {
219 pub fn not_initialized() -> Self {
221 Self::NotInitialized
222 }
223 pub fn already_initialized() -> Self {
225 Self::AlreadyInitialized
226 }
227 pub fn timeout() -> Self {
229 Self::Timeout
230 }
231 pub fn try_again<T: ToVeilidAPIErrorArgument>(msg: T) -> Self {
233 Self::TryAgain {
234 message: msg.to_veilid_api_error_argument(),
235 }
236 }
237 pub fn shutdown() -> Self {
239 Self::Shutdown
240 }
241 pub fn invalid_target<T: ToVeilidAPIErrorArgument>(msg: T) -> Self {
243 Self::InvalidTarget {
244 message: msg.to_veilid_api_error_argument(),
245 }
246 }
247 pub fn no_connection<T: ToVeilidAPIErrorArgument>(msg: T) -> Self {
249 Self::NoConnection {
250 message: msg.to_veilid_api_error_argument(),
251 }
252 }
253 pub fn key_not_found(key: OpaqueRecordKey) -> Self {
255 Self::KeyNotFound { key }
256 }
257 pub fn parse_error<T: ToVeilidAPIErrorArgument, S: ToVeilidAPIErrorArgument>(
259 msg: T,
260 value: S,
261 ) -> Self {
262 Self::ParseError {
263 message: msg.to_veilid_api_error_argument(),
264 value: value.to_veilid_api_error_argument(),
265 }
266 }
267 pub fn invalid_argument<
269 T: ToVeilidAPIErrorArgument,
270 S: ToVeilidAPIErrorArgument,
271 R: ToVeilidAPIErrorArgument,
272 >(
273 context: T,
274 argument: S,
275 value: R,
276 ) -> Self {
277 Self::InvalidArgument {
278 context: context.to_veilid_api_error_argument(),
279 argument: argument.to_veilid_api_error_argument(),
280 value: value.to_veilid_api_error_argument(),
281 }
282 }
283 pub fn missing_argument<T: ToVeilidAPIErrorArgument, S: ToVeilidAPIErrorArgument>(
285 context: T,
286 argument: S,
287 ) -> Self {
288 Self::MissingArgument {
289 context: context.to_veilid_api_error_argument(),
290 argument: argument.to_veilid_api_error_argument(),
291 }
292 }
293 pub fn generic<T: ToVeilidAPIErrorArgument>(msg: T) -> Self {
295 Self::Generic {
296 message: msg.to_veilid_api_error_argument(),
297 }
298 }
299 pub(crate) fn transaction_not_found<T: ToVeilidAPIErrorArgument>(msg: T) -> Self {
300 Self::TransactionNotFound {
301 message: msg.to_veilid_api_error_argument(),
302 }
303 }
304
305 pub fn from_network_result<T>(nr: NetworkResult<T>) -> Result<T, Self> {
307 match nr {
308 NetworkResult::Timeout => Err(VeilidAPIError::timeout()),
309 NetworkResult::ServiceUnavailable(m) => Err(VeilidAPIError::invalid_target(m)),
310 NetworkResult::NoConnection(m) => Err(VeilidAPIError::no_connection(m.to_string())),
311 NetworkResult::AlreadyExists(m) => Err(VeilidAPIError::no_connection(format!(
312 "Already exists: {}",
313 m
314 ))),
315 NetworkResult::InvalidMessage(m) => {
316 Err(VeilidAPIError::parse_error("Invalid message", m))
317 }
318 NetworkResult::Value(v) => Ok(v),
319 }
320 }
321
322 pub fn log_level(&self) -> Level {
324 match self {
325 VeilidAPIError::NotInitialized
326 | VeilidAPIError::AlreadyInitialized
327 | VeilidAPIError::InvalidTarget { message: _ }
328 | VeilidAPIError::Internal { message: _ }
329 | VeilidAPIError::Generic { message: _ }
330 | VeilidAPIError::ParseError {
331 message: _,
332 value: _,
333 }
334 | VeilidAPIError::InvalidArgument {
335 context: _,
336 argument: _,
337 value: _,
338 }
339 | VeilidAPIError::MissingArgument {
340 context: _,
341 argument: _,
342 }
343 | VeilidAPIError::Shutdown => Level::ERROR,
344
345 VeilidAPIError::NoConnection { message: _ }
346 | VeilidAPIError::KeyNotFound { key: _ }
347 | VeilidAPIError::Unimplemented { message: _ } => Level::WARN,
348
349 VeilidAPIError::Timeout
350 | VeilidAPIError::TryAgain { message: _ }
351 | VeilidAPIError::TransactionNotFound { message: _ } => Level::DEBUG,
352 }
353 }
354
355 pub fn internal<T: ToString>(msg: T) -> Self {
357 let message = msg.to_string();
358 Self::Internal { message }
361 }
362 pub fn unimplemented<T: ToString>(msg: T) -> Self {
364 let message = msg.to_string();
365 Self::Unimplemented { message }
368 }
369}
370
371pub trait ToVeilidAPIErrorArgument {
375 fn to_veilid_api_error_argument(&self) -> String;
377}
378
379impl ToVeilidAPIErrorArgument for String {
380 fn to_veilid_api_error_argument(&self) -> String {
381 self.clone()
382 }
383}
384impl ToVeilidAPIErrorArgument for str {
385 fn to_veilid_api_error_argument(&self) -> String {
386 self.to_string()
387 }
388}
389impl ToVeilidAPIErrorArgument for [u8] {
390 fn to_veilid_api_error_argument(&self) -> String {
391 hex::encode(self)
392 }
393}
394impl ToVeilidAPIErrorArgument for Vec<u8> {
395 fn to_veilid_api_error_argument(&self) -> String {
396 hex::encode(self)
397 }
398}
399
400impl ToVeilidAPIErrorArgument for usize {
401 fn to_veilid_api_error_argument(&self) -> String {
402 self.to_string()
403 }
404}
405impl ToVeilidAPIErrorArgument for u64 {
406 fn to_veilid_api_error_argument(&self) -> String {
407 self.to_string()
408 }
409}
410impl ToVeilidAPIErrorArgument for u32 {
411 fn to_veilid_api_error_argument(&self) -> String {
412 self.to_string()
413 }
414}
415impl ToVeilidAPIErrorArgument for u16 {
416 fn to_veilid_api_error_argument(&self) -> String {
417 self.to_string()
418 }
419}
420impl ToVeilidAPIErrorArgument for u8 {
421 fn to_veilid_api_error_argument(&self) -> String {
422 self.to_string()
423 }
424}
425impl ToVeilidAPIErrorArgument for isize {
426 fn to_veilid_api_error_argument(&self) -> String {
427 self.to_string()
428 }
429}
430impl ToVeilidAPIErrorArgument for i64 {
431 fn to_veilid_api_error_argument(&self) -> String {
432 self.to_string()
433 }
434}
435impl ToVeilidAPIErrorArgument for i32 {
436 fn to_veilid_api_error_argument(&self) -> String {
437 self.to_string()
438 }
439}
440impl ToVeilidAPIErrorArgument for i16 {
441 fn to_veilid_api_error_argument(&self) -> String {
442 self.to_string()
443 }
444}
445impl ToVeilidAPIErrorArgument for i8 {
446 fn to_veilid_api_error_argument(&self) -> String {
447 self.to_string()
448 }
449}
450impl ToVeilidAPIErrorArgument for f64 {
451 fn to_veilid_api_error_argument(&self) -> String {
452 self.to_string()
453 }
454}
455impl ToVeilidAPIErrorArgument for f32 {
456 fn to_veilid_api_error_argument(&self) -> String {
457 self.to_string()
458 }
459}
460
461impl<T: ToVeilidAPIErrorArgument> ToVeilidAPIErrorArgument for core::ops::Range<T> {
462 fn to_veilid_api_error_argument(&self) -> String {
463 format!(
464 "{}..{}",
465 self.start.to_veilid_api_error_argument(),
466 self.end.to_veilid_api_error_argument()
467 )
468 }
469}
470
471impl ToVeilidAPIErrorArgument for Timestamp {
472 fn to_veilid_api_error_argument(&self) -> String {
473 self.to_string()
474 }
475}
476impl ToVeilidAPIErrorArgument for TimestampDuration {
477 fn to_veilid_api_error_argument(&self) -> String {
478 self.to_string()
479 }
480}
481impl ToVeilidAPIErrorArgument for ValueSeqNum {
482 fn to_veilid_api_error_argument(&self) -> String {
483 self.to_string()
484 }
485}
486impl ToVeilidAPIErrorArgument for ValueSubkeyRangeSet {
487 fn to_veilid_api_error_argument(&self) -> String {
488 self.to_string()
489 }
490}
491impl ToVeilidAPIErrorArgument for CryptoKind {
492 fn to_veilid_api_error_argument(&self) -> String {
493 self.to_string()
494 }
495}
496impl ToVeilidAPIErrorArgument for VeilidCapability {
497 fn to_veilid_api_error_argument(&self) -> String {
498 self.to_string()
499 }
500}
501
502impl ToVeilidAPIErrorArgument for RouteId {
503 fn to_veilid_api_error_argument(&self) -> String {
504 self.to_string()
505 }
506}
507impl ToVeilidAPIErrorArgument for NodeId {
508 fn to_veilid_api_error_argument(&self) -> String {
509 self.to_string()
510 }
511}
512impl ToVeilidAPIErrorArgument for PublicKey {
513 fn to_veilid_api_error_argument(&self) -> String {
514 self.to_string()
515 }
516}
517impl ToVeilidAPIErrorArgument for SecretKey {
518 fn to_veilid_api_error_argument(&self) -> String {
519 format!(
520 "{}:{}",
521 self.kind(),
522 self.ref_value().to_veilid_api_error_argument()
523 )
524 }
525}
526impl ToVeilidAPIErrorArgument for SharedSecret {
527 fn to_veilid_api_error_argument(&self) -> String {
528 format!(
529 "{}:{}",
530 self.kind(),
531 self.ref_value().to_veilid_api_error_argument()
532 )
533 }
534}
535impl ToVeilidAPIErrorArgument for Signature {
536 fn to_veilid_api_error_argument(&self) -> String {
537 format!(
538 "{}:{}",
539 self.kind(),
540 self.ref_value().to_veilid_api_error_argument()
541 )
542 }
543}
544impl ToVeilidAPIErrorArgument for HashDigest {
545 fn to_veilid_api_error_argument(&self) -> String {
546 format!(
547 "{}:{}",
548 self.kind(),
549 self.ref_value().to_veilid_api_error_argument()
550 )
551 }
552}
553impl ToVeilidAPIErrorArgument for KeyPair {
554 fn to_veilid_api_error_argument(&self) -> String {
555 format!(
556 "{}:{}",
557 self.kind(),
558 self.ref_value().to_veilid_api_error_argument(),
559 )
560 }
561}
562impl ToVeilidAPIErrorArgument for RecordKey {
563 fn to_veilid_api_error_argument(&self) -> String {
564 format!(
565 "{}:{}",
566 self.kind(),
567 self.value().to_veilid_api_error_argument()
568 )
569 }
570}
571impl ToVeilidAPIErrorArgument for MemberId {
572 fn to_veilid_api_error_argument(&self) -> String {
573 self.to_string()
574 }
575}
576impl ToVeilidAPIErrorArgument for OpaqueRecordKey {
577 fn to_veilid_api_error_argument(&self) -> String {
578 format!(
579 "{}:{}",
580 self.kind(),
581 self.ref_value().to_veilid_api_error_argument()
582 )
583 }
584}
585impl ToVeilidAPIErrorArgument for BareRecordKey {
586 fn to_veilid_api_error_argument(&self) -> String {
587 format!(
588 "{}{}",
589 self.ref_key(),
590 self.ref_encryption_key()
591 .map(|ek| ek.to_veilid_api_error_argument())
592 .unwrap_or("".to_string())
593 )
594 }
595}
596impl ToVeilidAPIErrorArgument for BareKeyPair {
597 fn to_veilid_api_error_argument(&self) -> String {
598 format!(
599 "{}:{}",
600 self.ref_key().to_veilid_api_error_argument(),
601 self.ref_secret().to_veilid_api_error_argument()
602 )
603 }
604}
605impl ToVeilidAPIErrorArgument for BarePublicKey {
606 fn to_veilid_api_error_argument(&self) -> String {
607 self.to_string()
608 }
609}
610impl ToVeilidAPIErrorArgument for BareSecretKey {
611 fn to_veilid_api_error_argument(&self) -> String {
612 "*".repeat(self.to_string().len())
613 }
614}
615impl ToVeilidAPIErrorArgument for BareSharedSecret {
616 fn to_veilid_api_error_argument(&self) -> String {
617 "*".repeat(self.to_string().len())
618 }
619}
620impl ToVeilidAPIErrorArgument for BareSignature {
621 fn to_veilid_api_error_argument(&self) -> String {
622 self.to_string()
623 }
624}
625impl ToVeilidAPIErrorArgument for BareHashDigest {
626 fn to_veilid_api_error_argument(&self) -> String {
627 self.to_string()
628 }
629}
630impl ToVeilidAPIErrorArgument for BareOpaqueRecordKey {
631 fn to_veilid_api_error_argument(&self) -> String {
632 self.to_string()
633 }
634}
635impl ToVeilidAPIErrorArgument for BareMemberId {
636 fn to_veilid_api_error_argument(&self) -> String {
637 self.to_string()
638 }
639}
640
641impl ToVeilidAPIErrorArgument for serde_json::Error {
642 fn to_veilid_api_error_argument(&self) -> String {
643 self.to_string()
644 }
645}
646
647impl<T: ToVeilidAPIErrorArgument + ?Sized> ToVeilidAPIErrorArgument for &T {
648 fn to_veilid_api_error_argument(&self) -> String {
649 (**self).to_veilid_api_error_argument()
650 }
651}
652
653pub type VeilidAPIResult<T> = Result<T, VeilidAPIError>;
657
658pub trait OkVeilidAPIResult<T> {
660 fn ok_try_again(self) -> VeilidAPIResult<Option<T>>;
662 fn ok_try_again_timeout(self) -> VeilidAPIResult<Option<T>>;
664}
665
666impl<T> OkVeilidAPIResult<T> for VeilidAPIResult<Option<T>> {
667 fn ok_try_again(self) -> VeilidAPIResult<Option<T>> {
668 match self {
669 Ok(v) => Ok(v),
670 Err(VeilidAPIError::TryAgain { message: _ }) => Ok(None),
671 Err(e) => Err(e),
672 }
673 }
674 fn ok_try_again_timeout(self) -> VeilidAPIResult<Option<T>> {
675 match self {
676 Ok(v) => Ok(v),
677 Err(VeilidAPIError::TryAgain { message: _ }) => Ok(None),
678 Err(VeilidAPIError::Timeout) => Ok(None),
679 Err(e) => Err(e),
680 }
681 }
682}
683
684impl From<std::io::Error> for VeilidAPIError {
685 fn from(e: std::io::Error) -> Self {
686 match e.kind() {
687 std::io::ErrorKind::TimedOut => VeilidAPIError::timeout(),
688 std::io::ErrorKind::ConnectionRefused => VeilidAPIError::no_connection(e.to_string()),
689 std::io::ErrorKind::ConnectionReset => VeilidAPIError::no_connection(e.to_string()),
690 std::io::ErrorKind::ConnectionAborted => VeilidAPIError::no_connection(e.to_string()),
695 std::io::ErrorKind::NotConnected => VeilidAPIError::no_connection(e.to_string()),
696 std::io::ErrorKind::AddrInUse => VeilidAPIError::no_connection(e.to_string()),
697 std::io::ErrorKind::AddrNotAvailable => VeilidAPIError::no_connection(e.to_string()),
698 std::io::ErrorKind::Unsupported => VeilidAPIError::internal(e.to_string()),
709 std::io::ErrorKind::OutOfMemory => VeilidAPIError::internal(e.to_string()),
710 _ => VeilidAPIError::generic(e.to_string()),
711 }
712 }
713}