use std::fmt::Debug;
use anyhow::bail;
use trustfall::Schema;
macro_rules! add_version_method {
() => {
pub fn version(&self) -> u32 {
match self {
{{#each version_numbers}}
#[cfg(feature = "v{{this}}")]
Self::V{{this}}(..) => {{this}},
{{/each}}
}
}
};
}
#[non_exhaustive]
#[derive(Debug)]
pub enum VersionedStorage {
{{#each version_numbers}}
#[cfg(feature = "v{{this}}")]
V{{this}}(trustfall_rustdoc_adapter_v{{this}}::PackageStorage),
{{/each}}
}
#[non_exhaustive]
#[derive(Debug)]
pub enum VersionedIndex<'a> {
{{#each version_numbers}}
#[cfg(feature = "v{{this}}")]
V{{this}}(trustfall_rustdoc_adapter_v{{this}}::PackageIndex<'a>),
{{/each}}
}
#[non_exhaustive]
pub enum VersionedRustdocAdapter<'a> {
{{#each version_numbers}}
#[cfg(feature = "v{{this}}")]
V{{this}}(
&'static Schema,
trustfall_rustdoc_adapter_v{{this}}::RustdocAdapter<'a>,
),
{{/each}}
}
impl VersionedStorage {
/// The version of the crate held here, as reported by its rustdoc data.
///
/// This is the version listed in the `Cargo.toml` of the crate, not its rustdoc format version.
pub fn crate_version(&self) -> Option<&str> {
match self {
{{#each version_numbers}}
#[cfg(feature = "v{{this}}")]
VersionedStorage::V{{this}}(s) => s.crate_version(),
{{/each}}
}
}
add_version_method!();
}
impl<'a> VersionedIndex<'a> {
pub fn from_storage(storage: &'a VersionedStorage) -> Self {
match storage {
{{#each version_numbers}}
#[cfg(feature = "v{{this}}")]
VersionedStorage::V{{this}}(s) => Self::V{{this}}(
trustfall_rustdoc_adapter_v{{this}}::PackageIndex::from_storage(s),
),
{{/each}}
}
}
/// Build an index for Rust standard-library component rustdoc JSON.
///
/// This opts into adapter-side standard-library stability rules. Use
/// [`Self::from_storage`] for ordinary crates.
pub fn from_rust_std_component_storage(storage: &'a VersionedStorage) -> Self {
match storage {
{{#each version_numbers}}
#[cfg(feature = "v{{this}}")]
VersionedStorage::V{{this}}(s) => Self::V{{this}}(
trustfall_rustdoc_adapter_v{{this}}::PackageIndex::from_rust_std_component_storage(s),
),
{{/each}}
}
}
add_version_method!();
}
impl<'a> VersionedRustdocAdapter<'a> {
pub fn new(
current: &'a VersionedIndex<'a>,
baseline: Option<&'a VersionedIndex<'a>>,
) -> anyhow::Result<Self> {
match (current, baseline) {
{{#each version_numbers}}
#[cfg(feature = "v{{this}}")]
(VersionedIndex::V{{this}}(c), Some(VersionedIndex::V{{this}}(b))) => {
let adapter = trustfall_rustdoc_adapter_v{{this}}::RustdocAdapter::new(
c,
Some(b),
);
Ok(VersionedRustdocAdapter::V{{this}}(
trustfall_rustdoc_adapter_v{{this}}::RustdocAdapter::schema(),
adapter,
))
}
#[cfg(feature = "v{{this}}")]
(VersionedIndex::V{{this}}(c), None) => {
let adapter = trustfall_rustdoc_adapter_v{{this}}::RustdocAdapter::new(c, None);
Ok(VersionedRustdocAdapter::V{{this}}(
trustfall_rustdoc_adapter_v{{this}}::RustdocAdapter::schema(),
adapter,
))
}
{{/each}}
#[allow(unreachable_patterns)]
(c, Some(b)) => {
bail!(
"version mismatch between current (v{}) and baseline (v{}) format versions",
c.version(),
b.version()
)
}
}
}
pub fn schema(&self) -> &Schema {
match self {
{{#each version_numbers}}
#[cfg(feature = "v{{this}}")]
VersionedRustdocAdapter::V{{this}}(schema, ..) => schema,
{{/each}}
}
}
add_version_method!();
}
pub(crate) fn supported_versions() -> &'static [u32] {
&[
{{#each version_numbers}}
#[cfg(feature = "v{{this}}")]
{{this}},
{{/each}}
]
}