@@ -173,3 +173,60 @@ pub(crate) fn parse_memory_to_mb(memory_str: &str) -> Result<u32> {
173173 Err ( eyre ! ( "Memory specification cannot be empty - please provide a value like '2G', '1024M', or '512'" ) )
174174 }
175175}
176+
177+ /// Convert memory value with unit to megabytes (MiB)
178+ /// Handles libvirt-style units distinguishing between decimal (KB, MB, GB - powers of 1000)
179+ /// and binary (KiB, MiB, GiB - powers of 1024) units per libvirt specification
180+ pub ( crate ) fn convert_memory_to_mb ( value : u32 , unit : & str ) -> u32 {
181+ // Use u128 for calculations to prevent overflow with large units like TB
182+ let value_u128 = value as u128 ;
183+ let mib_u128 = 1024 * 1024 ;
184+
185+ let mb = match unit {
186+ // Binary prefixes (powers of 1024), converting to MiB
187+ "k" | "K" | "KiB" => value_u128 / 1024 ,
188+ "M" | "MiB" => value_u128,
189+ "G" | "GiB" => value_u128 * 1024 ,
190+ "T" | "TiB" => value_u128 * 1024 * 1024 ,
191+
192+ // Decimal prefixes (powers of 1000), converting to MiB
193+ "B" | "bytes" => value_u128 / mib_u128,
194+ "KB" => ( value_u128 * 1_000 ) / mib_u128,
195+ "MB" => ( value_u128 * 1_000_000 ) / mib_u128,
196+ "GB" => ( value_u128 * 1_000_000_000 ) / mib_u128,
197+ "TB" => ( value_u128 * 1_000_000_000_000 ) / mib_u128,
198+
199+ // Libvirt default is KiB for memory
200+ _ => value_u128 / 1024 ,
201+ } ;
202+ mb as u32
203+ }
204+
205+ #[ cfg( test) ]
206+ mod tests {
207+ use super :: * ;
208+
209+ #[ test]
210+ fn test_convert_memory_to_mb ( ) {
211+ // Test binary units (powers of 1024)
212+ assert_eq ! ( convert_memory_to_mb( 4194304 , "KiB" ) , 4096 ) ;
213+ assert_eq ! ( convert_memory_to_mb( 2097152 , "KiB" ) , 2048 ) ;
214+ assert_eq ! ( convert_memory_to_mb( 2048 , "MiB" ) , 2048 ) ;
215+ assert_eq ! ( convert_memory_to_mb( 4096 , "MiB" ) , 4096 ) ;
216+ assert_eq ! ( convert_memory_to_mb( 4 , "GiB" ) , 4096 ) ;
217+ assert_eq ! ( convert_memory_to_mb( 2 , "GiB" ) , 2048 ) ;
218+
219+ // Test short forms (binary)
220+ assert_eq ! ( convert_memory_to_mb( 4 , "G" ) , 4096 ) ;
221+ assert_eq ! ( convert_memory_to_mb( 2048 , "M" ) , 2048 ) ;
222+ assert_eq ! ( convert_memory_to_mb( 2097152 , "K" ) , 2048 ) ;
223+
224+ // Test decimal units (powers of 1000)
225+ assert_eq ! ( convert_memory_to_mb( 1048576 , "KB" ) , 1000 ) ;
226+ assert_eq ! ( convert_memory_to_mb( 1024 , "MB" ) , 976 ) ;
227+ assert_eq ! ( convert_memory_to_mb( 4 , "GB" ) , 3814 ) ;
228+
229+ // Test default/unknown unit (defaults to KiB)
230+ assert_eq ! ( convert_memory_to_mb( 4194304 , "unknown" ) , 4096 ) ;
231+ }
232+ }
0 commit comments