Skip to main content

forge_dictate/bench/
assets.rs

1//! The public bench slice that ships in the binary: LibriSpeech test-clean
2//! utterances, their transcripts, and the attribution the licence asks for.
3//!
4//! Embedded once here and installed beside the models on first use, so an
5//! installed binary carries the corpus and neither bench depends on the repo
6//! tree. The clip bytes are the asset; the manifest beside them is the digest
7//! list the reader verifies by name.
8
9use std::path::Path;
10
11use crate::Error;
12
13/// The manifest the installed slice is read through: one clip per entry,
14/// with its digest and the words it was read from.
15pub(crate) const MANIFEST: &str = include_str!("../../assets/public-corpus/manifest.json");
16
17/// The licence and provenance the asset ships with, written beside the
18/// clips so a reader of the files has them where the audio is.
19const ATTRIBUTION: &str = include_str!("../../assets/public-corpus/ATTRIBUTION.md");
20
21/// Every clip: its file name and its bytes.
22const CLIPS: &[(&str, &[u8])] = &[
23    ("clip-0000.wav", include_bytes!("../../assets/public-corpus/clip-0000.wav")),
24    ("clip-0001.wav", include_bytes!("../../assets/public-corpus/clip-0001.wav")),
25    ("clip-0002.wav", include_bytes!("../../assets/public-corpus/clip-0002.wav")),
26    ("clip-0003.wav", include_bytes!("../../assets/public-corpus/clip-0003.wav")),
27    ("clip-0004.wav", include_bytes!("../../assets/public-corpus/clip-0004.wav")),
28    ("clip-0005.wav", include_bytes!("../../assets/public-corpus/clip-0005.wav")),
29    ("clip-0006.wav", include_bytes!("../../assets/public-corpus/clip-0006.wav")),
30    ("clip-0007.wav", include_bytes!("../../assets/public-corpus/clip-0007.wav")),
31    ("clip-0008.wav", include_bytes!("../../assets/public-corpus/clip-0008.wav")),
32    ("clip-0009.wav", include_bytes!("../../assets/public-corpus/clip-0009.wav")),
33    ("clip-0010.wav", include_bytes!("../../assets/public-corpus/clip-0010.wav")),
34    ("clip-0011.wav", include_bytes!("../../assets/public-corpus/clip-0011.wav")),
35    ("clip-0012.wav", include_bytes!("../../assets/public-corpus/clip-0012.wav")),
36    ("clip-0013.wav", include_bytes!("../../assets/public-corpus/clip-0013.wav")),
37    ("clip-0014.wav", include_bytes!("../../assets/public-corpus/clip-0014.wav")),
38    ("clip-0015.wav", include_bytes!("../../assets/public-corpus/clip-0015.wav")),
39    ("clip-0016.wav", include_bytes!("../../assets/public-corpus/clip-0016.wav")),
40    ("clip-0017.wav", include_bytes!("../../assets/public-corpus/clip-0017.wav")),
41    ("clip-0018.wav", include_bytes!("../../assets/public-corpus/clip-0018.wav")),
42    ("clip-0019.wav", include_bytes!("../../assets/public-corpus/clip-0019.wav")),
43    ("clip-0020.wav", include_bytes!("../../assets/public-corpus/clip-0020.wav")),
44    ("clip-0021.wav", include_bytes!("../../assets/public-corpus/clip-0021.wav")),
45    ("clip-0022.wav", include_bytes!("../../assets/public-corpus/clip-0022.wav")),
46    ("clip-0023.wav", include_bytes!("../../assets/public-corpus/clip-0023.wav")),
47    ("clip-0024.wav", include_bytes!("../../assets/public-corpus/clip-0024.wav")),
48    ("clip-0025.wav", include_bytes!("../../assets/public-corpus/clip-0025.wav")),
49    ("clip-0026.wav", include_bytes!("../../assets/public-corpus/clip-0026.wav")),
50    ("clip-0027.wav", include_bytes!("../../assets/public-corpus/clip-0027.wav")),
51    ("clip-0028.wav", include_bytes!("../../assets/public-corpus/clip-0028.wav")),
52    ("clip-0029.wav", include_bytes!("../../assets/public-corpus/clip-0029.wav")),
53    ("clip-0030.wav", include_bytes!("../../assets/public-corpus/clip-0030.wav")),
54    ("clip-0031.wav", include_bytes!("../../assets/public-corpus/clip-0031.wav")),
55];
56
57/// Install the bundled slice into `dir` when the slice there is not this
58/// binary's, and leave it alone when it is.
59///
60/// The manifest lands last: a half-written slice then reads as an empty tier
61/// or a refusal, never as certified audio.
62pub(crate) fn install(dir: &Path) -> Result<(), Error> {
63    let manifest_path = dir.join("manifest.json");
64    let installed = std::fs::read(&manifest_path).ok();
65    if installed.as_deref() == Some(MANIFEST.as_bytes()) {
66        let whole = CLIPS
67            .iter()
68            .all(|(name, bytes)| std::fs::read(dir.join(name)).is_ok_and(|have| have == *bytes));
69        if whole {
70            return Ok(());
71        }
72    }
73
74    std::fs::create_dir_all(dir).map_err(|source| Error::Io { path: dir.to_path_buf(), source })?;
75    for (name, bytes) in CLIPS {
76        let path = dir.join(name);
77        std::fs::write(&path, bytes).map_err(|source| Error::Io { path, source })?;
78    }
79    let attribution = dir.join("ATTRIBUTION.md");
80    std::fs::write(&attribution, ATTRIBUTION)
81        .map_err(|source| Error::Io { path: attribution, source })?;
82    std::fs::write(&manifest_path, MANIFEST)
83        .map_err(|source| Error::Io { path: manifest_path, source })?;
84    Ok(())
85}