use std::path::{Path, PathBuf};
use std::sync::OnceLock;
use crate::error::{Error, Result};
const PHONTAB: &[u8] = include_bytes!("../vendor/espeak-ng-data/phontab");
const PHONINDEX: &[u8] = include_bytes!("../vendor/espeak-ng-data/phonindex");
const PHONDATA: &[u8] = include_bytes!("../vendor/espeak-ng-data/phondata");
const INTONATIONS: &[u8] = include_bytes!("../vendor/espeak-ng-data/intonations");
const EN_DICT: &[u8] = include_bytes!("../vendor/espeak-ng-data/en_dict");
const VI_DICT: &[u8] = include_bytes!("../vendor/espeak-ng-data/vi_dict");
static DATA_DIR: OnceLock<PathBuf> = OnceLock::new();
pub(crate) fn materialized_data_dir() -> Result<&'static Path> {
if let Some(path) = DATA_DIR.get() {
return Ok(path.as_path());
}
let path = write_embedded_data()?;
let _ = DATA_DIR.set(path);
Ok(DATA_DIR
.get()
.expect("embedded data dir initialized")
.as_path())
}
fn write_embedded_data() -> Result<PathBuf> {
let root = std::env::temp_dir().join("piper-phoneme-streaming-espeak-data-v1");
std::fs::create_dir_all(&root)?;
write_if_needed(&root.join("phontab"), PHONTAB)?;
write_if_needed(&root.join("phonindex"), PHONINDEX)?;
write_if_needed(&root.join("phondata"), PHONDATA)?;
write_if_needed(&root.join("intonations"), INTONATIONS)?;
write_if_needed(&root.join("en_dict"), EN_DICT)?;
write_if_needed(&root.join("vi_dict"), VI_DICT)?;
Ok(root)
}
fn write_if_needed(path: &Path, expected: &[u8]) -> Result<()> {
match std::fs::read(path) {
Ok(existing) if existing == expected => return Ok(()),
Ok(_) | Err(_) => {}
}
std::fs::write(path, expected).map_err(Error::Io)
}