use std::sync::OnceLock;
use thiserror::Error;
use crate::archive::{decode_catalog, ArchiveError};
use crate::catalog::{Catalog, CatalogProfile};
use crate::definition::CatalogEdition;
use crate::overlay::{corrected_patches, PatchError};
static IFC2X3_TC1: OnceLock<Result<Catalog, ArchiveError>> = OnceLock::new();
static IFC4_ADD2_TC1: OnceLock<Result<Catalog, ArchiveError>> = OnceLock::new();
static IFC4X3_ADD2: OnceLock<Result<Catalog, ArchiveError>> = OnceLock::new();
static IFC4_ADD2_TC1_CORRECTED: OnceLock<Result<Catalog, EmbeddedCatalogError>> = OnceLock::new();
static IFC4X3_ADD2_CORRECTED: OnceLock<Result<Catalog, EmbeddedCatalogError>> = OnceLock::new();
pub fn load_catalog(
edition: CatalogEdition,
profile: CatalogProfile,
) -> Result<Catalog, EmbeddedCatalogError> {
match profile {
CatalogProfile::Official => official_catalog(edition),
CatalogProfile::Corrected => corrected_catalog(edition),
_ => Err(EmbeddedCatalogError::UnsupportedProfile(profile)),
}
}
pub fn official_catalog(edition: CatalogEdition) -> Result<Catalog, EmbeddedCatalogError> {
match edition {
CatalogEdition::Ifc2x3Tc1 => IFC2X3_TC1
.get_or_init(|| decode_catalog(include_bytes!("../data/ifc2x3-tc1.bin")))
.clone()
.map_err(EmbeddedCatalogError::Archive),
CatalogEdition::Ifc4Add2Tc1 => IFC4_ADD2_TC1
.get_or_init(|| decode_catalog(include_bytes!("../data/ifc4-add2-tc1.bin")))
.clone()
.map_err(EmbeddedCatalogError::Archive),
CatalogEdition::Ifc4x3Add2 => IFC4X3_ADD2
.get_or_init(|| decode_catalog(include_bytes!("../data/ifc4x3-add2.bin")))
.clone()
.map_err(EmbeddedCatalogError::Archive),
}
}
pub fn corrected_catalog(edition: CatalogEdition) -> Result<Catalog, EmbeddedCatalogError> {
match edition {
CatalogEdition::Ifc4Add2Tc1 => IFC4_ADD2_TC1_CORRECTED
.get_or_init(|| {
let official = official_catalog(edition)?;
official
.with_patches(CatalogProfile::Corrected, &corrected_patches(edition))
.map_err(EmbeddedCatalogError::Patch)
})
.clone(),
CatalogEdition::Ifc4x3Add2 => IFC4X3_ADD2_CORRECTED
.get_or_init(|| {
let official = official_catalog(edition)?;
official
.with_patches(CatalogProfile::Corrected, &corrected_patches(edition))
.map_err(EmbeddedCatalogError::Patch)
})
.clone(),
_ => Err(EmbeddedCatalogError::UnavailableEdition(edition)),
}
}
#[derive(Debug, Clone, PartialEq, Eq, Error)]
#[non_exhaustive]
pub enum EmbeddedCatalogError {
#[error("no embedded catalog for {0:?}")]
UnavailableEdition(CatalogEdition),
#[error("embedded loading does not construct {0:?} profiles")]
UnsupportedProfile(CatalogProfile),
#[error(transparent)]
Archive(#[from] ArchiveError),
#[error(transparent)]
Patch(#[from] PatchError),
}