qualia_core_db/render/
derivation.rs1use crate::container_10d::provenance_section::ProvenanceSidecar;
9use crate::render::assets::import_asset;
10use crate::render::compile_10d::{compile_mesh_to_10d_with_provenance, Compile10dError};
11
12#[derive(Debug, PartialEq, Eq)]
14pub enum DerivationError {
15 ImportFailed(String),
17 CompilationFailed(Compile10dError),
19}
20
21impl std::fmt::Display for DerivationError {
22 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
23 match self {
24 Self::ImportFailed(e) => write!(f, "Derivation import failed: {e}"),
25 Self::CompilationFailed(e) => write!(f, "Derivation compilation failed: {e}"),
26 }
27 }
28}
29impl std::error::Error for DerivationError {}
30
31pub fn run_derivation_job(
36 source_bytes: &[u8],
37 format_hint: Option<&str>,
38 media_type: &str,
39 licence: &str,
40 vc_payload: Option<&[u8]>,
41) -> Result<Vec<u8>, DerivationError> {
42 let mesh = import_asset(source_bytes, format_hint)
43 .map_err(|e| DerivationError::ImportFailed(e.to_string()))?;
44
45 let mut sidecar = ProvenanceSidecar::new(source_bytes, media_type, licence);
46 if let Some(vc_bytes) = vc_payload {
47 sidecar = sidecar.with_vc(vc_bytes);
48 }
49
50 compile_mesh_to_10d_with_provenance(&mesh, Some(&sidecar))
51 .map_err(DerivationError::CompilationFailed)
52}
53
54#[cfg(test)]
55mod tests {
56 use super::*;
57 use crate::container_10d::header::Container10dHeader;
58 use crate::container_10d::provenance_section::{
59 decode_provenance_section, validate_provenance,
60 };
61 use crate::container_10d::section::{parse_section_table, SectionType};
62
63 const TRI_OBJ: &[u8] = b"v 0 0 0\nv 1 0 0\nv 0 1 0\nf 1 2 3\n";
64
65 #[test]
66 fn derivation_job_produces_valid_container() {
67 let out = run_derivation_job(TRI_OBJ, Some("obj"), "text/plain", "CC0", None).unwrap();
68
69 let header = Container10dHeader::parse(&out).unwrap();
70 let descs = parse_section_table(&out, &header).unwrap();
71
72 let prov = descs
74 .iter()
75 .find(|d| d.section_type == SectionType::ProvenanceSidecar as u8)
76 .expect("provenance section generated");
77
78 let payload = &out[prov.byte_offset as usize..][..prov.byte_length as usize];
79 let view = decode_provenance_section(payload).unwrap();
80
81 validate_provenance(&view).unwrap();
82 assert_eq!(view.licence(), "CC0");
83 assert_eq!(view.source_bytes(), TRI_OBJ);
84 }
85}