#[expect(
clippy::large_include_file,
reason = "embedded sample dataset, intentionally large"
)]
#[cfg(all(bundled_sample_available, not(target_arch = "wasm32")))]
pub(crate) const BUNDLED_WCAV: &[u8] = include_bytes!("../assets/sample_wind.wcav");
#[cfg(not(all(bundled_sample_available, not(target_arch = "wasm32"))))]
pub(crate) const BUNDLED_WCAV: &[u8] = &[];
pub(crate) const fn has_bundled_sample() -> bool {
!BUNDLED_WCAV.is_empty()
}
pub(crate) const fn can_load_sample() -> bool {
!cfg!(target_arch = "wasm32")
}
#[cfg(not(target_arch = "wasm32"))]
pub(crate) use native::load_sample_bytes;
#[cfg(not(target_arch = "wasm32"))]
mod native {
use std::path::PathBuf;
pub(crate) const SAMPLE_URL: &str = concat!(
"https://raw.githubusercontent.com/Anvoker/bywind/v",
env!("CARGO_PKG_VERSION"),
"/bywind-viz/assets/sample_wind.wcav",
);
fn cache_path() -> Option<PathBuf> {
let dirs = directories::ProjectDirs::from("dev", "Anvoker", "bywind-viz")?;
let name = concat!("sample_wind-v", env!("CARGO_PKG_VERSION"), ".wcav");
Some(dirs.cache_dir().join(name))
}
pub(crate) fn load_sample_bytes() -> Result<Vec<u8>, String> {
if !super::BUNDLED_WCAV.is_empty() {
return Ok(super::BUNDLED_WCAV.to_vec());
}
if let Some(path) = cache_path() {
if path.is_file() {
match std::fs::read(&path) {
Ok(bytes) if !bytes.is_empty() => return Ok(bytes),
Ok(_) => log::warn!(
"cached sample at {} was empty; redownloading",
path.display(),
),
Err(e) => log::warn!(
"cached sample at {} unreadable ({e}); redownloading",
path.display(),
),
}
}
}
let bytes = download().map_err(|e| format!("download from {SAMPLE_URL}: {e}"))?;
if let Some(path) = cache_path() {
if let Some(parent) = path.parent() {
drop(std::fs::create_dir_all(parent));
}
if let Err(e) = std::fs::write(&path, &bytes) {
log::warn!("failed to cache sample at {}: {e}", path.display());
}
}
Ok(bytes)
}
fn download() -> Result<Vec<u8>, String> {
use std::io::Read as _;
let mut resp = ureq::get(SAMPLE_URL).call().map_err(|e| e.to_string())?;
let mut bytes = Vec::with_capacity(26 * 1024 * 1024);
resp.body_mut()
.as_reader()
.read_to_end(&mut bytes)
.map_err(|e| e.to_string())?;
Ok(bytes)
}
}