mod.rs (4038B)
1 //! Passive storage status values for the service-owned status envelope. 2 3 mod disk; 4 5 use core::num::NonZeroU32; 6 7 use serde::Serialize; 8 9 pub use disk::{ 10 MinimumFreeBytes, PlatformStateFilesystemCapacitySource, StateFilesystemCapacity, 11 StateFilesystemCapacityError, StateFilesystemCapacityReadiness, StateFilesystemCapacitySource, 12 inspect_state_filesystem_capacity, 13 }; 14 15 /// Service-neutral storage health classification. 16 #[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize)] 17 #[serde(rename_all = "snake_case")] 18 pub enum StorageHealth { 19 Ready, 20 ReadOnly, 21 RepairRequired, 22 Unavailable, 23 } 24 25 /// Service-neutral storage integrity classification. 26 #[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize)] 27 #[serde(rename_all = "snake_case")] 28 pub enum StorageIntegrity { 29 Verified, 30 VerificationRequired, 31 Failed, 32 } 33 34 /// Passive storage facts supplied to a versioned service-status envelope. 35 #[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize)] 36 pub struct StorageStatus { 37 health: StorageHealth, 38 schema_version: NonZeroU32, 39 generation: u64, 40 integrity: StorageIntegrity, 41 } 42 43 impl StorageStatus { 44 /// Constructs a passive status from already-validated storage facts. 45 #[must_use] 46 pub const fn new( 47 health: StorageHealth, 48 schema_version: NonZeroU32, 49 generation: u64, 50 integrity: StorageIntegrity, 51 ) -> Self { 52 Self { 53 health, 54 schema_version, 55 generation, 56 integrity, 57 } 58 } 59 60 #[must_use] 61 pub const fn health(self) -> StorageHealth { 62 self.health 63 } 64 65 #[must_use] 66 pub const fn schema_version(self) -> NonZeroU32 { 67 self.schema_version 68 } 69 70 #[must_use] 71 pub const fn generation(self) -> u64 { 72 self.generation 73 } 74 75 #[must_use] 76 pub const fn integrity(self) -> StorageIntegrity { 77 self.integrity 78 } 79 } 80 81 #[cfg(test)] 82 mod tests { 83 use super::*; 84 85 #[test] 86 fn status_projection_and_enum_spellings_are_exact() { 87 let health = [ 88 (StorageHealth::Ready, "ready"), 89 (StorageHealth::ReadOnly, "read_only"), 90 (StorageHealth::RepairRequired, "repair_required"), 91 (StorageHealth::Unavailable, "unavailable"), 92 ]; 93 for (value, wire) in health { 94 assert_eq!( 95 serde_json::to_string(&value).unwrap(), 96 format!(r#""{wire}""#) 97 ); 98 } 99 100 let integrity = [ 101 (StorageIntegrity::Verified, "verified"), 102 ( 103 StorageIntegrity::VerificationRequired, 104 "verification_required", 105 ), 106 (StorageIntegrity::Failed, "failed"), 107 ]; 108 for (value, wire) in integrity { 109 assert_eq!( 110 serde_json::to_string(&value).unwrap(), 111 format!(r#""{wire}""#) 112 ); 113 } 114 115 let status = StorageStatus::new( 116 StorageHealth::RepairRequired, 117 NonZeroU32::new(1).unwrap(), 118 7, 119 StorageIntegrity::VerificationRequired, 120 ); 121 assert_eq!(status.health(), StorageHealth::RepairRequired); 122 assert_eq!(status.schema_version().get(), 1); 123 assert_eq!(status.generation(), 7); 124 assert_eq!(status.integrity(), StorageIntegrity::VerificationRequired); 125 assert_eq!( 126 serde_json::to_string(&status).unwrap(), 127 r#"{"health":"repair_required","schema_version":1,"generation":7,"integrity":"verification_required"}"# 128 ); 129 } 130 131 #[test] 132 fn zero_schema_version_cannot_cross_the_construction_boundary() { 133 assert!(NonZeroU32::new(0).is_none()); 134 let maximum = NonZeroU32::new(u32::MAX).unwrap(); 135 let status = StorageStatus::new( 136 StorageHealth::Ready, 137 maximum, 138 u64::MAX, 139 StorageIntegrity::Verified, 140 ); 141 assert_eq!(status.schema_version(), maximum); 142 assert_eq!(status.generation(), u64::MAX); 143 } 144 }