tigerbeetle_unofficial_core/
error.rs1use std::{
2 error::Error,
3 fmt, mem,
4 num::{NonZeroU32, NonZeroU8},
5};
6
7pub use sys::{
8 generated_safe::{
9 self as sys_safe, CreateAccountErrorKind, CreateTransferErrorKind,
10 InitStatusErrorKind as NewClientErrorKind, PacketStatusErrorKind as SendErrorKind,
11 },
12 tb_create_accounts_result_t as RawCreateAccountsIndividualApiResult,
13 tb_create_transfers_result_t as RawCreateTransfersIndividualApiResult,
14};
15
16#[derive(Clone, Copy)]
17pub struct NewClientError(pub(crate) NonZeroU32);
18
19impl NewClientError {
20 const CODE_RANGE: std::ops::RangeInclusive<u32> =
21 sys_safe::MIN_INIT_STATUS_ERROR_CODE..=sys_safe::MAX_INIT_STATUS_ERROR_CODE;
22
23 pub fn kind(self) -> NewClientErrorKind {
24 let code = self.0.get();
25 if Self::CODE_RANGE.contains(&code) {
26 unsafe { mem::transmute::<u32, NewClientErrorKind>(code) }
28 } else {
29 NewClientErrorKind::UnstableUncategorized
30 }
31 }
32
33 pub fn code(self) -> NonZeroU32 {
34 self.0
35 }
36}
37
38impl fmt::Debug for NewClientError {
39 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
40 let mut d = f.debug_tuple("NewClientError");
41 let kind = self.kind();
42 if matches!(kind, NewClientErrorKind::UnstableUncategorized) {
43 let code = self.code();
44 d.field(&code);
45 } else {
46 d.field(&kind);
47 }
48 d.finish()
49 }
50}
51
52impl fmt::Display for NewClientError {
53 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
54 use NewClientErrorKind as K;
55
56 match self.kind() {
57 K::AddressInvalid => "Replica addresses format is invalid",
58 K::AddressLimitExceeded => "Replica addresses limit exceeded",
59 K::NetworkSubsystem => "Internal client had unexpected networking issues",
60 K::OutOfMemory => "Internal client ran out of memory",
61 K::SystemResources => "Internal client ran out of system resources",
62 K::Unexpected => "Unexpected internal error",
63 _ => return write!(f, "Unknown error status: {}", self.code()),
64 }
65 .fmt(f)
66 }
67}
68
69impl Error for NewClientError {}
70
71impl From<NewClientErrorKind> for NewClientError {
72 fn from(value: NewClientErrorKind) -> Self {
78 let this = Self(NonZeroU32::new(value as _).unwrap());
79 if matches!(this.kind(), NewClientErrorKind::UnstableUncategorized) {
80 panic!("NewClientErrorKind::{value:?}")
81 }
82 this
83 }
84}
85
86#[derive(Clone, Copy)]
87pub struct SendError(pub(crate) NonZeroU8);
88
89impl SendError {
90 const CODE_RANGE: std::ops::RangeInclusive<u8> =
91 sys_safe::MIN_PACKET_STATUS_ERROR_CODE..=sys_safe::MAX_PACKET_STATUS_ERROR_CODE;
92
93 pub fn kind(self) -> SendErrorKind {
94 let code = self.0.get();
95 if Self::CODE_RANGE.contains(&code) {
96 unsafe { mem::transmute::<u8, SendErrorKind>(code) }
98 } else {
99 SendErrorKind::UnstableUncategorized
100 }
101 }
102
103 pub fn code(self) -> NonZeroU8 {
104 self.0
105 }
106}
107
108impl fmt::Debug for SendError {
109 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
110 let mut d = f.debug_tuple("SendError");
111 let kind = self.kind();
112 if matches!(kind, SendErrorKind::UnstableUncategorized) {
113 let code = self.code();
114 d.field(&code);
115 } else {
116 d.field(&kind);
117 }
118 d.finish()
119 }
120}
121
122impl fmt::Display for SendError {
123 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
124 use SendErrorKind as K;
125
126 match self.kind() {
127 K::TooMuchData => "Too much data provided on this batch",
128 K::InvalidOperation => "Invalid operation",
129 K::InvalidDataSize => "Invalid data size",
130 K::ClientEvicted => "Client was evicted",
131 K::ClientReleaseTooLow => "Client was evicted: release too old",
132 K::ClientReleaseTooHigh => "Client was evicted: release too new",
133 K::ClientShutdown => "Client was closed",
134 _ => return write!(f, "Unknown error status: {}", self.code()),
135 }
136 .fmt(f)
137 }
138}
139
140impl Error for SendError {}
141
142impl From<SendErrorKind> for SendError {
143 fn from(value: SendErrorKind) -> Self {
149 let this = Self(NonZeroU8::new(value as _).unwrap());
150 if matches!(this.kind(), SendErrorKind::UnstableUncategorized) {
151 panic!("SendErrorKind::{value:?}")
152 }
153 this
154 }
155}
156
157#[derive(Clone, Copy)]
158pub struct CreateAccountError(pub(crate) NonZeroU32);
159
160impl CreateAccountError {
161 const CODE_RANGE: std::ops::RangeInclusive<u32> =
162 sys_safe::MIN_CREATE_ACCOUNT_ERROR_CODE..=sys_safe::MAX_CREATE_ACCOUNT_ERROR_CODE;
163
164 pub fn kind(self) -> CreateAccountErrorKind {
165 let code = self.0.get();
166 if Self::CODE_RANGE.contains(&code) {
167 unsafe { mem::transmute::<u32, CreateAccountErrorKind>(code) }
169 } else {
170 CreateAccountErrorKind::UnstableUncategorized
171 }
172 }
173
174 pub fn code(self) -> NonZeroU32 {
175 self.0
176 }
177}
178
179impl fmt::Debug for CreateAccountError {
180 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
181 let mut d = f.debug_tuple("CreateAccountError");
182 let kind = self.kind();
183 if matches!(kind, CreateAccountErrorKind::UnstableUncategorized) {
184 d.field(&self.0);
185 } else {
186 d.field(&kind);
187 }
188 d.finish()
189 }
190}
191
192impl fmt::Display for CreateAccountError {
193 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
194 write!(f, "{:?}", self.kind())
195 }
196}
197
198impl Error for CreateAccountError {}
199
200impl From<CreateAccountErrorKind> for CreateAccountError {
201 fn from(value: CreateAccountErrorKind) -> Self {
207 let this = Self(NonZeroU32::new(value as _).unwrap());
208 if matches!(this.kind(), CreateAccountErrorKind::UnstableUncategorized) {
209 panic!("CreateAccountErrorKind::{value:?}")
210 }
211 this
212 }
213}
214
215#[derive(Clone, Copy)]
221#[repr(transparent)]
222pub struct CreateAccountsIndividualApiError(RawCreateAccountsIndividualApiResult);
223
224impl CreateAccountsIndividualApiError {
225 pub fn from_raw_result(raw: RawCreateAccountsIndividualApiResult) -> Option<Self> {
231 (raw.result != 0).then_some(Self(raw))
232 }
233
234 pub unsafe fn from_raw_result_unchecked(raw: RawCreateAccountsIndividualApiResult) -> Self {
240 Self(raw)
241 }
242
243 pub fn vec_from_raw_results(mut v: Vec<RawCreateAccountsIndividualApiResult>) -> Vec<Self> {
247 v.retain(|r| r.result != 0);
248 unsafe { Self::vec_from_raw_results_unchecked(v) }
249 }
250
251 pub unsafe fn vec_from_raw_results_unchecked(
259 v: Vec<RawCreateAccountsIndividualApiResult>,
260 ) -> Vec<Self> {
261 let mut v = mem::ManuallyDrop::new(v);
262 let len = v.len();
263 let cap = v.capacity();
264 let ptr = v.as_mut_ptr().cast::<CreateAccountsIndividualApiError>();
265 Vec::from_raw_parts(ptr, len, cap)
270 }
271
272 pub fn index(&self) -> u32 {
274 self.0.index
275 }
276
277 pub fn inner(&self) -> CreateAccountError {
279 CreateAccountError(
280 unsafe { NonZeroU32::new_unchecked(self.0.result) },
282 )
283 }
284
285 pub fn kind(&self) -> CreateAccountErrorKind {
287 self.inner().kind()
288 }
289}
290
291impl fmt::Debug for CreateAccountsIndividualApiError {
292 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
293 f.debug_struct("CreateAccountsIndividualApiError")
294 .field("index", &self.index())
295 .field("inner", &self.inner())
296 .finish()
297 }
298}
299
300impl fmt::Display for CreateAccountsIndividualApiError {
301 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
302 write!(
303 f,
304 "`{}` error occurred at account with index {}",
305 self.inner(),
306 self.index(),
307 )
308 }
309}
310
311impl Error for CreateAccountsIndividualApiError {}
312
313#[derive(Debug)]
315pub struct CreateAccountsApiError(Vec<CreateAccountsIndividualApiError>);
316
317impl CreateAccountsApiError {
318 pub fn as_slice(&self) -> &[CreateAccountsIndividualApiError] {
320 &self.0
321 }
322
323 pub fn from_errors(v: Vec<CreateAccountsIndividualApiError>) -> Option<Self> {
329 (!v.is_empty()).then_some(CreateAccountsApiError(v))
330 }
331
332 pub fn from_raw_results(v: Vec<RawCreateAccountsIndividualApiResult>) -> Option<Self> {
336 Self::from_errors(CreateAccountsIndividualApiError::vec_from_raw_results(v))
337 }
338}
339
340impl AsRef<[CreateAccountsIndividualApiError]> for CreateAccountsApiError {
341 fn as_ref(&self) -> &[CreateAccountsIndividualApiError] {
342 &self.0
343 }
344}
345
346impl fmt::Display for CreateAccountsApiError {
347 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
348 write!(
349 f,
350 "{} api errors occurred at accounts' creation",
351 self.0.len(),
352 )
353 }
354}
355
356impl Error for CreateAccountsApiError {
357 fn source(&self) -> Option<&(dyn Error + 'static)> {
358 self.0.first().map(|e| e as _)
359 }
360}
361
362impl From<CreateAccountsIndividualApiError> for CreateAccountsApiError {
363 fn from(value: CreateAccountsIndividualApiError) -> Self {
364 CreateAccountsApiError(vec![value])
365 }
366}
367
368#[derive(Debug)]
369#[non_exhaustive]
370pub enum CreateAccountsError {
371 Send(SendError),
372 Api(CreateAccountsApiError),
373}
374
375impl Error for CreateAccountsError {
376 fn source(&self) -> Option<&(dyn Error + 'static)> {
377 Some(match self {
378 Self::Send(e) => e as _,
379 Self::Api(e) => e as _,
380 })
381 }
382}
383
384impl fmt::Display for CreateAccountsError {
385 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
386 write!(f, "Failed to create accounts: ")?;
387 match self {
388 Self::Send(e) => write!(f, "{e}"),
389 Self::Api(e) => write!(f, "{e}"),
390 }
391 }
392}
393
394impl From<SendError> for CreateAccountsError {
395 fn from(value: SendError) -> Self {
396 Self::Send(value)
397 }
398}
399
400impl From<CreateAccountsApiError> for CreateAccountsError {
401 fn from(value: CreateAccountsApiError) -> Self {
402 Self::Api(value)
403 }
404}
405
406#[derive(Clone, Copy)]
407pub struct CreateTransferError(pub(crate) NonZeroU32);
408
409impl CreateTransferError {
410 const CODE_RANGE: std::ops::RangeInclusive<u32> =
411 sys_safe::MIN_CREATE_TRANSFER_ERROR_CODE..=sys_safe::MAX_CREATE_TRANSFER_ERROR_CODE;
412
413 pub fn kind(self) -> CreateTransferErrorKind {
414 let code = self.0.get();
415 if Self::CODE_RANGE.contains(&code)
416 && !sys_safe::EXCLUDED_CREATE_TRANSFER_ERROR_CODES.contains(&code)
417 {
418 unsafe { mem::transmute::<u32, CreateTransferErrorKind>(code) }
420 } else {
421 CreateTransferErrorKind::UnstableUncategorized
422 }
423 }
424
425 pub fn code(self) -> NonZeroU32 {
426 self.0
427 }
428}
429
430impl fmt::Debug for CreateTransferError {
431 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
432 let mut d = f.debug_tuple("CreateTransferError");
433 let kind = self.kind();
434 if matches!(kind, CreateTransferErrorKind::UnstableUncategorized) {
435 let code = self.code().get();
436 d.field(&code);
437 } else {
438 d.field(&kind);
439 }
440 d.finish()
441 }
442}
443
444impl fmt::Display for CreateTransferError {
445 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
446 write!(f, "{:?}", self.kind())
447 }
448}
449
450impl Error for CreateTransferError {}
451
452impl From<CreateTransferErrorKind> for CreateTransferError {
453 fn from(value: CreateTransferErrorKind) -> Self {
459 let this = Self(NonZeroU32::new(value as _).unwrap());
460 if matches!(this.kind(), CreateTransferErrorKind::UnstableUncategorized) {
461 panic!("CreateTransferErrorKind::{value:?}")
462 }
463 this
464 }
465}
466
467#[derive(Clone, Copy)]
473#[repr(transparent)]
474pub struct CreateTransfersIndividualApiError(RawCreateTransfersIndividualApiResult);
475
476impl CreateTransfersIndividualApiError {
477 pub fn from_raw_result(raw: RawCreateTransfersIndividualApiResult) -> Option<Self> {
483 (raw.result != 0).then_some(Self(raw))
484 }
485
486 pub unsafe fn from_raw_result_unchecked(raw: RawCreateTransfersIndividualApiResult) -> Self {
492 Self(raw)
493 }
494
495 pub fn vec_from_raw_results(mut v: Vec<RawCreateTransfersIndividualApiResult>) -> Vec<Self> {
499 v.retain(|r| r.result != 0);
500 unsafe { Self::vec_from_raw_results_unchecked(v) }
501 }
502
503 pub unsafe fn vec_from_raw_results_unchecked(
511 v: Vec<RawCreateTransfersIndividualApiResult>,
512 ) -> Vec<Self> {
513 let mut v = mem::ManuallyDrop::new(v);
514 let len = v.len();
515 let cap = v.capacity();
516 let ptr = v.as_mut_ptr().cast::<CreateTransfersIndividualApiError>();
517 Vec::from_raw_parts(ptr, len, cap)
522 }
523
524 pub fn index(&self) -> u32 {
526 self.0.index
527 }
528
529 pub fn inner(&self) -> CreateTransferError {
531 CreateTransferError(
532 unsafe { NonZeroU32::new_unchecked(self.0.result) },
534 )
535 }
536
537 pub fn kind(&self) -> CreateTransferErrorKind {
539 self.inner().kind()
540 }
541}
542
543impl fmt::Debug for CreateTransfersIndividualApiError {
544 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
545 f.debug_struct("CreateTransfersIndividualApiError")
546 .field("index", &self.index())
547 .field("inner", &self.inner())
548 .finish()
549 }
550}
551
552impl fmt::Display for CreateTransfersIndividualApiError {
553 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
554 write!(
555 f,
556 "`{}` error occurred at account with index {}",
557 self.inner(),
558 self.index(),
559 )
560 }
561}
562
563impl Error for CreateTransfersIndividualApiError {}
564
565#[derive(Debug)]
567pub struct CreateTransfersApiError(Vec<CreateTransfersIndividualApiError>);
568
569impl CreateTransfersApiError {
570 pub fn as_slice(&self) -> &[CreateTransfersIndividualApiError] {
572 &self.0
573 }
574
575 pub fn from_errors(v: Vec<CreateTransfersIndividualApiError>) -> Option<Self> {
581 (!v.is_empty()).then_some(CreateTransfersApiError(v))
582 }
583
584 pub fn from_raw_results(v: Vec<RawCreateTransfersIndividualApiResult>) -> Option<Self> {
588 Self::from_errors(CreateTransfersIndividualApiError::vec_from_raw_results(v))
589 }
590}
591
592impl AsRef<[CreateTransfersIndividualApiError]> for CreateTransfersApiError {
593 fn as_ref(&self) -> &[CreateTransfersIndividualApiError] {
594 &self.0
595 }
596}
597
598impl fmt::Display for CreateTransfersApiError {
599 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
600 write!(
601 f,
602 "{} api errors occurred at transfers' creation",
603 self.0.len(),
604 )
605 }
606}
607
608impl Error for CreateTransfersApiError {
609 fn source(&self) -> Option<&(dyn Error + 'static)> {
610 self.0.first().map(|e| e as _)
611 }
612}
613
614impl From<CreateTransfersIndividualApiError> for CreateTransfersApiError {
615 fn from(value: CreateTransfersIndividualApiError) -> Self {
616 Self(vec![value])
617 }
618}
619
620#[derive(Debug)]
621#[non_exhaustive]
622pub enum CreateTransfersError {
623 Send(SendError),
624 Api(CreateTransfersApiError),
625}
626
627impl Error for CreateTransfersError {
628 fn source(&self) -> Option<&(dyn Error + 'static)> {
629 Some(match self {
630 Self::Send(e) => e as _,
631 Self::Api(e) => e as _,
632 })
633 }
634}
635
636impl fmt::Display for CreateTransfersError {
637 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
638 write!(f, "Failed to create transfers: ")?;
639 match self {
640 Self::Send(e) => write!(f, "{e}"),
641 Self::Api(e) => write!(f, "{e}"),
642 }
643 }
644}
645
646impl From<SendError> for CreateTransfersError {
647 fn from(value: SendError) -> Self {
648 Self::Send(value)
649 }
650}
651
652impl From<CreateTransfersApiError> for CreateTransfersError {
653 fn from(value: CreateTransfersApiError) -> Self {
654 Self::Api(value)
655 }
656}