use std::alloc::{GlobalAlloc, Layout, System}; use std::sync::atomic::{ AtomicUsize, Ordering::{Relaxed, SeqCst}, }; pub struct Allocator; static ALLOCATED: AtomicUsize = AtomicUsize::new(0); unsafe impl GlobalAlloc for Allocator { unsafe fn alloc(&self, layout: Layout) -> *mut u8 { let ret = System.alloc(layout); if !ret.is_null() { ALLOCATED.fetch_add(layout.size(), SeqCst); } ret } unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) { System.dealloc(ptr, layout); ALLOCATED.fetch_sub(layout.size(), SeqCst); } } impl Allocator { pub fn allocated() -> usize { ALLOCATED.load(Relaxed) } } #[global_allocator] static ALLOCATOR: Allocator = Allocator; static UNITS: (&str, &[(&str, usize)]) = ( "b", &[ ("B", 8), ("kB", 1024), ("MB", 1024), ("GB", 1024), ("TB", 1024), ("PB", 1024), ], ); pub fn as_string(bytes: usize) -> String { let mut range: usize = 1; for (i, (_, diff)) in UNITS.1.iter().enumerate() { if bytes < range * diff { return format!( "{:.2}{}", bytes as f32 / range as f32, if i == 0 { UNITS.0 } else { UNITS.1[i - 1].0 } ); } range *= diff } todo!() }