//! Embedding convention for the static reference data files (`data/*.yml`) //! //! Reference data that changes independently of the code — distro series //! pointers, pinned SSH host keys, package quirks — lives in YAML files //! under `data/` at the repo root instead of hardcoded in the source, so //! it is updatable in one reviewable place. //! //! This module is deliberately not a central registry: each file is //! embedded by the module that owns it (distro_info.rs owns //! data/distro_info.yml, launchpad.rs owns data/launchpad.yml, //! apt/keyring.rs owns data/keyserver.yml, put/ssh.rs owns //! data/host_keys.yml, quirks.rs owns data/quirks.yml) through the //! [`embed_data!`] macro below, so data //! and its accessors stay together and a diff touching one domain cannot //! half-touch another. The macro embeds the file at compile time and //! parses it once into a `lazy_static` on first use; since the data ships //! inside the binary, a parse failure is a build-time bug that cannot be //! recovered from at runtime, and the macro panics on it. //! //! Paths and URLs in the data files carry their variable parts as `{name}` //! placeholders, substituted with `str::replace` at the use site — no //! template engine. /// Embed one YAML data file as a lazily-parsed static, following the /// convention documented at the module level. /// /// Takes the visibility of the generated static (none for private, `pub` or /// `pub(crate)`-style), its name, its struct type (which stays defined in /// the owning module, next to its accessors) and the file path relative to /// the invoking source file (`"../data/distro_info.yml"` from /// `src/distro_info.rs`, `"../../data/host_keys.yml"` from /// `src/put/ssh.rs`, ...), and expands to the house `include_str!` → /// `lazy_static` → parse pattern — only the embed+parse boilerplate is /// generated. /// /// ```ignore /// embed_data! { /// static ref MY_DATA: MyData = "../data/my_data.yml" /// } /// ``` macro_rules! embed_data { // Internal arm: the visibility arrives wrapped in parentheses (empty for // private statics) because `lazy_static!` only re-matches literal // `pub`/`pub(...)` token sequences, not an opaque forwarded `vis`. (@expand ($($vis:tt)*) static ref $name:ident : $ty:ty = $path:literal) => { lazy_static::lazy_static! { // The YAML is include_str!'d at compile time and statically // valid; if it ever failed to parse it would be a build-time bug // that cannot be recovered from at runtime, so panicking here is // acceptable. $($vis)* static ref $name: $ty = serde_yaml::from_str(include_str!($path)) .expect(concat!( "built-in ", $path, " data is statically valid and must parse" )); } }; (static ref $name:ident : $ty:ty = $path:literal) => { $crate::data::embed_data!(@expand () static ref $name : $ty = $path); }; (pub static ref $name:ident : $ty:ty = $path:literal) => { $crate::data::embed_data!(@expand (pub) static ref $name : $ty = $path); }; (pub ($($vis:tt)+) static ref $name:ident : $ty:ty = $path:literal) => { $crate::data::embed_data!(@expand (pub ($($vis)+)) static ref $name : $ty = $path); }; } /// Makes the macro available through the module path /// (`use crate::data::embed_data;`) pub(crate) use embed_data;