1use std::collections::HashMap;
10use std::sync::Arc;
11use tokio::sync::RwLock;
12use serde::{Deserialize, Serialize};
13use sha2::{Sha256, Digest};
14
15#[derive(Debug, Clone)]
17pub struct DataIntegrity {
18 checksum_verifier: ChecksumVerifier,
20 version_verifier: VersionVerifier,
22 corruption_detector: CorruptionDetector,
24 stats: Arc<RwLock<IntegrityStats>>,
26 initialized: bool,
28}
29
30impl DataIntegrity {
31 pub fn new() -> Self {
33 Self {
34 checksum_verifier: ChecksumVerifier::new(),
35 version_verifier: VersionVerifier::new(),
36 corruption_detector: CorruptionDetector::new(),
37 stats: Arc::new(RwLock::new(IntegrityStats::new())),
38 initialized: false,
39 }
40 }
41
42 pub fn with_config(config: IntegrityConfig) -> Self {
44 Self {
45 checksum_verifier: ChecksumVerifier::with_config(config.checksum_config),
46 version_verifier: VersionVerifier::with_config(config.version_config),
47 corruption_detector: CorruptionDetector::with_config(config.corruption_config),
48 stats: Arc::new(RwLock::new(IntegrityStats::new())),
49 initialized: false,
50 }
51 }
52
53 pub async fn initialize(&mut self) -> Result<(), IntegrityError> {
55 self.checksum_verifier.initialize().await?;
56 self.version_verifier.initialize().await?;
57 self.corruption_detector.initialize().await?;
58
59 let mut stats = self.stats.write().await;
60 stats.reset();
61
62 self.initialized = true;
63 Ok(())
64 }
65
66 pub async fn shutdown(&mut self) -> Result<(), IntegrityError> {
68 self.initialized = false;
69 Ok(())
70 }
71
72 pub fn is_initialized(&self) -> bool {
74 self.initialized
75 }
76
77 pub async fn verify_integrity(&self, data: &[u8], metadata: &DataMetadata) -> Result<IntegrityResult, IntegrityError> {
79 if !self.initialized {
80 return Err(IntegrityError::NotInitialized);
81 }
82
83 let mut result = IntegrityResult::new();
84 let mut stats = self.stats.write().await;
85
86 match self.checksum_verifier.verify(data, &metadata.checksum).await {
88 Ok(checksum_result) => {
89 result.checksum_valid = checksum_result;
90 if checksum_result {
91 stats.checksum_verifications_passed += 1;
92 } else {
93 stats.checksum_verifications_failed += 1;
94 }
95 }
96 Err(e) => {
97 result.checksum_valid = false;
98 result.errors.push(IntegrityError::ChecksumVerificationFailed(e.to_string()));
99 stats.checksum_verifications_failed += 1;
100 }
101 }
102
103 match self.version_verifier.verify(&metadata.version, &metadata.expected_version).await {
105 Ok(version_result) => {
106 result.version_valid = version_result;
107 if version_result {
108 stats.version_verifications_passed += 1;
109 } else {
110 stats.version_verifications_failed += 1;
111 }
112 }
113 Err(e) => {
114 result.version_valid = false;
115 result.errors.push(IntegrityError::VersionVerificationFailed(e.to_string()));
116 stats.version_verifications_failed += 1;
117 }
118 }
119
120 match self.corruption_detector.detect_corruption(data, &metadata).await {
122 Ok(corruption_result) => {
123 result.corruption_detected = corruption_result.is_corrupted;
124 result.corruption_details = corruption_result.details;
125 if corruption_result.is_corrupted {
126 stats.corruption_detections += 1;
127 }
128 }
129 Err(e) => {
130 result.corruption_detected = false;
131 result.errors.push(IntegrityError::CorruptionDetectionFailed(e.to_string()));
132 }
133 }
134
135 result.overall_valid = result.checksum_valid && result.version_valid && !result.corruption_detected;
137
138 if result.overall_valid {
139 stats.total_verifications_passed += 1;
140 } else {
141 stats.total_verifications_failed += 1;
142 }
143
144 stats.total_verifications += 1;
145
146 Ok(result)
147 }
148
149 pub async fn generate_checksum(&self, data: &[u8]) -> Result<String, IntegrityError> {
151 if !self.initialized {
152 return Err(IntegrityError::NotInitialized);
153 }
154
155 self.checksum_verifier.generate(data).await
156 }
157
158 pub async fn validate_data_format(&self, data: &[u8], expected_format: &DataFormat) -> Result<bool, IntegrityError> {
160 if !self.initialized {
161 return Err(IntegrityError::NotInitialized);
162 }
163
164 match expected_format {
165 DataFormat::Json => {
166 match serde_json::from_slice::<serde_json::Value>(data) {
167 Ok(_) => Ok(true),
168 Err(_) => Ok(false),
169 }
170 }
171 DataFormat::Bincode => {
172 match bincode::deserialize::<serde_json::Value>(data) {
173 Ok(_) => Ok(true),
174 Err(_) => Ok(false),
175 }
176 }
177 DataFormat::Binary => Ok(true), DataFormat::Text => {
179 match std::str::from_utf8(data) {
180 Ok(_) => Ok(true),
181 Err(_) => Ok(false),
182 }
183 }
184 }
185 }
186
187 pub async fn get_stats(&self) -> IntegrityStats {
189 self.stats.read().await.clone()
190 }
191
192 pub async fn reset_stats(&self) {
194 let mut stats = self.stats.write().await;
195 stats.reset();
196 }
197}
198
199#[derive(Debug, Clone)]
201pub struct ChecksumVerifier {
202 algorithm: ChecksumAlgorithm,
204 initialized: bool,
206}
207
208impl ChecksumVerifier {
209 pub fn new() -> Self {
211 Self {
212 algorithm: ChecksumAlgorithm::Sha256,
213 initialized: false,
214 }
215 }
216
217 pub fn with_config(config: ChecksumConfig) -> Self {
219 Self {
220 algorithm: config.algorithm,
221 initialized: false,
222 }
223 }
224
225 pub async fn initialize(&mut self) -> Result<(), IntegrityError> {
227 self.initialized = true;
228 Ok(())
229 }
230
231 pub async fn generate(&self, data: &[u8]) -> Result<String, IntegrityError> {
233 if !self.initialized {
234 return Err(IntegrityError::NotInitialized);
235 }
236
237 match self.algorithm {
238 ChecksumAlgorithm::Sha256 => {
239 let mut hasher = Sha256::new();
240 hasher.update(data);
241 let result = hasher.finalize();
242 Ok(format!("{:x}", result))
243 }
244 ChecksumAlgorithm::Sha1 => {
245 use sha1::{Sha1, Digest};
246 let mut hasher = Sha1::new();
247 hasher.update(data);
248 let result = hasher.finalize();
249 Ok(format!("{:x}", result))
250 }
251 ChecksumAlgorithm::Md5 => {
252 let result = md5::compute(data);
253 Ok(format!("{:x}", result))
254 }
255 }
256 }
257
258 pub async fn verify(&self, data: &[u8], expected_checksum: &str) -> Result<bool, IntegrityError> {
260 if !self.initialized {
261 return Err(IntegrityError::NotInitialized);
262 }
263
264 let actual_checksum = self.generate(data).await?;
265 Ok(actual_checksum == expected_checksum)
266 }
267}
268
269#[derive(Debug, Clone)]
271pub struct VersionVerifier {
272 initialized: bool,
274}
275
276impl VersionVerifier {
277 pub fn new() -> Self {
279 Self {
280 initialized: false,
281 }
282 }
283
284 pub fn with_config(_config: VersionConfig) -> Self {
286 Self {
287 initialized: false,
288 }
289 }
290
291 pub async fn initialize(&mut self) -> Result<(), IntegrityError> {
293 self.initialized = true;
294 Ok(())
295 }
296
297 pub async fn verify(&self, actual_version: &str, expected_version: &str) -> Result<bool, IntegrityError> {
299 if !self.initialized {
300 return Err(IntegrityError::NotInitialized);
301 }
302
303 Ok(actual_version == expected_version)
304 }
305}
306
307#[derive(Debug, Clone)]
309pub struct CorruptionDetector {
310 initialized: bool,
312}
313
314impl CorruptionDetector {
315 pub fn new() -> Self {
317 Self {
318 initialized: false,
319 }
320 }
321
322 pub fn with_config(_config: CorruptionConfig) -> Self {
324 Self {
325 initialized: false,
326 }
327 }
328
329 pub async fn initialize(&mut self) -> Result<(), IntegrityError> {
331 self.initialized = true;
332 Ok(())
333 }
334
335 pub async fn detect_corruption(&self, data: &[u8], metadata: &DataMetadata) -> Result<CorruptionResult, IntegrityError> {
337 if !self.initialized {
338 return Err(IntegrityError::NotInitialized);
339 }
340
341 let mut result = CorruptionResult::new();
342
343 if metadata.format != DataFormat::Binary && data.contains(&0) {
345 result.is_corrupted = true;
346 result.details.push("Null bytes detected in non-binary data".to_string());
347 }
348
349 if let Some(expected_size) = metadata.expected_size {
351 if data.len() != expected_size {
352 result.is_corrupted = true;
353 result.details.push(format!(
354 "Data size mismatch: expected {}, got {}",
355 expected_size,
356 data.len()
357 ));
358 }
359 }
360
361 match metadata.format {
363 DataFormat::Json => {
364 if let Err(e) = serde_json::from_slice::<serde_json::Value>(data) {
365 result.is_corrupted = true;
366 result.details.push(format!("Invalid JSON: {}", e));
367 }
368 }
369 DataFormat::Text => {
370 if let Err(e) = std::str::from_utf8(data) {
371 result.is_corrupted = true;
372 result.details.push(format!("Invalid UTF-8: {}", e));
373 }
374 }
375 _ => {} }
377
378 Ok(result)
379 }
380}
381
382#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
384pub struct DataMetadata {
385 pub checksum: String,
387 pub version: String,
389 pub expected_version: String,
391 pub format: DataFormat,
393 pub expected_size: Option<usize>,
395 pub created_at: u64,
397 pub modified_at: u64,
399}
400
401#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
403pub enum DataFormat {
404 Json,
406 Bincode,
408 Binary,
410 Text,
412}
413
414#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
416pub enum ChecksumAlgorithm {
417 Sha256,
419 Sha1,
421 Md5,
423}
424
425#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
427pub struct IntegrityResult {
428 pub checksum_valid: bool,
430 pub version_valid: bool,
432 pub corruption_detected: bool,
434 pub corruption_details: Vec<String>,
436 pub overall_valid: bool,
438 pub errors: Vec<IntegrityError>,
440}
441
442impl IntegrityResult {
443 pub fn new() -> Self {
445 Self {
446 checksum_valid: false,
447 version_valid: false,
448 corruption_detected: false,
449 corruption_details: Vec::new(),
450 overall_valid: false,
451 errors: Vec::new(),
452 }
453 }
454}
455
456#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
458pub struct CorruptionResult {
459 pub is_corrupted: bool,
461 pub details: Vec<String>,
463}
464
465impl CorruptionResult {
466 pub fn new() -> Self {
468 Self {
469 is_corrupted: false,
470 details: Vec::new(),
471 }
472 }
473}
474
475#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
477pub struct IntegrityStats {
478 pub total_verifications: usize,
480 pub total_verifications_passed: usize,
482 pub total_verifications_failed: usize,
484 pub checksum_verifications_passed: usize,
486 pub checksum_verifications_failed: usize,
488 pub version_verifications_passed: usize,
490 pub version_verifications_failed: usize,
492 pub corruption_detections: usize,
494}
495
496impl IntegrityStats {
497 pub fn new() -> Self {
499 Self {
500 total_verifications: 0,
501 total_verifications_passed: 0,
502 total_verifications_failed: 0,
503 checksum_verifications_passed: 0,
504 checksum_verifications_failed: 0,
505 version_verifications_passed: 0,
506 version_verifications_failed: 0,
507 corruption_detections: 0,
508 }
509 }
510
511 pub fn reset(&mut self) {
513 self.total_verifications = 0;
514 self.total_verifications_passed = 0;
515 self.total_verifications_failed = 0;
516 self.checksum_verifications_passed = 0;
517 self.checksum_verifications_failed = 0;
518 self.version_verifications_passed = 0;
519 self.version_verifications_failed = 0;
520 self.corruption_detections = 0;
521 }
522}
523
524#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
526pub struct IntegrityConfig {
527 pub checksum_config: ChecksumConfig,
529 pub version_config: VersionConfig,
531 pub corruption_config: CorruptionConfig,
533}
534
535impl Default for IntegrityConfig {
536 fn default() -> Self {
537 Self {
538 checksum_config: ChecksumConfig::default(),
539 version_config: VersionConfig::default(),
540 corruption_config: CorruptionConfig::default(),
541 }
542 }
543}
544
545#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
547pub struct ChecksumConfig {
548 pub algorithm: ChecksumAlgorithm,
550}
551
552impl Default for ChecksumConfig {
553 fn default() -> Self {
554 Self {
555 algorithm: ChecksumAlgorithm::Sha256,
556 }
557 }
558}
559
560#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
562pub struct VersionConfig {
563 pub enable_version_verification: bool,
565}
566
567impl Default for VersionConfig {
568 fn default() -> Self {
569 Self {
570 enable_version_verification: true,
571 }
572 }
573}
574
575#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
577pub struct CorruptionConfig {
578 pub enable_corruption_detection: bool,
580}
581
582impl Default for CorruptionConfig {
583 fn default() -> Self {
584 Self {
585 enable_corruption_detection: true,
586 }
587 }
588}
589
590#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
592pub enum IntegrityError {
593 NotInitialized,
595 ChecksumVerificationFailed(String),
597 VersionVerificationFailed(String),
599 CorruptionDetectionFailed(String),
601 ChecksumMismatch,
603 VersionMismatch,
605 DataCorruption,
607 InvalidDataFormat,
609 ConfigurationError(String),
611}
612
613impl std::fmt::Display for IntegrityError {
614 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
615 match self {
616 IntegrityError::NotInitialized => write!(f, "Data integrity system not initialized"),
617 IntegrityError::ChecksumVerificationFailed(msg) => write!(f, "Checksum verification failed: {}", msg),
618 IntegrityError::VersionVerificationFailed(msg) => write!(f, "Version verification failed: {}", msg),
619 IntegrityError::CorruptionDetectionFailed(msg) => write!(f, "Corruption detection failed: {}", msg),
620 IntegrityError::ChecksumMismatch => write!(f, "Checksum mismatch"),
621 IntegrityError::VersionMismatch => write!(f, "Version mismatch"),
622 IntegrityError::DataCorruption => write!(f, "Data corruption detected"),
623 IntegrityError::InvalidDataFormat => write!(f, "Invalid data format"),
624 IntegrityError::ConfigurationError(msg) => write!(f, "Configuration error: {}", msg),
625 }
626 }
627}
628
629impl std::error::Error for IntegrityError {}
630
631#[cfg(test)]
632mod tests {
633 use super::*;
634
635 #[tokio::test]
636 async fn test_data_integrity_creation() {
637 let integrity = DataIntegrity::new();
638 assert!(!integrity.is_initialized());
639 }
640
641 #[tokio::test]
642 async fn test_data_integrity_initialization() {
643 let mut integrity = DataIntegrity::new();
644 let result = integrity.initialize().await;
645 assert!(result.is_ok());
646 assert!(integrity.is_initialized());
647 }
648
649 #[tokio::test]
650 async fn test_data_integrity_shutdown() {
651 let mut integrity = DataIntegrity::new();
652 integrity.initialize().await.unwrap();
653 let result = integrity.shutdown().await;
654 assert!(result.is_ok());
655 assert!(!integrity.is_initialized());
656 }
657
658 #[tokio::test]
659 async fn test_checksum_generation() {
660 let mut integrity = DataIntegrity::new();
661 integrity.initialize().await.unwrap();
662
663 let data = b"Hello, World!";
664 let checksum = integrity.generate_checksum(data).await.unwrap();
665
666 assert_eq!(checksum.len(), 64); assert!(checksum.chars().all(|c| c.is_ascii_hexdigit()));
669 }
670
671 #[tokio::test]
672 async fn test_checksum_verification() {
673 let mut integrity = DataIntegrity::new();
674 integrity.initialize().await.unwrap();
675
676 let data = b"Hello, World!";
677 let checksum = integrity.generate_checksum(data).await.unwrap();
678
679 let metadata = DataMetadata {
680 checksum: checksum.clone(),
681 version: "1.0".to_string(),
682 expected_version: "1.0".to_string(),
683 format: DataFormat::Text,
684 expected_size: Some(data.len()),
685 created_at: 1234567890,
686 modified_at: 1234567890,
687 };
688
689 let result = integrity.verify_integrity(data, &metadata).await.unwrap();
690 assert!(result.checksum_valid);
691 assert!(result.version_valid);
692 assert!(!result.corruption_detected);
693 assert!(result.overall_valid);
694 }
695
696 #[tokio::test]
697 async fn test_checksum_mismatch() {
698 let mut integrity = DataIntegrity::new();
699 integrity.initialize().await.unwrap();
700
701 let data = b"Hello, World!";
702 let wrong_checksum = "wrong_checksum";
703
704 let metadata = DataMetadata {
705 checksum: wrong_checksum.to_string(),
706 version: "1.0".to_string(),
707 expected_version: "1.0".to_string(),
708 format: DataFormat::Text,
709 expected_size: Some(data.len()),
710 created_at: 1234567890,
711 modified_at: 1234567890,
712 };
713
714 let result = integrity.verify_integrity(data, &metadata).await.unwrap();
715 assert!(!result.checksum_valid);
716 assert!(result.version_valid);
717 assert!(!result.corruption_detected);
718 assert!(!result.overall_valid);
719 }
720
721 #[tokio::test]
722 async fn test_version_mismatch() {
723 let mut integrity = DataIntegrity::new();
724 integrity.initialize().await.unwrap();
725
726 let data = b"Hello, World!";
727 let checksum = integrity.generate_checksum(data).await.unwrap();
728
729 let metadata = DataMetadata {
730 checksum,
731 version: "1.0".to_string(),
732 expected_version: "2.0".to_string(),
733 format: DataFormat::Text,
734 expected_size: Some(data.len()),
735 created_at: 1234567890,
736 modified_at: 1234567890,
737 };
738
739 let result = integrity.verify_integrity(data, &metadata).await.unwrap();
740 assert!(result.checksum_valid);
741 assert!(!result.version_valid);
742 assert!(!result.corruption_detected);
743 assert!(!result.overall_valid);
744 }
745
746 #[tokio::test]
747 async fn test_corruption_detection() {
748 let mut integrity = DataIntegrity::new();
749 integrity.initialize().await.unwrap();
750
751 let data = b"Hello, World!\x00"; let checksum = integrity.generate_checksum(data).await.unwrap();
753
754 let metadata = DataMetadata {
755 checksum,
756 version: "1.0".to_string(),
757 expected_version: "1.0".to_string(),
758 format: DataFormat::Text, expected_size: Some(data.len()),
760 created_at: 1234567890,
761 modified_at: 1234567890,
762 };
763
764 let result = integrity.verify_integrity(data, &metadata).await.unwrap();
765 assert!(result.checksum_valid);
766 assert!(result.version_valid);
767 assert!(result.corruption_detected);
768 assert!(!result.overall_valid);
769 assert!(!result.corruption_details.is_empty());
770 }
771
772 #[tokio::test]
773 async fn test_data_format_validation() {
774 let mut integrity = DataIntegrity::new();
775 integrity.initialize().await.unwrap();
776
777 let json_data = b"{\"key\": \"value\"}";
779 let is_valid = integrity.validate_data_format(json_data, &DataFormat::Json).await.unwrap();
780 assert!(is_valid);
781
782 let invalid_json = b"{invalid json}";
784 let is_valid = integrity.validate_data_format(invalid_json, &DataFormat::Json).await.unwrap();
785 assert!(!is_valid);
786
787 let text_data = b"Hello, World!";
789 let is_valid = integrity.validate_data_format(text_data, &DataFormat::Text).await.unwrap();
790 assert!(is_valid);
791
792 let invalid_text = b"Hello, World!\xff";
794 let is_valid = integrity.validate_data_format(invalid_text, &DataFormat::Text).await.unwrap();
795 assert!(!is_valid);
796 }
797
798 #[tokio::test]
799 async fn test_integrity_statistics() {
800 let mut integrity = DataIntegrity::new();
801 integrity.initialize().await.unwrap();
802
803 let data = b"Hello, World!";
804 let checksum = integrity.generate_checksum(data).await.unwrap();
805
806 let metadata = DataMetadata {
807 checksum,
808 version: "1.0".to_string(),
809 expected_version: "1.0".to_string(),
810 format: DataFormat::Text,
811 expected_size: Some(data.len()),
812 created_at: 1234567890,
813 modified_at: 1234567890,
814 };
815
816 let _ = integrity.verify_integrity(data, &metadata).await.unwrap();
818
819 let stats = integrity.get_stats().await;
820 assert_eq!(stats.total_verifications, 1);
821 assert_eq!(stats.total_verifications_passed, 1);
822 assert_eq!(stats.total_verifications_failed, 0);
823 assert_eq!(stats.checksum_verifications_passed, 1);
824 assert_eq!(stats.version_verifications_passed, 1);
825 }
826
827 #[tokio::test]
828 async fn test_integrity_statistics_reset() {
829 let mut integrity = DataIntegrity::new();
830 integrity.initialize().await.unwrap();
831
832 let data = b"Hello, World!";
833 let checksum = integrity.generate_checksum(data).await.unwrap();
834
835 let metadata = DataMetadata {
836 checksum,
837 version: "1.0".to_string(),
838 expected_version: "1.0".to_string(),
839 format: DataFormat::Text,
840 expected_size: Some(data.len()),
841 created_at: 1234567890,
842 modified_at: 1234567890,
843 };
844
845 let _ = integrity.verify_integrity(data, &metadata).await.unwrap();
847
848 integrity.reset_stats().await;
850
851 let stats = integrity.get_stats().await;
852 assert_eq!(stats.total_verifications, 0);
853 assert_eq!(stats.total_verifications_passed, 0);
854 assert_eq!(stats.total_verifications_failed, 0);
855 }
856
857 #[test]
858 fn test_checksum_algorithm_default() {
859 let config = ChecksumConfig::default();
860 assert_eq!(config.algorithm, ChecksumAlgorithm::Sha256);
861 }
862
863 #[test]
864 fn test_integrity_config_default() {
865 let config = IntegrityConfig::default();
866 assert_eq!(config.checksum_config.algorithm, ChecksumAlgorithm::Sha256);
867 assert!(config.version_config.enable_version_verification);
868 assert!(config.corruption_config.enable_corruption_detection);
869 }
870
871 #[test]
872 fn test_integrity_error_display() {
873 let error = IntegrityError::ChecksumMismatch;
874 let error_string = format!("{}", error);
875 assert!(error_string.contains("Checksum mismatch"));
876 }
877
878 #[test]
879 fn test_data_metadata_creation() {
880 let metadata = DataMetadata {
881 checksum: "test_checksum".to_string(),
882 version: "1.0".to_string(),
883 expected_version: "1.0".to_string(),
884 format: DataFormat::Json,
885 expected_size: Some(100),
886 created_at: 1234567890,
887 modified_at: 1234567890,
888 };
889
890 assert_eq!(metadata.checksum, "test_checksum");
891 assert_eq!(metadata.version, "1.0");
892 assert_eq!(metadata.format, DataFormat::Json);
893 assert_eq!(metadata.expected_size, Some(100));
894 }
895}