mod cache_dir;
mod options;
mod tarball;
pub use cache_dir::{init_sdk_cache_dir, resolved_cache_dir};
pub use options::{InstallOptions, InstallSource};
use crate::dict::Dict;
use crate::error::JmdictError;
use crate::model::{FORMAT_VERSION, JMDICT_VERSION};
use std::path::{Path, PathBuf};
pub(crate) const REQUIRED_FILES: &[&str] = &[
"entries.bin",
"kana.fst",
"kanji.fst",
"romaji.fst",
"id.fst",
"gloss.fst",
"gloss_postings.bin",
];
pub fn default_data_url() -> String {
format!(
"https://github.com/theGlenn/jmdict-fst/releases/download/jmdict-fast-v{crate}/jmdict-data-jmdict{jm}-fmt{fmt}.tar.gz",
crate = env!("CARGO_PKG_VERSION"),
jm = JMDICT_VERSION,
fmt = FORMAT_VERSION,
)
}
pub(crate) fn install_subdir() -> PathBuf {
PathBuf::from("jmdict-fast")
.join(format!("fmt{FORMAT_VERSION}"))
.join(JMDICT_VERSION)
}
pub(crate) fn install_complete(dir: &Path) -> bool {
REQUIRED_FILES.iter().all(|f| dir.join(f).exists())
}
impl Dict {
pub fn install() -> Result<Self, JmdictError> {
Self::install_with(InstallOptions::default())
}
pub fn install_from_url(url: impl Into<String>) -> Result<Self, JmdictError> {
Self::install_with(InstallOptions::default().source(InstallSource::Url(url.into())))
}
pub fn install_from_tarball(path: impl Into<PathBuf>) -> Result<Self, JmdictError> {
Self::install_with(InstallOptions::default().source(InstallSource::Tarball(path.into())))
}
pub fn install_with(opts: InstallOptions) -> Result<Self, JmdictError> {
let root = match opts.cache_dir.clone() {
Some(p) => p,
None => resolved_cache_dir()?,
};
let target = root.join(install_subdir());
if opts.force || !install_complete(&target) {
if opts.force && target.exists() {
std::fs::remove_dir_all(&target)?;
}
std::fs::create_dir_all(&target)?;
materialize(&target, &opts.source)?;
if !install_complete(&target) {
return Err(JmdictError::DataCorrupted);
}
}
Dict::load(&target)
}
}
fn materialize(target: &Path, source: &InstallSource) -> Result<(), JmdictError> {
match source {
InstallSource::OfficialRelease => {
let bytes = tarball::download(&default_data_url())?;
tarball::extract(&bytes, target)
}
InstallSource::Url(url) => {
let bytes = tarball::download(url)?;
tarball::extract(&bytes, target)
}
InstallSource::Tarball(path) => tarball::extract_from_path(path, target),
}
}