distill_schema/
lib.rs

1mod schemas;
2use std::path::PathBuf;
3
4use distill_core::{utils::make_array, ArtifactId, ArtifactMetadata, AssetMetadata, AssetRef};
5pub use schemas::{data_capnp, pack_capnp, service_capnp};
6impl ::std::fmt::Debug for data_capnp::FileState {
7    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
8        match self {
9            data::FileState::Exists => {
10                write!(f, "FileState::Exists")?;
11            }
12            data::FileState::Deleted => {
13                write!(f, "FileState::Deleted")?;
14            }
15        }
16        Ok(())
17    }
18}
19
20impl From<distill_core::CompressionType> for data_capnp::CompressionType {
21    fn from(c: distill_core::CompressionType) -> Self {
22        match c {
23            distill_core::CompressionType::None => Self::None,
24            distill_core::CompressionType::Lz4 => Self::Lz4,
25        }
26    }
27}
28
29impl From<data_capnp::CompressionType> for distill_core::CompressionType {
30    fn from(c: data_capnp::CompressionType) -> Self {
31        match c {
32            data_capnp::CompressionType::None => Self::None,
33            data_capnp::CompressionType::Lz4 => Self::Lz4,
34        }
35    }
36}
37
38pub use crate::{data_capnp as data, pack_capnp as pack, service_capnp as service};
39
40fn set_assetref_list(
41    asset_ids: &[AssetRef],
42    builder: &mut capnp::struct_list::Builder<'_, data::asset_ref::Owned>,
43) {
44    for (idx, asset_ref) in asset_ids.iter().enumerate() {
45        let mut builder = builder.reborrow().get(idx as u32);
46        match asset_ref {
47            AssetRef::Path(p) => {
48                builder.set_path(
49                    p.to_str()
50                        .expect("failed to convert path to string")
51                        .as_bytes(),
52                );
53            }
54            AssetRef::Uuid(uuid) => {
55                builder.init_uuid().set_id(&uuid.0);
56            }
57        }
58    }
59}
60
61pub fn parse_db_asset_ref(asset_ref: &data::asset_ref::Reader<'_>) -> AssetRef {
62    match asset_ref.which().expect("capnp: failed to read asset ref") {
63        data::asset_ref::Path(p) => AssetRef::Path(PathBuf::from(
64            std::str::from_utf8(p.expect("capnp: failed to read asset ref path"))
65                .expect("capnp: failed to parse utf8 string"),
66        )),
67        data::asset_ref::Uuid(uuid) => AssetRef::Uuid(make_array(
68            uuid.and_then(|id| id.get_id())
69                .expect("capnp: failed to read asset ref uuid"),
70        )),
71    }
72}
73
74pub fn parse_artifact_metadata(artifact: &data::artifact_metadata::Reader<'_>) -> ArtifactMetadata {
75    let asset_id = make_array(
76        artifact
77            .get_asset_id()
78            .expect("capnp: failed to read asset_id")
79            .get_id()
80            .expect("capnp: failed to read asset_id"),
81    );
82    let compressed_size = artifact.get_compressed_size();
83    let compressed_size = if compressed_size == 0 {
84        None
85    } else {
86        Some(compressed_size)
87    };
88    let uncompressed_size = artifact.get_uncompressed_size();
89    let uncompressed_size = if uncompressed_size == 0 {
90        None
91    } else {
92        Some(uncompressed_size)
93    };
94    ArtifactMetadata {
95        asset_id,
96        id: ArtifactId(u64::from_le_bytes(make_array(
97            artifact.get_hash().expect("capnp: failed to read hash"),
98        ))),
99        load_deps: artifact
100            .get_load_deps()
101            .expect("capnp: failed to read load deps")
102            .iter()
103            .map(|dep| parse_db_asset_ref(&dep))
104            .collect(),
105        build_deps: artifact
106            .get_build_deps()
107            .expect("capnp: failed to read build deps")
108            .iter()
109            .map(|dep| parse_db_asset_ref(&dep))
110            .collect(),
111        type_id: make_array(
112            artifact
113                .get_type_id()
114                .expect("capnp: failed to read asset type"),
115        ),
116        compression: artifact
117            .get_compression()
118            .expect("capnp: failed to read compression type")
119            .into(),
120        compressed_size,
121        uncompressed_size,
122    }
123}
124
125pub fn parse_db_metadata(metadata: &data::asset_metadata::Reader<'_>) -> AssetMetadata {
126    let asset_id = make_array(
127        metadata
128            .get_id()
129            .expect("capnp: failed to read asset_id")
130            .get_id()
131            .expect("capnp: failed to read asset_id"),
132    );
133    let search_tags = metadata
134        .get_search_tags()
135        .expect("capnp: failed to read search tags")
136        .iter()
137        .map(|tag| {
138            let key =
139                std::str::from_utf8(tag.get_key().expect("capnp: failed to read search tag key"))
140                    .expect("failed to read tag key as utf8")
141                    .to_owned();
142            let value = std::str::from_utf8(
143                tag.get_value()
144                    .expect("capnp: failed to read search tag value"),
145            )
146            .expect("failed to read tag value as utf8")
147            .to_owned();
148            if !value.is_empty() {
149                (key, Some(value))
150            } else {
151                (key, None)
152            }
153        })
154        .collect();
155    let artifact_metadata = if let data::asset_metadata::latest_artifact::Artifact(Ok(artifact)) =
156        metadata
157            .get_latest_artifact()
158            .which()
159            .expect("capnp: failed to read latest_artifact")
160    {
161        Some(parse_artifact_metadata(&artifact))
162    } else {
163        None
164    };
165    let build_pipeline = metadata
166        .get_build_pipeline()
167        .expect("capnp: failed to read build pipeline")
168        .get_id()
169        .expect("capnp: failed to read build pipeline id");
170    let build_pipeline = if !build_pipeline.is_empty() {
171        Some(make_array(build_pipeline))
172    } else {
173        None
174    };
175    AssetMetadata {
176        id: asset_id,
177        search_tags,
178        build_pipeline,
179        artifact: artifact_metadata,
180    }
181}
182pub fn build_artifact_metadata(
183    artifact_metadata: &ArtifactMetadata,
184    artifact: &mut data::artifact_metadata::Builder<'_>,
185) {
186    let mut artifact = artifact.reborrow();
187    artifact
188        .reborrow()
189        .init_asset_id()
190        .set_id(&artifact_metadata.asset_id.0);
191    artifact
192        .reborrow()
193        .set_hash(&artifact_metadata.id.0.to_le_bytes());
194    set_assetref_list(
195        &artifact_metadata.load_deps,
196        &mut artifact
197            .reborrow()
198            .init_load_deps(artifact_metadata.load_deps.len() as u32),
199    );
200    set_assetref_list(
201        &artifact_metadata.build_deps,
202        &mut artifact
203            .reborrow()
204            .init_build_deps(artifact_metadata.build_deps.len() as u32),
205    );
206    artifact
207        .reborrow()
208        .set_compression(artifact_metadata.compression.into());
209    artifact
210        .reborrow()
211        .set_compressed_size(artifact_metadata.compressed_size.unwrap_or(0));
212    artifact
213        .reborrow()
214        .set_uncompressed_size(artifact_metadata.uncompressed_size.unwrap_or(0));
215    artifact
216        .reborrow()
217        .set_type_id(&artifact_metadata.type_id.0);
218}
219
220pub fn build_asset_metadata(
221    metadata: &AssetMetadata,
222    m: &mut data::asset_metadata::Builder<'_>,
223    source: data::AssetSource,
224) {
225    m.reborrow().init_id().set_id(&metadata.id.0);
226    if let Some(pipeline) = metadata.build_pipeline {
227        m.reborrow().init_build_pipeline().set_id(&pipeline.0);
228    }
229    let mut search_tags = m
230        .reborrow()
231        .init_search_tags(metadata.search_tags.len() as u32);
232    for (idx, (key, value)) in metadata.search_tags.iter().enumerate() {
233        search_tags
234            .reborrow()
235            .get(idx as u32)
236            .set_key(key.as_bytes());
237        if let Some(value) = value {
238            search_tags
239                .reborrow()
240                .get(idx as u32)
241                .set_value(value.as_bytes());
242        }
243    }
244    if let Some(artifact_metadata) = &metadata.artifact {
245        let mut artifact = m.reborrow().init_latest_artifact().init_artifact();
246        build_artifact_metadata(&artifact_metadata, &mut artifact);
247    } else {
248        m.reborrow().init_latest_artifact().set_none(());
249    }
250    m.reborrow().set_source(source);
251}
252
253pub fn build_asset_metadata_message<K>(
254    metadata: &AssetMetadata,
255    source: data::AssetSource,
256) -> capnp::message::Builder<capnp::message::HeapAllocator> {
257    let mut value_builder = capnp::message::Builder::new_default();
258    {
259        let mut m = value_builder.init_root::<data::asset_metadata::Builder<'_>>();
260        build_asset_metadata(metadata, &mut m, source);
261    }
262    value_builder
263}