use cache_dir::{get_cache_dir, NoSuchDirectoryError};
use std::{
fs::File,
io::{Error as IoError, Read, Write},
sync::LazyLock,
};
use tracing::error;
use uuid::Error as UuidError;
pub use uuid::Uuid;
#[allow(dead_code)]
#[derive(Debug)]
enum DeviceIdError {
NoCacheDir(NoSuchDirectoryError),
NoFile(IoError),
DataInvalid(UuidError),
}
const ID_FILE_NAME: &str = "device.id";
fn try_get_device_id() -> Result<Uuid, DeviceIdError> {
let path = get_cache_dir()
.map_err(DeviceIdError::NoCacheDir)?
.join(ID_FILE_NAME);
let mut file = File::open(path).map_err(DeviceIdError::NoFile)?;
let mut buf = Vec::with_capacity(16);
file.read_to_end(&mut buf).map_err(DeviceIdError::NoFile)?;
Ok(Uuid::from_slice(&buf).map_err(DeviceIdError::DataInvalid)?)
}
static ID_FILE: LazyLock<Uuid> = LazyLock::new(|| {
try_get_device_id().map_or_else(
|e| {
error!(
?e,
"Can't restore the device id from file. Using new device id."
);
let new = Uuid::new_v4();
const ERROR_MSG: &str =
"Can't save device id to file, it will not be restored next time.";
match get_cache_dir() {
Ok(path) => match File::create(path.join(ID_FILE_NAME)) {
Ok(mut file) => match file.write_all(new.as_bytes()) {
Ok(_) => (),
Err(e) => error!(?e, ERROR_MSG),
},
Err(e) => error!(?e, ERROR_MSG),
},
Err(e) => error!(?e, ERROR_MSG),
}
new
},
|i| i,
)
});
pub fn get_device_id() -> Uuid {
ID_FILE.clone()
}