diff --git a/crates/arr-subs/src/lib.rs b/crates/arr-subs/src/lib.rs index 4585a6e..f4a7131 100644 --- a/crates/arr-subs/src/lib.rs +++ b/crates/arr-subs/src/lib.rs @@ -32,6 +32,33 @@ pub type SearchFuture<'a> = Pin>> /// One downloaded subtitle. pub type DownloadFuture<'a> = Pin> + Send + 'a>>; +/// Translation engine names DESIGN.md §15 recognises, whether or not this +/// binary has the matching cargo feature compiled in. +pub const ENGINES: &[&str] = &["openai", "deepl", "google", "command"]; + +/// Which of [`ENGINES`] this binary actually compiled in. +/// +/// A backend whose feature is not compiled in must not be selectable +/// (DESIGN.md §15, issue #198): the settings API checks a requested engine +/// against this list before it ever reaches the database. +#[must_use] +pub fn compiled_engines() -> Vec<&'static str> { + let mut engines = Vec::new(); + if cfg!(feature = "translate-openai") { + engines.push("openai"); + } + if cfg!(feature = "translate-deepl") { + engines.push("deepl"); + } + if cfg!(feature = "translate-google") { + engines.push("google"); + } + if cfg!(feature = "translate-command") { + engines.push("command"); + } + engines +} + /// One subtitle source: OpenSubtitles.com, Podnapisi (DESIGN.md §15). /// /// Boxed futures rather than `async fn`, so that the trait stays object safe @@ -158,6 +185,16 @@ mod tests { assert_eq!(candidates[0].language, Language::PortuguesePortugal); } + #[test] + fn no_engine_is_compiled_in_by_default() { + // The default feature set is empty (Cargo.toml), matching #198's + // scope: the backends themselves are later issues. + assert!(super::compiled_engines().is_empty()); + for engine in super::compiled_engines() { + assert!(super::ENGINES.contains(&engine)); + } + } + #[tokio::test] async fn a_candidate_id_round_trips_to_its_download() { let provider = StubProvider;