1#[cfg(feature = "std")]
29use thiserror::Error;
30
31#[cfg(feature = "std")]
32use std::io;
33
34#[derive(Debug)]
39#[cfg_attr(feature = "std", derive(Error))]
40pub enum DbError {
41 #[cfg_attr(feature = "std", error("Connection failed to {endpoint}: {reason}"))]
44 ConnectionFailed {
45 #[cfg(feature = "std")]
46 endpoint: String,
47 #[cfg(feature = "std")]
48 reason: String,
49 #[cfg(not(feature = "std"))]
50 _endpoint: (),
51 #[cfg(not(feature = "std"))]
52 _reason: (),
53 },
54
55 #[cfg_attr(feature = "std", error("Buffer full: {buffer_name} ({size} items)"))]
58 BufferFull {
59 size: u32,
60 #[cfg(feature = "std")]
61 buffer_name: String,
62 #[cfg(not(feature = "std"))]
63 _buffer_name: (),
64 },
65
66 #[cfg_attr(feature = "std", error("Consumer lagged by {lag_count} messages"))]
68 BufferLagged {
69 lag_count: u64,
70 #[cfg(feature = "std")]
71 buffer_name: String,
72 #[cfg(not(feature = "std"))]
73 _buffer_name: (),
74 },
75
76 #[cfg_attr(feature = "std", error("Buffer channel closed: {buffer_name}"))]
78 BufferClosed {
79 #[cfg(feature = "std")]
80 buffer_name: String,
81 #[cfg(not(feature = "std"))]
82 _buffer_name: (),
83 },
84
85 #[cfg_attr(feature = "std", error("Buffer empty: no pending values"))]
87 BufferEmpty,
88
89 #[cfg_attr(feature = "std", error("Record type not found: {record_name}"))]
92 RecordNotFound {
93 #[cfg(feature = "std")]
94 record_name: String,
95 #[cfg(not(feature = "std"))]
96 _record_name: (),
97 },
98
99 #[cfg_attr(feature = "std", error("Record key not found: {key}"))]
101 RecordKeyNotFound {
102 #[cfg(feature = "std")]
103 key: String,
104 #[cfg(not(feature = "std"))]
105 _key: (),
106 },
107
108 #[cfg_attr(feature = "std", error("Invalid record ID: {id}"))]
110 InvalidRecordId { id: u32 },
111
112 #[cfg_attr(
114 feature = "std",
115 error("Type mismatch: expected {expected_type}, record {record_id} has different type")
116 )]
117 TypeMismatch {
118 record_id: u32,
119 #[cfg(feature = "std")]
120 expected_type: String,
121 #[cfg(not(feature = "std"))]
122 _expected_type: (),
123 },
124
125 #[cfg_attr(
127 feature = "std",
128 error("Ambiguous type lookup: {type_name} has {count} records, use explicit key")
129 )]
130 AmbiguousType {
131 count: u32,
132 #[cfg(feature = "std")]
133 type_name: String,
134 #[cfg(not(feature = "std"))]
135 _type_name: (),
136 },
137
138 #[cfg_attr(feature = "std", error("Duplicate record key: {key}"))]
140 DuplicateRecordKey {
141 #[cfg(feature = "std")]
142 key: String,
143 #[cfg(not(feature = "std"))]
144 _key: (),
145 },
146
147 #[cfg_attr(feature = "std", error("Invalid operation '{operation}': {reason}"))]
149 InvalidOperation {
150 #[cfg(feature = "std")]
151 operation: String,
152 #[cfg(feature = "std")]
153 reason: String,
154 #[cfg(not(feature = "std"))]
155 _operation: (),
156 #[cfg(not(feature = "std"))]
157 _reason: (),
158 },
159
160 #[cfg_attr(feature = "std", error("Permission denied: {operation}"))]
162 PermissionDenied {
163 #[cfg(feature = "std")]
164 operation: String,
165 #[cfg(not(feature = "std"))]
166 _operation: (),
167 },
168
169 #[cfg_attr(feature = "std", error("Missing configuration parameter: {parameter}"))]
172 MissingConfiguration {
173 #[cfg(feature = "std")]
174 parameter: String,
175 #[cfg(not(feature = "std"))]
176 _parameter: (),
177 },
178
179 #[cfg_attr(feature = "std", error("Runtime error: {message}"))]
182 RuntimeError {
183 #[cfg(feature = "std")]
184 message: String,
185 #[cfg(not(feature = "std"))]
186 _message: (),
187 },
188
189 #[cfg_attr(feature = "std", error("Resource unavailable: {resource_name}"))]
191 ResourceUnavailable {
192 resource_type: u8,
193 #[cfg(feature = "std")]
194 resource_name: String,
195 #[cfg(not(feature = "std"))]
196 _resource_name: (),
197 },
198
199 #[cfg_attr(
202 feature = "std",
203 error("Hardware error: component {component}, code 0x{error_code:04X}")
204 )]
205 HardwareError {
206 component: u8,
207 error_code: u16,
208 #[cfg(feature = "std")]
209 description: String,
210 #[cfg(not(feature = "std"))]
211 _description: (),
212 },
213
214 #[cfg_attr(feature = "std", error("Internal error (0x{code:04X}): {message}"))]
217 Internal {
218 code: u32,
219 #[cfg(feature = "std")]
220 message: String,
221 #[cfg(not(feature = "std"))]
222 _message: (),
223 },
224
225 #[cfg(feature = "std")]
228 #[error("Failed to attach database: {message}")]
229 AttachFailed { message: String },
230
231 #[cfg(feature = "std")]
233 #[error("Failed to detach database: {message}")]
234 DetachFailed { message: String },
235
236 #[cfg(feature = "std")]
238 #[error("Timeout while setting value")]
239 SetTimeout,
240
241 #[cfg(feature = "std")]
243 #[error("Timeout while getting value")]
244 GetTimeout,
245
246 #[cfg(feature = "std")]
248 #[error("Runtime thread has shut down")]
249 RuntimeShutdown,
250
251 #[cfg_attr(
254 feature = "std",
255 error("Cyclic dependency detected among records: {records:?}")
256 )]
257 CyclicDependency {
258 #[cfg(feature = "std")]
259 records: Vec<String>,
260 #[cfg(not(feature = "std"))]
261 _records: (),
262 },
263
264 #[cfg_attr(
266 feature = "std",
267 error("Transform on '{output_key}' references unregistered input '{input_key}'")
268 )]
269 TransformInputNotFound {
270 #[cfg(feature = "std")]
271 output_key: String,
272 #[cfg(feature = "std")]
273 input_key: String,
274 #[cfg(not(feature = "std"))]
275 _output_key: (),
276 #[cfg(not(feature = "std"))]
277 _input_key: (),
278 },
279
280 #[cfg(feature = "std")]
283 #[error("I/O error: {source}")]
284 Io {
285 #[from]
286 source: io::Error,
287 },
288
289 #[cfg(feature = "std")]
291 #[error("I/O error: {context}: {source}")]
292 IoWithContext {
293 context: String,
294 #[source]
295 source: io::Error,
296 },
297
298 #[cfg(feature = "std")]
300 #[error("JSON error: {source}")]
301 Json {
302 #[from]
303 source: serde_json::Error,
304 },
305
306 #[cfg(feature = "std")]
308 #[error("JSON error: {context}: {source}")]
309 JsonWithContext {
310 context: String,
311 #[source]
312 source: serde_json::Error,
313 },
314}
315
316#[cfg(not(feature = "std"))]
318impl core::fmt::Display for DbError {
319 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
320 let (code, message) = match self {
321 DbError::ConnectionFailed { .. } => (0x1002, "Connection failed"),
322 DbError::BufferFull { .. } => (0x2002, "Buffer full"),
323 DbError::BufferLagged { .. } => (0xA001, "Buffer consumer lagged"),
324 DbError::BufferClosed { .. } => (0xA002, "Buffer channel closed"),
325 DbError::BufferEmpty => (0xA003, "Buffer empty"),
326 DbError::RecordNotFound { .. } => (0x7003, "Record not found"),
327 DbError::RecordKeyNotFound { .. } => (0x7006, "Record key not found"),
328 DbError::InvalidRecordId { .. } => (0x7007, "Invalid record ID"),
329 DbError::TypeMismatch { .. } => (0x7008, "Type mismatch"),
330 DbError::AmbiguousType { .. } => (0x7009, "Ambiguous type lookup"),
331 DbError::DuplicateRecordKey { .. } => (0x700A, "Duplicate record key"),
332 DbError::InvalidOperation { .. } => (0x7004, "Invalid operation"),
333 DbError::PermissionDenied { .. } => (0x7005, "Permission denied"),
334 DbError::MissingConfiguration { .. } => (0x4002, "Missing configuration"),
335 DbError::RuntimeError { .. } => (0x7002, "Runtime error"),
336 DbError::ResourceUnavailable { .. } => (0x5002, "Resource unavailable"),
337 DbError::HardwareError { .. } => (0x6001, "Hardware error"),
338 DbError::Internal { .. } => (0x7001, "Internal error"),
339 DbError::CyclicDependency { .. } => (0xC001, "Cyclic dependency in transforms"),
340 DbError::TransformInputNotFound { .. } => (0xC002, "Transform input not found"),
341 };
342 write!(f, "Error 0x{:04X}: {}", code, message)
343 }
344}
345
346impl DbError {
348 pub const RESOURCE_TYPE_MEMORY: u8 = 0;
350 pub const RESOURCE_TYPE_FILE_HANDLE: u8 = 1;
351 pub const RESOURCE_TYPE_SOCKET: u8 = 2;
352 pub const RESOURCE_TYPE_BUFFER: u8 = 3;
353 pub const RESOURCE_TYPE_THREAD: u8 = 4;
354 pub const RESOURCE_TYPE_MUTEX: u8 = 5;
355 pub const RESOURCE_TYPE_SEMAPHORE: u8 = 6;
356 pub const RESOURCE_TYPE_CHANNEL: u8 = 7;
357 pub const RESOURCE_TYPE_WOULD_BLOCK: u8 = 255;
358
359 pub fn hardware_error(component: u8, error_code: u16) -> Self {
361 DbError::HardwareError {
362 component,
363 error_code,
364 #[cfg(feature = "std")]
365 description: String::new(),
366 #[cfg(not(feature = "std"))]
367 _description: (),
368 }
369 }
370
371 pub fn internal(code: u32) -> Self {
373 DbError::Internal {
374 code,
375 #[cfg(feature = "std")]
376 message: String::new(),
377 #[cfg(not(feature = "std"))]
378 _message: (),
379 }
380 }
381
382 pub fn is_network_error(&self) -> bool {
384 matches!(self, DbError::ConnectionFailed { .. })
385 }
386
387 pub fn is_capacity_error(&self) -> bool {
389 matches!(self, DbError::BufferFull { .. })
390 }
391
392 pub fn is_hardware_error(&self) -> bool {
394 matches!(self, DbError::HardwareError { .. })
395 }
396
397 pub fn is_buffer_error(&self) -> bool {
399 matches!(
400 self,
401 DbError::BufferFull { .. }
402 | DbError::BufferEmpty
403 | DbError::BufferLagged { .. }
404 | DbError::BufferClosed { .. }
405 )
406 }
407
408 pub fn is_database_error(&self) -> bool {
410 matches!(
411 self,
412 DbError::RecordNotFound { .. }
413 | DbError::RecordKeyNotFound { .. }
414 | DbError::InvalidRecordId { .. }
415 | DbError::TypeMismatch { .. }
416 | DbError::AmbiguousType { .. }
417 | DbError::DuplicateRecordKey { .. }
418 | DbError::InvalidOperation { .. }
419 | DbError::PermissionDenied { .. }
420 )
421 }
422
423 pub fn is_configuration_error(&self) -> bool {
425 matches!(self, DbError::MissingConfiguration { .. })
426 }
427
428 pub fn is_runtime_error(&self) -> bool {
430 matches!(
431 self,
432 DbError::RuntimeError { .. } | DbError::ResourceUnavailable { .. }
433 )
434 }
435
436 pub fn is_transform_error(&self) -> bool {
438 matches!(
439 self,
440 DbError::CyclicDependency { .. } | DbError::TransformInputNotFound { .. }
441 )
442 }
443
444 #[cfg(feature = "std")]
446 pub fn is_io_error(&self) -> bool {
447 matches!(self, DbError::Io { .. } | DbError::IoWithContext { .. })
448 }
449
450 #[cfg(feature = "std")]
452 pub fn is_json_error(&self) -> bool {
453 matches!(self, DbError::Json { .. } | DbError::JsonWithContext { .. })
454 }
455
456 pub const fn error_code(&self) -> u32 {
458 match self {
459 DbError::ConnectionFailed { .. } => 0x1002,
461
462 DbError::BufferFull { .. } => 0x2002,
464
465 DbError::MissingConfiguration { .. } => 0x4002,
467
468 DbError::ResourceUnavailable { .. } => 0x5002,
470
471 DbError::HardwareError { .. } => 0x6001,
473
474 DbError::Internal { .. } => 0x7001,
476 DbError::RuntimeError { .. } => 0x7002,
477 DbError::RecordNotFound { .. } => 0x7003,
478 DbError::InvalidOperation { .. } => 0x7004,
479 DbError::PermissionDenied { .. } => 0x7005,
480 DbError::RecordKeyNotFound { .. } => 0x7006,
481 DbError::InvalidRecordId { .. } => 0x7007,
482 DbError::TypeMismatch { .. } => 0x7008,
483 DbError::AmbiguousType { .. } => 0x7009,
484 DbError::DuplicateRecordKey { .. } => 0x700A,
485
486 DbError::CyclicDependency { .. } => 0xC001,
488 DbError::TransformInputNotFound { .. } => 0xC002,
489
490 #[cfg(feature = "std")]
492 DbError::Io { .. } => 0x8001,
493 #[cfg(feature = "std")]
494 DbError::IoWithContext { .. } => 0x8002,
495
496 #[cfg(feature = "std")]
498 DbError::Json { .. } => 0x9001,
499 #[cfg(feature = "std")]
500 DbError::JsonWithContext { .. } => 0x9002,
501
502 DbError::BufferLagged { .. } => 0xA001,
504 DbError::BufferClosed { .. } => 0xA002,
505 DbError::BufferEmpty => 0xA003,
506
507 #[cfg(feature = "std")]
509 DbError::AttachFailed { .. } => 0xB001,
510 #[cfg(feature = "std")]
511 DbError::DetachFailed { .. } => 0xB002,
512 #[cfg(feature = "std")]
513 DbError::SetTimeout => 0xB003,
514 #[cfg(feature = "std")]
515 DbError::GetTimeout => 0xB004,
516 #[cfg(feature = "std")]
517 DbError::RuntimeShutdown => 0xB005,
518 }
519 }
520
521 pub const fn error_category(&self) -> u32 {
523 self.error_code() & 0xF000
524 }
525
526 #[cfg(feature = "std")]
528 fn prepend_context<S: Into<String>>(existing: &mut String, new_context: S) {
529 let new_context = new_context.into();
530 existing.insert_str(0, ": ");
531 existing.insert_str(0, &new_context);
532 }
533
534 #[cfg(feature = "std")]
536 pub fn with_context<S: Into<String>>(self, context: S) -> Self {
537 match self {
538 DbError::ConnectionFailed {
539 mut reason,
540 endpoint,
541 } => {
542 Self::prepend_context(&mut reason, context);
543 DbError::ConnectionFailed { endpoint, reason }
544 }
545 DbError::BufferFull {
546 size,
547 mut buffer_name,
548 } => {
549 Self::prepend_context(&mut buffer_name, context);
550 DbError::BufferFull { size, buffer_name }
551 }
552 DbError::BufferLagged {
553 lag_count,
554 mut buffer_name,
555 } => {
556 Self::prepend_context(&mut buffer_name, context);
557 DbError::BufferLagged {
558 lag_count,
559 buffer_name,
560 }
561 }
562 DbError::BufferClosed { mut buffer_name } => {
563 Self::prepend_context(&mut buffer_name, context);
564 DbError::BufferClosed { buffer_name }
565 }
566 DbError::BufferEmpty => DbError::BufferEmpty,
567 DbError::RecordNotFound { mut record_name } => {
568 Self::prepend_context(&mut record_name, context);
569 DbError::RecordNotFound { record_name }
570 }
571 DbError::RecordKeyNotFound { mut key } => {
572 Self::prepend_context(&mut key, context);
573 DbError::RecordKeyNotFound { key }
574 }
575 DbError::InvalidRecordId { id } => {
576 DbError::InvalidRecordId { id }
578 }
579 DbError::TypeMismatch {
580 record_id,
581 mut expected_type,
582 } => {
583 Self::prepend_context(&mut expected_type, context);
584 DbError::TypeMismatch {
585 record_id,
586 expected_type,
587 }
588 }
589 DbError::AmbiguousType {
590 count,
591 mut type_name,
592 } => {
593 Self::prepend_context(&mut type_name, context);
594 DbError::AmbiguousType { count, type_name }
595 }
596 DbError::DuplicateRecordKey { mut key } => {
597 Self::prepend_context(&mut key, context);
598 DbError::DuplicateRecordKey { key }
599 }
600 DbError::InvalidOperation {
601 operation,
602 mut reason,
603 } => {
604 Self::prepend_context(&mut reason, context);
605 DbError::InvalidOperation { operation, reason }
606 }
607 DbError::PermissionDenied { mut operation } => {
608 Self::prepend_context(&mut operation, context);
609 DbError::PermissionDenied { operation }
610 }
611 DbError::MissingConfiguration { mut parameter } => {
612 Self::prepend_context(&mut parameter, context);
613 DbError::MissingConfiguration { parameter }
614 }
615 DbError::RuntimeError { mut message } => {
616 Self::prepend_context(&mut message, context);
617 DbError::RuntimeError { message }
618 }
619 DbError::ResourceUnavailable {
620 resource_type,
621 mut resource_name,
622 } => {
623 Self::prepend_context(&mut resource_name, context);
624 DbError::ResourceUnavailable {
625 resource_type,
626 resource_name,
627 }
628 }
629 DbError::HardwareError {
630 component,
631 error_code,
632 mut description,
633 } => {
634 Self::prepend_context(&mut description, context);
635 DbError::HardwareError {
636 component,
637 error_code,
638 description,
639 }
640 }
641 DbError::Internal { code, mut message } => {
642 Self::prepend_context(&mut message, context);
643 DbError::Internal { code, message }
644 }
645 #[cfg(feature = "std")]
647 DbError::AttachFailed { mut message } => {
648 Self::prepend_context(&mut message, context);
649 DbError::AttachFailed { message }
650 }
651 #[cfg(feature = "std")]
652 DbError::DetachFailed { mut message } => {
653 Self::prepend_context(&mut message, context);
654 DbError::DetachFailed { message }
655 }
656 #[cfg(feature = "std")]
658 DbError::SetTimeout => DbError::SetTimeout,
659 #[cfg(feature = "std")]
660 DbError::GetTimeout => DbError::GetTimeout,
661 #[cfg(feature = "std")]
662 DbError::RuntimeShutdown => DbError::RuntimeShutdown,
663 DbError::CyclicDependency { .. } => self,
665 DbError::TransformInputNotFound { .. } => self,
666 #[cfg(feature = "std")]
668 DbError::Io { source } => DbError::IoWithContext {
669 context: context.into(),
670 source,
671 },
672 #[cfg(feature = "std")]
673 DbError::Json { source } => DbError::JsonWithContext {
674 context: context.into(),
675 source,
676 },
677 #[cfg(feature = "std")]
679 DbError::IoWithContext {
680 context: mut ctx,
681 source,
682 } => {
683 Self::prepend_context(&mut ctx, context);
684 DbError::IoWithContext {
685 context: ctx,
686 source,
687 }
688 }
689 #[cfg(feature = "std")]
690 DbError::JsonWithContext {
691 context: mut ctx,
692 source,
693 } => {
694 Self::prepend_context(&mut ctx, context);
695 DbError::JsonWithContext {
696 context: ctx,
697 source,
698 }
699 }
700 }
701 }
702
703 #[cfg(feature = "std")]
705 pub fn into_anyhow(self) -> anyhow::Error {
706 self.into()
707 }
708}
709
710pub type DbResult<T> = Result<T, DbError>;
712
713impl From<aimdb_executor::ExecutorError> for DbError {
722 fn from(err: aimdb_executor::ExecutorError) -> Self {
723 use aimdb_executor::ExecutorError;
724
725 match err {
726 ExecutorError::SpawnFailed { message } => {
727 #[cfg(feature = "std")]
728 {
729 DbError::RuntimeError { message }
730 }
731 #[cfg(not(feature = "std"))]
732 {
733 let _ = message; DbError::RuntimeError { _message: () }
735 }
736 }
737 ExecutorError::RuntimeUnavailable { message } => {
738 #[cfg(feature = "std")]
739 {
740 DbError::RuntimeError { message }
741 }
742 #[cfg(not(feature = "std"))]
743 {
744 let _ = message; DbError::RuntimeError { _message: () }
746 }
747 }
748 ExecutorError::TaskJoinFailed { message } => {
749 #[cfg(feature = "std")]
750 {
751 DbError::RuntimeError { message }
752 }
753 #[cfg(not(feature = "std"))]
754 {
755 let _ = message; DbError::RuntimeError { _message: () }
757 }
758 }
759 ExecutorError::QueueClosed => {
760 #[cfg(feature = "std")]
761 {
762 DbError::RuntimeError {
763 message: "join queue closed".to_string(),
764 }
765 }
766 #[cfg(not(feature = "std"))]
767 {
768 DbError::RuntimeError { _message: () }
769 }
770 }
771 }
772 }
773}
774
775#[cfg(test)]
776mod tests {
777 use super::*;
778
779 #[test]
780 fn test_error_size_constraint() {
781 let size = core::mem::size_of::<DbError>();
782 assert!(
783 size <= 64,
784 "DbError size ({} bytes) exceeds 64-byte embedded limit",
785 size
786 );
787 }
788
789 #[test]
790 fn test_error_codes() {
791 let connection_error = DbError::ConnectionFailed {
792 #[cfg(feature = "std")]
793 endpoint: "localhost".to_string(),
794 #[cfg(feature = "std")]
795 reason: "timeout".to_string(),
796 #[cfg(not(feature = "std"))]
797 _endpoint: (),
798 #[cfg(not(feature = "std"))]
799 _reason: (),
800 };
801 assert_eq!(connection_error.error_code(), 0x1002);
802 assert_eq!(connection_error.error_category(), 0x1000);
803
804 let buffer_error = DbError::BufferFull {
805 size: 1024,
806 #[cfg(feature = "std")]
807 buffer_name: String::new(),
808 #[cfg(not(feature = "std"))]
809 _buffer_name: (),
810 };
811 assert_eq!(buffer_error.error_code(), 0x2002);
812 }
813
814 #[test]
815 fn test_helper_methods() {
816 let connection_error = DbError::ConnectionFailed {
817 #[cfg(feature = "std")]
818 endpoint: "localhost".to_string(),
819 #[cfg(feature = "std")]
820 reason: "timeout".to_string(),
821 #[cfg(not(feature = "std"))]
822 _endpoint: (),
823 #[cfg(not(feature = "std"))]
824 _reason: (),
825 };
826
827 assert!(connection_error.is_network_error());
828 assert!(!connection_error.is_capacity_error());
829 assert!(!connection_error.is_hardware_error());
830
831 let hardware_error = DbError::hardware_error(2, 404);
832 assert!(hardware_error.is_hardware_error());
833
834 let internal_error = DbError::internal(500);
835 assert!(matches!(
836 internal_error,
837 DbError::Internal { code: 500, .. }
838 ));
839 }
840
841 #[cfg(feature = "std")]
842 #[test]
843 fn test_error_context() {
844 let error = DbError::ConnectionFailed {
845 endpoint: "localhost:5432".to_string(),
846 reason: "timeout".to_string(),
847 }
848 .with_context("Database connection")
849 .with_context("Application startup");
850
851 if let DbError::ConnectionFailed { reason, .. } = error {
852 assert_eq!(reason, "Application startup: Database connection: timeout");
853 } else {
854 panic!("Expected ConnectionFailed");
855 }
856 }
857
858 #[cfg(feature = "std")]
859 #[test]
860 fn test_io_json_conversions() {
861 let io_error = std::io::Error::other("File not found");
862 let db_error: DbError = io_error.into();
863 assert!(matches!(db_error, DbError::Io { .. }));
864
865 let json_error = serde_json::from_str::<serde_json::Value>("invalid").unwrap_err();
866 let db_error: DbError = json_error.into();
867 assert!(matches!(db_error, DbError::Json { .. }));
868 }
869
870 #[test]
871 fn test_buffer_empty() {
872 let buffer = DbError::BufferEmpty;
873 assert!(buffer.is_buffer_error());
874 assert!(!buffer.is_network_error());
875 }
876
877 #[cfg(feature = "std")]
878 #[test]
879 fn test_configuration_error() {
880 let configuration = DbError::MissingConfiguration {
881 parameter: "my_parameter".to_string(),
882 };
883 assert!(configuration.is_configuration_error());
884 assert!(!configuration.is_buffer_error());
885 }
886
887 #[cfg(feature = "std")]
888 #[test]
889 fn test_runtime_error() {
890 let runtime = DbError::RuntimeError {
891 message: "Hello, World".to_string(),
892 };
893 assert!(runtime.is_runtime_error());
894 assert!(!runtime.is_buffer_error());
895 }
896
897 #[test]
898 fn test_database_error() {
899 let database = DbError::InvalidRecordId { id: 5 };
900 assert!(database.is_database_error());
901 assert!(!database.is_buffer_error());
902 }
903
904 #[cfg(feature = "std")]
905 #[test]
906 fn test_transform_error() {
907 let transform = DbError::CyclicDependency {
908 records: vec!["Hello, World!".to_string()],
909 };
910 assert!(transform.is_transform_error());
911 assert!(!transform.is_buffer_error());
912 }
913
914 #[cfg(feature = "std")]
915 #[test]
916 fn test_io_error() {
917 let io_error = std::io::Error::other("test");
918 let db_error: DbError = io_error.into();
919 assert!(db_error.is_io_error());
920 assert!(!db_error.is_buffer_error());
921 }
922
923 #[cfg(feature = "std")]
924 #[test]
925 fn test_json_error() {
926 let json_error = serde_json::from_str::<serde_json::Value>("invalid").unwrap_err();
927 let db_error: DbError = json_error.into();
928 assert!(db_error.is_json_error());
929 assert!(!db_error.is_buffer_error());
930 }
931}