-
-
Notifications
You must be signed in to change notification settings - Fork 94
/
usage.rs
71 lines (60 loc) 路 1.81 KB
/
usage.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
use std::fmt;
use std::io;
use std::path::Path;
use winapi::um::{fileapi, winnt};
use heim_common::prelude::*;
use heim_common::units::{information, ratio, Information, Ratio};
#[derive(Default)]
pub struct Usage {
total: winnt::ULARGE_INTEGER,
available: winnt::ULARGE_INTEGER,
free: winnt::ULARGE_INTEGER,
}
impl Usage {
pub fn total(&self) -> Information {
Information::new::<information::byte>(unsafe { *self.total.QuadPart() })
}
pub fn used(&self) -> Information {
self.total() - self.free()
}
pub fn free(&self) -> Information {
Information::new::<information::byte>(unsafe { *self.free.QuadPart() })
}
pub fn ratio(&self) -> Ratio {
// TODO: Possible value truncation
Ratio::new::<ratio::ratio>(
(self.used().get::<information::byte>() as f64
/ self.total().get::<information::byte>() as f64) as f32,
)
}
}
impl fmt::Debug for Usage {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("Usage")
.field("total", &self.total())
.field("used", &self.used())
.field("free", &self.free())
.field("ratio", &self.ratio())
.finish()
}
}
pub async fn usage<T: AsRef<Path>>(path: T) -> Result<Usage> {
let path = match widestring::U16CString::from_os_str(path.as_ref()) {
Ok(path) => path,
Err(_) => return Err(io::Error::from(io::ErrorKind::InvalidInput).into()),
};
let mut usage = Usage::default();
let result = unsafe {
fileapi::GetDiskFreeSpaceExW(
path.as_ptr(),
&mut usage.available,
&mut usage.total,
&mut usage.free,
)
};
if result != 0 {
Ok(usage)
} else {
Err(Error::last_os_error())
}
}