use std::{ffi::OsStr, fs::File, io, path::Path};
#[cfg_attr(windows, path = "windows.rs")]
#[cfg_attr(unix, path = "unix.rs")]
#[cfg_attr(target_os = "wasi", path = "wasi.rs")]
mod sys;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct FileID (sys::FileIDImpl);
impl FileID {
pub fn new<T: GetID + ?Sized>(file: &T) -> io::Result<Self> {
file.get_id()
}
#[must_use]
pub const fn storage_id(&self) -> u64 {
self.0.0
}
#[must_use]
#[allow(clippy::unnecessary_cast)]
pub const fn internal_file_id(&self) -> u128 {
self.0.1 as u128
}
}
pub trait GetID {
fn get_id(&self) -> io::Result<FileID>;
}
impl GetID for FileID {
fn get_id(&self) -> io::Result<FileID> {
Ok(self.to_owned())
}
}
macro_rules! impl_get_id {
($($type:ty),+) => {
$(
impl GetID for $type {
fn get_id(&self) -> io::Result<FileID> {
File::open(self)?.get_id()
}
}
)+
};
}
impl_get_id!(Path, str, OsStr);
pub fn compare_ids<T1: GetID + ?Sized, T2: GetID + ?Sized>(id1: &T1, id2: &T2) -> io::Result<bool> {
Ok(id1.get_id()? == id2.get_id()?)
}
#[cfg(test)]
mod tests {
use crate::FileID;
#[test]
fn check_comparisons() -> std::io::Result<()> {
let id1 = FileID::new("Cargo.toml")?;
let id2 = FileID::new("Cargo.toml")?;
let id3 = FileID::new("LICENSE")?;
assert_eq!(id1, id2);
assert_ne!(id1, id3);
println!("id1: {id1:?}\nid2: {id2:?}\nid3: {id3:?}");
Ok(())
}
}