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}