1use std::{sync::Arc, time::Duration};
3
4use directories::ProjectDirs;
5
6use crate::{
7 error::{RLanLibError, Result},
8 oui::{db::OuiDb, offline_db::OfflineOuiDb, traits::Oui},
9};
10
11pub mod db;
16pub mod offline_db;
18pub mod traits;
20pub mod types;
22
23pub fn default(project_name: &str, max_age: Duration) -> Result<Arc<dyn Oui>> {
25 log::info!("initializing oui data dir");
26
27 let project_dirs =
28 ProjectDirs::from("", "", project_name).ok_or(RLanLibError::Oui(
29 format!("failed to find \"{project_name}\" oui data directory"),
30 ))?;
31
32 let data_dir = project_dirs.data_dir();
33
34 std::fs::create_dir_all(data_dir).map_err(|e| {
35 RLanLibError::Oui(format!(
36 "failed to initialize oui data directory: {} : {}",
37 data_dir.display(),
38 e
39 ))
40 })?;
41
42 let mut oui = OuiDb::new(data_dir);
43 let oui_age = oui.age();
44
45 if let Some(age) = oui_age
46 && let Ok(elapsed) = age.elapsed()
47 && elapsed > max_age
48 {
49 log::info!("oui data files are out of date: updating...");
50 match oui.update() {
51 Ok(_) => log::info!("successfully downloaded vendor data"),
52 Err(err) => {
53 log::warn!("failed to download vendor data: {}", err);
54 log::warn!(
55 "continuing with use of previously downloaded data: vendor data may be slightly out-of-date"
56 );
57 }
58 }
59 } else if oui_age.is_none() {
60 log::info!("downloading oui data files to {}", data_dir.display());
61 match oui.update() {
62 Ok(_) => log::info!("successfully downloaded vendor data"),
63 Err(err) => {
64 log::warn!("failed to download vendor data: {}", err);
65 log::warn!(
66 "loading offline data: vendor data may be out-of-date"
67 );
68 return Ok(Arc::new(OfflineOuiDb));
69 }
70 }
71 }
72
73 log::info!("loading oui data...");
74 oui.load_data()?;
75
76 Ok(Arc::new(oui))
77}