1use cache_dir::{get_cache_dir, NoSuchDirectoryError};
4use std::{
5 fs::File,
6 io::{Error as IoError, Read, Write},
7 sync::LazyLock,
8};
9use tracing::error;
10use uuid::Error as UuidError;
11pub use uuid::Uuid;
12
13#[allow(dead_code)]
15#[derive(Debug)]
16enum DeviceIdError {
17 NoCacheDir(NoSuchDirectoryError),
19 NoFile(IoError),
21 DataInvalid(UuidError),
23}
24
25const ID_FILE_NAME: &str = "device.id";
27
28fn try_get_device_id() -> Result<Uuid, DeviceIdError> {
29 let path = get_cache_dir()
30 .map_err(DeviceIdError::NoCacheDir)?
31 .join(ID_FILE_NAME);
32 let mut file = File::open(path).map_err(DeviceIdError::NoFile)?;
33 let mut buf = Vec::with_capacity(16);
34 file.read_to_end(&mut buf).map_err(DeviceIdError::NoFile)?;
35 Ok(Uuid::from_slice(&buf).map_err(DeviceIdError::DataInvalid)?)
36}
37
38static ID_FILE: LazyLock<Uuid> = LazyLock::new(|| {
39 try_get_device_id().map_or_else(
40 |e| {
41 error!(
42 ?e,
43 "Can't restore the device id from file. Using new device id."
44 );
45 let new = Uuid::new_v4();
46 const ERROR_MSG: &str =
47 "Can't save device id to file, it will not be restored next time.";
48 match get_cache_dir() {
49 Ok(path) => match File::create(path.join(ID_FILE_NAME)) {
50 Ok(mut file) => match file.write_all(new.as_bytes()) {
51 Ok(_) => (),
52 Err(e) => error!(?e, ERROR_MSG),
53 },
54 Err(e) => error!(?e, ERROR_MSG),
55 },
56 Err(e) => error!(?e, ERROR_MSG),
57 }
58 new
59 },
60 |i| i,
61 )
62});
63
64pub fn get_device_id() -> Uuid {
85 ID_FILE.clone()
86}