1mod boxed_importer;
2mod error;
3mod serde_obj;
4mod serialized_asset;
5
6#[cfg(feature = "serde_importers")]
7mod ron_importer;
8use std::io::{Read, Write};
9
10pub use distill_core::{
11 importer_context::{ImporterContext, ImporterContextHandle},
12 ArtifactMetadata, AssetMetadata,
13};
14use distill_core::{AssetRef, AssetUuid};
15use futures::{future::BoxFuture, AsyncRead, AsyncReadExt, AsyncWrite, AsyncWriteExt};
16pub use serde;
17use serde::Serialize;
18#[cfg(feature = "serde_importers")]
19pub use distill_serde_importable_derive::*;
20
21pub use self::error::{Error, Result};
22#[cfg(feature = "serde_importers")]
23pub use crate::ron_importer::{RonImporter, RonImporterOptions, RonImporterState};
24#[doc(hidden)]
25#[cfg(feature = "serde_importers")]
26pub use crate::serde_obj::typetag;
27#[cfg(feature = "serde_importers")]
28pub use crate::serde_obj::SerdeImportable;
29pub use crate::{
30 boxed_importer::{BoxedImporter, SourceMetadata, SOURCEMETADATA_VERSION},
31 serde_obj::{IntoSerdeObj, SerdeObj},
32 serialized_asset::SerializedAsset,
33};
34
35#[derive(Default)]
36pub struct ImportOp {
37 pub errors: Vec<Box<dyn std::error::Error + Send + 'static>>,
38 pub warnings: Vec<Box<dyn std::error::Error + Send + 'static>>,
39}
40
41impl ImportOp {
42 pub fn error<T: Into<Box<dyn std::error::Error + Send + 'static>>>(&mut self, err: T) {
43 self.errors.push(err.into());
44 }
45
46 pub fn warn<T: Into<Box<dyn std::error::Error + Send + 'static>>>(&mut self, err: T) {
47 self.warnings.push(err.into());
48 }
49
50 pub fn new_asset_uuid(&self) -> AssetUuid {
51 AssetUuid(*uuid::Uuid::new_v4().as_bytes())
52 }
53}
54
55pub trait Importer: Send + 'static {
57 fn version_static() -> u32
61 where
62 Self: Sized;
63 fn version(&self) -> u32;
67
68 type Options: Send + Sync + 'static;
71
72 type State: Serialize + Send + 'static;
77
78 fn import(
80 &self,
81 op: &mut ImportOp,
82 source: &mut dyn Read,
83 options: &Self::Options,
84 state: &mut Self::State,
85 ) -> Result<ImporterValue>;
86
87 fn export(
89 &self,
90 _output: &mut dyn Write,
91 _options: &Self::Options,
92 _state: &mut Self::State,
93 _assets: Vec<ExportAsset>,
94 ) -> Result<ImporterValue> {
95 Err(Error::ExportUnsupported)
96 }
97}
98
99pub trait AsyncImporter: Send + 'static {
101 fn version_static() -> u32
105 where
106 Self: Sized;
107 fn version(&self) -> u32;
111
112 type Options: Send + Sync + 'static;
115
116 type State: Serialize + Send + 'static;
121
122 fn import<'a>(
124 &'a self,
125 op: &'a mut ImportOp,
126 source: &'a mut (dyn AsyncRead + Unpin + Send + Sync),
127 options: &'a Self::Options,
128 state: &'a mut Self::State,
129 ) -> BoxFuture<'a, Result<ImporterValue>>;
130
131 fn export<'a>(
133 &'a self,
134 _output: &'a mut (dyn AsyncWrite + Unpin + Send + Sync),
135 _options: &'a Self::Options,
136 _state: &'a mut Self::State,
137 _assets: Vec<ExportAsset>,
138 ) -> BoxFuture<'a, Result<ImporterValue>> {
139 Box::pin(async move { Err(Error::ExportUnsupported) })
140 }
141}
142
143impl<T: Importer + Sync> AsyncImporter for T {
144 type Options = <T as Importer>::Options;
147 type State = <T as Importer>::State;
152
153 fn version_static() -> u32
154 where
155 Self: Sized,
156 {
157 <T as Importer>::version_static()
158 }
159
160 fn version(&self) -> u32 {
161 <T as Importer>::version(self)
162 }
163
164 fn import<'a>(
166 &'a self,
167 op: &'a mut ImportOp,
168 source: &'a mut (dyn AsyncRead + Unpin + Send + Sync),
169 options: &'a Self::Options,
170 state: &'a mut Self::State,
171 ) -> BoxFuture<'a, Result<ImporterValue>> {
172 Box::pin(async move {
173 let mut bytes = Vec::new();
174 source.read_to_end(&mut bytes).await?;
175 let mut reader = bytes.as_slice();
176 <T as Importer>::import(self, op, &mut reader, options, state)
177 })
178 }
179
180 fn export<'a>(
182 &'a self,
183 output: &'a mut (dyn AsyncWrite + Unpin + Send + Sync),
184 options: &'a Self::Options,
185 state: &'a mut Self::State,
186 assets: Vec<ExportAsset>,
187 ) -> BoxFuture<'a, Result<ImporterValue>> {
188 Box::pin(async move {
189 let mut write_buf = Vec::new();
190 let result = <T as Importer>::export(self, &mut write_buf, options, state, assets)?;
191 output.write(&write_buf).await?;
192 Ok(result)
193 })
194 }
195}
196
197pub struct ImportedAsset {
200 pub id: AssetUuid,
202 pub search_tags: Vec<(String, Option<String>)>,
204 pub build_deps: Vec<AssetRef>,
206 pub load_deps: Vec<AssetRef>,
208 pub build_pipeline: Option<AssetUuid>,
210 pub asset_data: Box<dyn SerdeObj>,
212}
213
214pub struct ImporterValue {
216 pub assets: Vec<ImportedAsset>,
217}
218
219pub struct ExportAsset {
221 pub asset: SerializedAsset<Vec<u8>>,
223}
224
225#[cfg(feature = "serde_importers")]
226#[macro_export]
227macro_rules! if_serde_importers {
228 ($($tt:tt)*) => {
229 $($tt)*
230 }
231}
232
233#[cfg(not(feature = "serde_importers"))]
234#[macro_export]
235#[doc(hidden)]
236macro_rules! if_serde_importers {
237 ($($tt:tt)*) => {};
238}
239
240pub fn import_error<T: Into<String>>(text: String) -> Box<dyn std::error::Error + Send + 'static> {
242 Box::new(Error::Custom(text))
243}