use windows_sys::Win32::UI::Shell::{StrFormatByteSizeW, ShellExecuteW};
use windows_sys::Win32::UI::WindowsAndMessaging::SW_SHOWNORMAL;
pub fn to_wstring(value: &str) -> Vec<u16> {
value.encode_utf16().chain(std::iter::once(0)).collect()
}
pub fn to_wstring_long_path(value: &str) -> Vec<u16> {
let clean_path = value.replace('/', "\\");
let mut s = String::from(clean_path);
if s.len() > 240 && s.contains(':') && !s.starts_with("\\\\?\\") {
s.insert_str(0, "\\\\?\\");
}
to_wstring(&s)
}
pub trait ToPcwstr {
fn to_pcwstr(&self) -> Vec<u16>;
}
impl ToPcwstr for str {
fn to_pcwstr(&self) -> Vec<u16> { to_wstring(self) }
}
impl ToPcwstr for String {
fn to_pcwstr(&self) -> Vec<u16> { to_wstring(self) }
}
pub fn u64_to_wstring(mut val: u64) -> Vec<u16> {
if val == 0 { return vec![0x0030, 0x0000]; } let mut buf = Vec::with_capacity(24);
while val > 0 {
let digit = (val % 10) as u16;
buf.push(0x0030 + digit);
val /= 10;
}
buf.reverse();
buf.push(0x0000);
buf
}
pub fn concat_wstrings(parts: &[&[u16]]) -> Vec<u16> {
let total_len = parts.iter().map(|p| {
if p.last() == Some(&0) { p.len() - 1 } else { p.len() }
}).sum::<usize>();
let mut res = Vec::with_capacity(total_len + 1);
for part in parts {
if part.is_empty() { continue; }
let len = if part.last() == Some(&0) { part.len() - 1 } else { part.len() };
res.extend_from_slice(&part[..len]);
}
res.push(0);
res
}
pub fn format_size(bytes: u64) -> Vec<u16> {
let mut buffer: [u16; 32] = [0; 32];
unsafe {
let size_i64 = if bytes > i64::MAX as u64 {
i64::MAX
} else {
bytes as i64
};
let ptr = StrFormatByteSizeW(size_i64, buffer.as_mut_ptr(), buffer.len() as u32);
if ptr.is_null() {
return vec![0];
}
let len = buffer.iter().position(|&c| c == 0).unwrap_or(buffer.len());
buffer[..=len].to_vec() }
}
pub fn reveal_path_in_explorer(path: &str) {
let select_prefix = to_wstring("/select,\"");
let path_w = to_wstring_long_path(path);
let suffix = to_wstring("\"");
let args = concat_wstrings(&[&select_prefix, &path_w, &suffix]);
unsafe {
ShellExecuteW(
std::ptr::null_mut(),
to_wstring("open").as_ptr(),
to_wstring("explorer.exe").as_ptr(),
args.as_ptr(),
std::ptr::null(),
SW_SHOWNORMAL
);
}
}
pub fn calculate_ratio_string(logical: u64, disk: u64) -> Vec<u16> {
if logical == 0 { return to_wstring("-"); }
let ratio = if disk >= logical {
0.0
} else {
100.0 - ((disk as f64 / logical as f64) * 100.0)
};
let s = format!("{:.1}%", ratio);
to_wstring(&s)
}