This repository has no description
1use std::path::{Path, PathBuf};
2
3use anyhow::{Context, Result};
4use jacquard_lexicon::codegen::{CodeGenerator, CodegenMode};
5use jacquard_lexicon::corpus::LexiconCorpus;
6use walkdir::WalkDir;
7
8const DEFAULT_LEXICONS_SUBDIR: &str = "lexicons";
9const STAGED_SUBDIR: &str = "lexicons-staged";
10const GENERATED_SUBDIR: &str = "src/_lex";
11const TEMP_SEGMENT: &str = "temp";
12
13fn main() -> Result<()> {
14 let manifest_dir = PathBuf::from(std::env::var("CARGO_MANIFEST_DIR")?);
15 let workspace_root = manifest_dir
16 .parent()
17 .and_then(Path::parent)
18 .context("resolve workspace root from manifest dir")?
19 .to_path_buf();
20
21 let lexicons_dir = std::env::var("BOBBIN_LEXICONS_DIR")
22 .map(PathBuf::from)
23 .unwrap_or_else(|_| workspace_root.join(DEFAULT_LEXICONS_SUBDIR));
24
25 println!("cargo:rerun-if-env-changed=BOBBIN_LEXICONS_DIR");
26 println!("cargo:rerun-if-changed={}", lexicons_dir.display());
27 println!("cargo:rerun-if-changed=build.rs");
28
29 let out_dir = PathBuf::from(std::env::var("OUT_DIR")?);
30
31 let staged = out_dir.join(STAGED_SUBDIR);
32 if staged.exists() {
33 std::fs::remove_dir_all(&staged).context("clean staged lexicons")?;
34 }
35 stage_lexicons(&lexicons_dir, &staged)?;
36
37 let corpus = LexiconCorpus::load_from_dir(&staged)
38 .map_err(|e| anyhow::anyhow!("load lexicon corpus: {e:?}"))?;
39
40 let generated = manifest_dir.join(GENERATED_SUBDIR);
41 if generated.exists() {
42 std::fs::remove_dir_all(&generated).context("clean generated dir")?;
43 }
44 std::fs::create_dir_all(&generated).context("create generated dir")?;
45
46 let codegen = CodeGenerator::with_mode(&corpus, "crate", CodegenMode::Pretty);
47 codegen
48 .write_to_disk(&generated)
49 .map_err(|e| anyhow::anyhow!("write generated code: {e:?}"))?;
50
51 Ok(())
52}
53
54fn stage_lexicons(src: &Path, dst: &Path) -> Result<()> {
55 WalkDir::new(src)
56 .into_iter()
57 .filter_map(std::result::Result::ok)
58 .filter(|e| e.file_type().is_file())
59 .filter(|e| {
60 e.path()
61 .extension()
62 .is_some_and(|ext| ext.eq_ignore_ascii_case("json"))
63 })
64 .filter(|e| !e.path().components().any(|c| c.as_os_str() == TEMP_SEGMENT))
65 .try_for_each(|entry| -> Result<()> {
66 let rel = entry.path().strip_prefix(src).context("strip src prefix")?;
67 let target = dst.join(rel);
68 if let Some(parent) = target.parent() {
69 std::fs::create_dir_all(parent).context("create staged parent")?;
70 }
71 std::fs::copy(entry.path(), &target).context("copy lexicon file")?;
72 Ok(())
73 })
74}