1use backtrace::Backtrace;
2use serde::{de, ser};
3use std::error::Error;
4use std::fmt::{Debug, Display, Formatter};
5use std::result::Result;
6
7use crate::{atomic, Atomic};
8
9#[derive(Debug, PartialEq, Eq, Clone)]
24pub enum ErrorKind {
25 FilterError,
28
29 IndexingError,
32 IndexNotFound,
34 IndexAlreadyExists,
36 IndexBuildFailed,
38 IndexCorrupted,
40 IndexTypeMismatch,
42 IndexingInProgress,
44
45 InvalidId,
48 NotIdentifiable,
50 NotFound,
52
53 InvalidOperation,
56
57 IOError,
60 DiskFull,
62 FileNotFound,
64 PermissionDenied,
66 FileCorrupted,
68 FileAccessError,
70
71 EncodingError,
74 ObjectMappingError,
76
77 SecurityError,
80
81 UniqueConstraintViolation,
84
85 ValidationError,
88 InvalidDataType,
90 InvalidFieldName,
92 MissingRequiredField,
94
95 CollectionNotFound,
98 RepositoryNotFound,
100
101 EventError,
104
105 PluginError,
108 PluginLoadFailed,
110
111 BackendError,
114 StoreNotInitialized,
116 StoreAlreadyClosed,
118 TransactionConflict,
122
123 MigrationError,
126
127 Extension(String),
131
132 InternalError,
135}
136
137impl Display for ErrorKind {
138 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
139 match self {
140 ErrorKind::FilterError => write!(f, "Filter error"),
141 ErrorKind::IndexingError => write!(f, "Indexing error"),
142 ErrorKind::IndexNotFound => write!(f, "Index not found"),
143 ErrorKind::IndexAlreadyExists => write!(f, "Index already exists"),
144 ErrorKind::IndexBuildFailed => write!(f, "Index build failed"),
145 ErrorKind::IndexCorrupted => write!(f, "Index corrupted"),
146 ErrorKind::IndexTypeMismatch => write!(f, "Index type mismatch"),
147 ErrorKind::IndexingInProgress => write!(f, "Indexing in progress"),
148 ErrorKind::InvalidId => write!(f, "Invalid ID"),
149 ErrorKind::NotIdentifiable => write!(f, "Not identifiable"),
150 ErrorKind::NotFound => write!(f, "Not found"),
151 ErrorKind::InvalidOperation => write!(f, "Invalid operation"),
152 ErrorKind::IOError => write!(f, "IO error"),
153 ErrorKind::DiskFull => write!(f, "Disk full"),
154 ErrorKind::FileNotFound => write!(f, "File not found"),
155 ErrorKind::PermissionDenied => write!(f, "Permission denied"),
156 ErrorKind::FileCorrupted => write!(f, "File corrupted"),
157 ErrorKind::FileAccessError => write!(f, "File access error"),
158 ErrorKind::EncodingError => write!(f, "Encoding error"),
159 ErrorKind::ObjectMappingError => write!(f, "Object mapping error"),
160 ErrorKind::SecurityError => write!(f, "Security error"),
161 ErrorKind::UniqueConstraintViolation => write!(f, "Unique constraint violation"),
162 ErrorKind::ValidationError => write!(f, "Validation error"),
163 ErrorKind::InvalidDataType => write!(f, "Invalid data type"),
164 ErrorKind::InvalidFieldName => write!(f, "Invalid field name"),
165 ErrorKind::MissingRequiredField => write!(f, "Missing required field"),
166 ErrorKind::CollectionNotFound => write!(f, "Collection not found"),
167 ErrorKind::RepositoryNotFound => write!(f, "Repository not found"),
168 ErrorKind::EventError => write!(f, "Event error"),
169 ErrorKind::PluginError => write!(f, "Plugin error"),
170 ErrorKind::PluginLoadFailed => write!(f, "Plugin load failed"),
171 ErrorKind::BackendError => write!(f, "Backend error"),
172 ErrorKind::StoreNotInitialized => write!(f, "Store not initialized"),
173 ErrorKind::StoreAlreadyClosed => write!(f, "Store already closed"),
174 ErrorKind::TransactionConflict => write!(f, "Transaction conflict"),
175 ErrorKind::MigrationError => write!(f, "Migration error"),
176 ErrorKind::Extension(name) => write!(f, "{} error", name),
177 ErrorKind::InternalError => write!(f, "Internal error"),
178 }
179 }
180}
181
182#[derive(Clone)]
205pub struct NitriteError {
206 message: String,
207 error_kind: ErrorKind,
208 cause: Option<Box<NitriteError>>,
209 backtrace: Atomic<Backtrace>,
210}
211
212impl NitriteError {
213 pub fn new(message: &str, error_kind: ErrorKind) -> Self {
224 NitriteError {
225 message: message.to_string(),
226 error_kind,
227 cause: None,
228 backtrace: atomic(Backtrace::new()),
229 }
230 }
231
232 pub fn new_with_cause(message: &str, error_type: ErrorKind, cause: NitriteError) -> Self {
246 NitriteError {
247 message: message.to_string(),
248 error_kind: error_type,
249 cause: Some(Box::new(cause)),
250 backtrace: atomic(Backtrace::new()),
251 }
252 }
253
254 pub fn message(&self) -> &str {
255 &self.message
256 }
257
258 pub fn kind(&self) -> &ErrorKind {
259 &self.error_kind
260 }
261
262 pub fn cause(&self) -> Option<&NitriteError> {
263 self.cause.as_deref()
264 }
265}
266
267impl Display for NitriteError {
268 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
269 write!(f, "{}", self.message)
270 }
271}
272
273impl Debug for NitriteError {
274 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
275 match &self.cause {
277 Some(cause) => write!(f, "{}\nCaused by: {:?}", self.message, cause),
278 None => write!(f, "{}\n{:?}", self.message, self.backtrace.read()),
279 }
280 }
281}
282
283impl Error for NitriteError {
284 fn source(&self) -> Option<&(dyn Error + 'static)> {
285 match &self.cause {
286 Some(cause) => Some(cause.as_ref()),
287 None => None,
288 }
289 }
290}
291
292pub type NitriteResult<T> = Result<T, NitriteError>;
310
311impl de::Error for NitriteError {
312 fn custom<T: Display>(msg: T) -> Self {
313 NitriteError::new(&msg.to_string(), ErrorKind::ObjectMappingError)
314 }
315}
316
317impl ser::Error for NitriteError {
318 fn custom<T: Display>(msg: T) -> Self {
319 NitriteError::new(&msg.to_string(), ErrorKind::ObjectMappingError)
320 }
321}
322
323impl From<std::io::Error> for NitriteError {
325 fn from(err: std::io::Error) -> Self {
326 let error_kind = match err.kind() {
327 std::io::ErrorKind::NotFound => ErrorKind::FileNotFound,
328 std::io::ErrorKind::PermissionDenied => ErrorKind::PermissionDenied,
329 std::io::ErrorKind::AlreadyExists => ErrorKind::FileCorrupted,
330 _ => ErrorKind::IOError,
331 };
332 NitriteError::new(&format!("IO error: {}", err), error_kind)
333 }
334}
335
336impl From<std::string::FromUtf8Error> for NitriteError {
337 fn from(err: std::string::FromUtf8Error) -> Self {
338 NitriteError::new(
339 &format!("UTF-8 encoding error: {}", err),
340 ErrorKind::EncodingError,
341 )
342 }
343}
344
345impl From<std::fmt::Error> for NitriteError {
346 fn from(err: std::fmt::Error) -> Self {
347 NitriteError::new(
348 &format!("Formatting error: {}", err),
349 ErrorKind::InternalError,
350 )
351 }
352}
353
354impl From<std::num::ParseIntError> for NitriteError {
355 fn from(err: std::num::ParseIntError) -> Self {
356 NitriteError::new(
357 &format!("Integer parsing error: {}", err),
358 ErrorKind::InvalidDataType,
359 )
360 }
361}
362
363impl From<std::num::ParseFloatError> for NitriteError {
364 fn from(err: std::num::ParseFloatError) -> Self {
365 NitriteError::new(
366 &format!("Float parsing error: {}", err),
367 ErrorKind::InvalidDataType,
368 )
369 }
370}
371
372impl From<String> for NitriteError {
373 fn from(msg: String) -> Self {
374 NitriteError::new(&msg, ErrorKind::InternalError)
375 }
376}
377
378impl From<&str> for NitriteError {
379 fn from(msg: &str) -> Self {
380 NitriteError::new(msg, ErrorKind::InternalError)
381 }
382}
383
384#[cfg(test)]
385mod tests {
386 use super::*;
387
388 fn create_io_error() -> Box<dyn Error + Send + Sync> {
389 Box::new(std::io::Error::other("IO Error"))
390 }
391
392 #[test]
393 fn nitrite_error_new_creates_error() {
394 let error = NitriteError::new("An error occurred", ErrorKind::IOError);
395 assert_eq!(error.message, "An error occurred");
396 assert_eq!(error.error_kind, ErrorKind::IOError);
397 assert!(error.cause.is_none());
398 }
399
400 #[test]
401 fn nitrite_error_new_with_cause_creates_error() {
402 let cause = create_io_error();
403 let error = NitriteError::new_with_cause(
404 "An error occurred",
405 ErrorKind::IOError,
406 NitriteError::new(&cause.to_string(), ErrorKind::IOError),
407 );
408 assert_eq!(error.message, "An error occurred");
409 assert_eq!(error.error_kind, ErrorKind::IOError);
410 assert!(error.cause.is_some());
411 }
412
413 #[test]
414 fn nitrite_error_message_returns_message() {
415 let error = NitriteError::new("An error occurred", ErrorKind::IOError);
416 assert_eq!(error.message(), "An error occurred");
417 }
418
419 #[test]
420 fn nitrite_error_kind_returns_kind() {
421 let error = NitriteError::new("An error occurred", ErrorKind::IOError);
422 assert_eq!(error.kind(), &ErrorKind::IOError);
423 }
424
425 #[test]
426 fn nitrite_error_cause_returns_cause() {
427 let cause = create_io_error();
428 let error = NitriteError::new_with_cause(
429 "An error occurred",
430 ErrorKind::IOError,
431 NitriteError::new(&cause.to_string(), ErrorKind::IOError),
432 );
433 assert!(error.cause().is_some());
434 }
435
436 #[test]
437 fn nitrite_error_cause_returns_none_when_no_cause() {
438 let error = NitriteError::new("An error occurred", ErrorKind::IOError);
439 assert!(error.cause().is_none());
440 }
441
442 #[test]
443 fn nitrite_error_display_formats_correctly() {
444 let error = NitriteError::new("An error occurred", ErrorKind::IOError);
445 let formatted = format!("{}", error);
446 assert_eq!(formatted, "An error occurred");
447 }
448
449 #[test]
450 fn nitrite_error_debug_formats_correctly() {
451 let error = NitriteError::new("An error occurred", ErrorKind::IOError);
452 let formatted = format!("{:?}", error);
453 assert!(formatted.contains("An error occurred"));
454 }
455
456 #[test]
457 fn nitrite_error_debug_formats_with_cause() {
458 let cause = create_io_error();
459 let error = NitriteError::new_with_cause(
460 "An error occurred",
461 ErrorKind::IOError,
462 NitriteError::new(&cause.to_string(), ErrorKind::IOError),
463 );
464 let formatted = format!("{:?}", error);
465 assert!(formatted.contains("An error occurred"));
466 assert!(formatted.contains("Caused by:"));
467 }
468
469 #[test]
470 fn nitrite_error_source_returns_cause() {
471 let cause = create_io_error();
472 let error = NitriteError::new_with_cause(
473 "An error occurred",
474 ErrorKind::IOError,
475 NitriteError::new(&cause.to_string(), ErrorKind::IOError),
476 );
477 assert!(error.source().is_some());
478 }
479
480 #[test]
481 fn nitrite_error_source_returns_none_when_no_cause() {
482 let error = NitriteError::new("An error occurred", ErrorKind::IOError);
483 assert!(error.source().is_none());
484 }
485
486 #[test]
487 fn nitrite_error_ser_custom_creates_error() {
488 let error = NitriteError::new("Custom error", ErrorKind::ObjectMappingError);
489 assert_eq!(error.message(), "Custom error");
490 assert_eq!(error.kind(), &ErrorKind::ObjectMappingError);
491 }
492
493 #[test]
495 fn test_filter_errors() {
496 let filter_error = NitriteError::new("Invalid filter syntax", ErrorKind::FilterError);
497 assert_eq!(filter_error.kind(), &ErrorKind::FilterError);
498 }
499
500 #[test]
502 fn test_id_errors() {
503 let invalid_id = NitriteError::new("Invalid ID format", ErrorKind::InvalidId);
504 assert_eq!(invalid_id.kind(), &ErrorKind::InvalidId);
505
506 let not_identifiable = NitriteError::new("Entity not identifiable", ErrorKind::NotIdentifiable);
507 assert_eq!(not_identifiable.kind(), &ErrorKind::NotIdentifiable);
508 }
509
510 #[test]
512 fn test_indexing_errors() {
513 let index_error = NitriteError::new("Indexing failed", ErrorKind::IndexingError);
514 assert_eq!(index_error.kind(), &ErrorKind::IndexingError);
515
516 let not_found = NitriteError::new("Index not found", ErrorKind::IndexNotFound);
517 assert_eq!(not_found.kind(), &ErrorKind::IndexNotFound);
518
519 let exists = NitriteError::new("Index already exists", ErrorKind::IndexAlreadyExists);
520 assert_eq!(exists.kind(), &ErrorKind::IndexAlreadyExists);
521
522 let build_failed = NitriteError::new("Index build failed", ErrorKind::IndexBuildFailed);
523 assert_eq!(build_failed.kind(), &ErrorKind::IndexBuildFailed);
524
525 let corrupted = NitriteError::new("Index corrupted", ErrorKind::IndexCorrupted);
526 assert_eq!(corrupted.kind(), &ErrorKind::IndexCorrupted);
527
528 let type_mismatch = NitriteError::new("Index type mismatch", ErrorKind::IndexTypeMismatch);
529 assert_eq!(type_mismatch.kind(), &ErrorKind::IndexTypeMismatch);
530
531 let in_progress = NitriteError::new("Indexing in progress", ErrorKind::IndexingInProgress);
532 assert_eq!(in_progress.kind(), &ErrorKind::IndexingInProgress);
533 }
534
535 #[test]
537 fn test_io_errors() {
538 let io_error = NitriteError::new("IO error", ErrorKind::IOError);
539 assert_eq!(io_error.kind(), &ErrorKind::IOError);
540
541 let disk_full = NitriteError::new("Disk full", ErrorKind::DiskFull);
542 assert_eq!(disk_full.kind(), &ErrorKind::DiskFull);
543
544 let file_not_found = NitriteError::new("File not found", ErrorKind::FileNotFound);
545 assert_eq!(file_not_found.kind(), &ErrorKind::FileNotFound);
546
547 let permission = NitriteError::new("Permission denied", ErrorKind::PermissionDenied);
548 assert_eq!(permission.kind(), &ErrorKind::PermissionDenied);
549
550 let corrupted = NitriteError::new("File corrupted", ErrorKind::FileCorrupted);
551 assert_eq!(corrupted.kind(), &ErrorKind::FileCorrupted);
552
553 let access = NitriteError::new("File access error", ErrorKind::FileAccessError);
554 assert_eq!(access.kind(), &ErrorKind::FileAccessError);
555 }
556
557 #[test]
559 fn test_security_errors() {
560 let security = NitriteError::new("Security error", ErrorKind::SecurityError);
561 assert_eq!(security.kind(), &ErrorKind::SecurityError);
562 }
563
564 #[test]
566 fn test_constraint_errors() {
567 let unique = NitriteError::new("Unique constraint violated", ErrorKind::UniqueConstraintViolation);
568 assert_eq!(unique.kind(), &ErrorKind::UniqueConstraintViolation);
569 }
570
571 #[test]
573 fn test_validation_errors() {
574 let validation = NitriteError::new("Validation failed", ErrorKind::ValidationError);
575 assert_eq!(validation.kind(), &ErrorKind::ValidationError);
576
577 let invalid_type = NitriteError::new("Invalid data type", ErrorKind::InvalidDataType);
578 assert_eq!(invalid_type.kind(), &ErrorKind::InvalidDataType);
579
580 let invalid_name = NitriteError::new("Invalid field name", ErrorKind::InvalidFieldName);
581 assert_eq!(invalid_name.kind(), &ErrorKind::InvalidFieldName);
582
583 let missing = NitriteError::new("Missing required field", ErrorKind::MissingRequiredField);
584 assert_eq!(missing.kind(), &ErrorKind::MissingRequiredField);
585 }
586
587 #[test]
589 fn test_collection_repository_errors() {
590 let not_found = NitriteError::new("Collection not found", ErrorKind::CollectionNotFound);
591 assert_eq!(not_found.kind(), &ErrorKind::CollectionNotFound);
592
593 let repo_not_found = NitriteError::new("Repository not found", ErrorKind::RepositoryNotFound);
594 assert_eq!(repo_not_found.kind(), &ErrorKind::RepositoryNotFound);
595 }
596
597 #[test]
599 fn test_event_subscription_errors() {
600 let event = NitriteError::new("Event error", ErrorKind::EventError);
601 assert_eq!(event.kind(), &ErrorKind::EventError);
602 }
603
604 #[test]
606 fn test_plugin_errors() {
607 let plugin = NitriteError::new("Plugin error", ErrorKind::PluginError);
608 assert_eq!(plugin.kind(), &ErrorKind::PluginError);
609
610 let load_failed = NitriteError::new("Plugin load failed", ErrorKind::PluginLoadFailed);
611 assert_eq!(load_failed.kind(), &ErrorKind::PluginLoadFailed);
612 }
613
614 #[test]
616 fn test_backend_store_errors() {
617 let backend = NitriteError::new("Backend error", ErrorKind::BackendError);
618 assert_eq!(backend.kind(), &ErrorKind::BackendError);
619
620 let not_init = NitriteError::new("Store not initialized", ErrorKind::StoreNotInitialized);
621 assert_eq!(not_init.kind(), &ErrorKind::StoreNotInitialized);
622
623 let closed = NitriteError::new("Store already closed", ErrorKind::StoreAlreadyClosed);
624 assert_eq!(closed.kind(), &ErrorKind::StoreAlreadyClosed);
625 }
626
627 #[test]
629 fn test_internal_errors() {
630 let internal = NitriteError::new("Internal error", ErrorKind::InternalError);
631 assert_eq!(internal.kind(), &ErrorKind::InternalError);
632 }
633
634 #[test]
636 fn test_extension_errors() {
637 let spatial_ext = NitriteError::new("Spatial index error", ErrorKind::Extension("spatial".to_string()));
639 assert_eq!(spatial_ext.kind(), &ErrorKind::Extension("spatial".to_string()));
640
641 let fulltext_ext = NitriteError::new("Full-text search error", ErrorKind::Extension("FullText".to_string()));
642 assert_eq!(fulltext_ext.kind(), &ErrorKind::Extension("FullText".to_string()));
643
644 assert_ne!(spatial_ext.kind(), fulltext_ext.kind());
646
647 let display = format!("{}", ErrorKind::Extension("MyExtension".to_string()));
649 assert_eq!(display, "MyExtension error");
650 }
651
652 #[test]
654 fn test_error_chain_with_different_kinds() {
655 let root_cause = NitriteError::new("File not found", ErrorKind::FileNotFound);
656 let mid_level = NitriteError::new_with_cause(
657 "Failed to read store",
658 ErrorKind::IOError,
659 root_cause,
660 );
661 let top_level = NitriteError::new_with_cause(
662 "Cannot initialize database",
663 ErrorKind::BackendError,
664 mid_level,
665 );
666
667 assert_eq!(top_level.kind(), &ErrorKind::BackendError);
668 assert!(top_level.cause().is_some());
669
670 if let Some(cause_box) = top_level.cause() {
671 assert_eq!(cause_box.kind(), &ErrorKind::IOError);
672 }
673 }
674
675 #[test]
677 fn test_error_kind_equality() {
678 let error1 = NitriteError::new("Error 1", ErrorKind::IndexNotFound);
679 let error2 = NitriteError::new("Error 2", ErrorKind::IndexNotFound);
680 let error3 = NitriteError::new("Error 3", ErrorKind::IndexAlreadyExists);
681
682 assert_eq!(error1.kind(), error2.kind());
683 assert_ne!(error1.kind(), error3.kind());
684 }
685
686 #[test]
688 fn test_error_message_preservation() {
689 let messages = vec![
690 ("Filter error message", ErrorKind::FilterError),
691 ("Index not found message", ErrorKind::IndexNotFound),
692 ("Disk full message", ErrorKind::DiskFull),
693 ("Object mapping error message", ErrorKind::ObjectMappingError),
694 ("Security error message", ErrorKind::SecurityError),
695 ];
696
697 for (msg, kind) in &messages {
698 let error = NitriteError::new(msg, kind.clone());
699 assert_eq!(error.message(), *msg);
700 assert_eq!(error.kind(), kind);
701 }
702 }
703
704 #[test]
706 fn test_from_io_error_not_found() {
707 let io_err = std::io::Error::new(std::io::ErrorKind::NotFound, "file not found");
708 let nitrite_err: NitriteError = io_err.into();
709
710 assert_eq!(nitrite_err.kind(), &ErrorKind::FileNotFound);
711 assert!(nitrite_err.message().contains("IO error"));
712 }
713
714 #[test]
715 fn test_from_io_error_permission_denied() {
716 let io_err = std::io::Error::new(std::io::ErrorKind::PermissionDenied, "permission denied");
717 let nitrite_err: NitriteError = io_err.into();
718
719 assert_eq!(nitrite_err.kind(), &ErrorKind::PermissionDenied);
720 assert!(nitrite_err.message().contains("IO error"));
721 }
722
723 #[test]
724 fn test_from_io_error_other() {
725 let io_err = std::io::Error::other("unknown io error");
726 let nitrite_err: NitriteError = io_err.into();
727
728 assert_eq!(nitrite_err.kind(), &ErrorKind::IOError);
729 assert!(nitrite_err.message().contains("IO error"));
730 }
731
732 #[test]
734 fn test_from_utf8_error() {
735 let invalid_utf8 = vec![0xFF, 0xFE];
736 let utf8_err = String::from_utf8(invalid_utf8).unwrap_err();
737 let nitrite_err: NitriteError = utf8_err.into();
738
739 assert_eq!(nitrite_err.kind(), &ErrorKind::EncodingError);
740 assert!(nitrite_err.message().contains("UTF-8"));
741 }
742
743 #[test]
745 fn test_from_fmt_error() {
746 use std::fmt::Write;
747 struct FailingWriter;
749
750 impl Write for FailingWriter {
751 fn write_str(&mut self, _: &str) -> std::fmt::Result {
752 Err(std::fmt::Error)
753 }
754 }
755
756 let fmt_err = write!(&mut FailingWriter, "test").unwrap_err();
757 let nitrite_err: NitriteError = fmt_err.into();
758
759 assert_eq!(nitrite_err.kind(), &ErrorKind::InternalError);
760 assert!(nitrite_err.message().contains("Formatting"));
761 }
762
763 #[test]
765 fn test_from_parse_int_error() {
766 let parse_err = "not_a_number".parse::<i32>().unwrap_err();
767 let nitrite_err: NitriteError = parse_err.into();
768
769 assert_eq!(nitrite_err.kind(), &ErrorKind::InvalidDataType);
770 assert!(nitrite_err.message().contains("Integer parsing"));
771 }
772
773 #[test]
775 fn test_from_parse_float_error() {
776 let parse_err = "not_a_float".parse::<f64>().unwrap_err();
777 let nitrite_err: NitriteError = parse_err.into();
778
779 assert_eq!(nitrite_err.kind(), &ErrorKind::InvalidDataType);
780 assert!(nitrite_err.message().contains("Float parsing"));
781 }
782
783 #[test]
785 fn test_from_string() {
786 let msg = String::from("test error message");
787 let nitrite_err: NitriteError = msg.into();
788
789 assert_eq!(nitrite_err.kind(), &ErrorKind::InternalError);
790 assert_eq!(nitrite_err.message(), "test error message");
791 }
792
793 #[test]
795 fn test_from_str() {
796 let msg = "test error message";
797 let nitrite_err: NitriteError = msg.into();
798
799 assert_eq!(nitrite_err.kind(), &ErrorKind::InternalError);
800 assert_eq!(nitrite_err.message(), "test error message");
801 }
802
803 #[test]
805 fn test_from_conversion_in_result_chain() {
806 fn operation_that_fails_with_io() -> NitriteResult<String> {
807 let io_err = std::io::Error::new(std::io::ErrorKind::NotFound, "file not found");
808 Err(io_err.into())
809 }
810
811 let result = operation_that_fails_with_io();
812 assert!(result.is_err());
813
814 if let Err(err) = result {
815 assert_eq!(err.kind(), &ErrorKind::FileNotFound);
816 }
817 }
818
819 #[test]
821 fn test_multiple_from_conversions() {
822 let io_err: NitriteError = std::io::Error::new(
823 std::io::ErrorKind::PermissionDenied,
824 "permission denied"
825 ).into();
826 assert_eq!(io_err.kind(), &ErrorKind::PermissionDenied);
827
828 let utf8_err: NitriteError = String::from_utf8(vec![0xFF]).unwrap_err().into();
829 assert_eq!(utf8_err.kind(), &ErrorKind::EncodingError);
830
831 let str_err: NitriteError = "string error".into();
832 assert_eq!(str_err.kind(), &ErrorKind::InternalError);
833 }
834
835 #[test]
837 fn test_question_mark_operator_with_from() {
838 fn parse_number_operation() -> NitriteResult<i32> {
839 let num: i32 = "12345".parse()?;
840 Ok(num)
841 }
842
843 let result = parse_number_operation();
844 assert!(result.is_ok());
845 assert_eq!(result.unwrap(), 12345);
846 }
847
848 #[test]
849 fn test_question_mark_operator_with_parse_error() {
850 fn parse_number_operation() -> NitriteResult<i32> {
851 let num: i32 = "not_a_number".parse()?;
852 Ok(num)
853 }
854
855 let result = parse_number_operation();
856 assert!(result.is_err());
857
858 if let Err(err) = result {
859 assert_eq!(err.kind(), &ErrorKind::InvalidDataType);
860 }
861 }
862}