use aion_package::{ExtractionLimits, Package};
use aion_store::PackageRecord;
use super::projection;
use super::types::{DeployedDocument, DeployedError, DeployedSchema};
pub(super) fn read_document(
archives: &[PackageRecord],
workflow_type: &str,
content_hash: &str,
) -> Result<DeployedDocument, DeployedError> {
let not_found = || DeployedError::NotFound {
workflow_type: workflow_type.to_owned(),
content_hash: content_hash.to_owned(),
};
let record = archives
.iter()
.find(|record| record.content_hash == content_hash)
.ok_or_else(not_found)?;
let package = Package::load_from_bytes(&record.archive, ExtractionLimits::unbounded())
.map_err(|error| DeployedError::Unreadable {
workflow_type: workflow_type.to_owned(),
content_hash: content_hash.to_owned(),
reason: error.to_string(),
})?;
if !declares_workflow_type(&package, workflow_type) {
return Err(not_found());
}
let awl = package
.awl()
.ok_or_else(|| DeployedError::NoArchivedSource {
workflow_type: workflow_type.to_owned(),
content_hash: content_hash.to_owned(),
})?;
let projection = projection::project(awl.document(), awl.schemas())?;
Ok(DeployedDocument {
workflow_type: workflow_type.to_owned(),
content_hash: content_hash.to_owned(),
document_name: awl.document_name().to_owned(),
source: awl.document().to_owned(),
schemas: awl
.schemas()
.iter()
.map(|(path, bytes)| DeployedSchema {
path: path.clone(),
text: String::from_utf8(bytes.clone()).ok(),
byte_length: bytes.len(),
})
.collect(),
projection,
})
}
fn declares_workflow_type(package: &Package, workflow_type: &str) -> bool {
package.manifest().entry_module == workflow_type
|| package
.manifest()
.additional_workflows
.iter()
.any(|entry| entry.workflow_type == workflow_type)
}