hydrate_pipeline/thumbnails/
mod.rs1mod thumbnail_provider_registry;
2pub use thumbnail_provider_registry::*;
3
4mod thumbnail_types;
5pub use thumbnail_types::*;
6
7mod thumbnail_system;
8mod thumbnail_thread_pool;
9
10pub use thumbnail_system::ThumbnailImage;
11pub use thumbnail_system::ThumbnailSystem;
12pub use thumbnail_system::ThumbnailSystemState;
13
14use crate::build::FetchedImportData;
15use crate::PipelineResult;
16use hydrate_base::hashing::HashMap;
17use hydrate_base::AssetId;
18use hydrate_data::{DataSet, SchemaSet};
19use hydrate_schema::HashSet;
20use siphasher::sip128::Hasher128;
21use std::cell::RefCell;
22use std::hash::Hash;
23use std::rc::Rc;
24use std::sync::Arc;
25
26crate::create_uuid_newtype!(ThumbnailInputHash, "ThumbnailInputHash");
27
28#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
29pub struct ThumbnailProviderId(pub usize);
30
31pub struct ThumbnailEnumeratedDependencies {
32 pub(crate) thumbnail_input_hash: ThumbnailInputHash,
34 pub(crate) gathered_data: Arc<Vec<u8>>,
35}
36
37pub trait ThumbnailProviderAbstract: Send + Sync {
38 fn asset_type_inner(&self) -> &'static str;
40
41 fn version_inner(&self) -> u32;
42
43 fn gather_inner(
44 &self,
45 asset_id: AssetId,
46 data_set: &DataSet,
47 schema_set: &SchemaSet,
48 ) -> PipelineResult<ThumbnailEnumeratedDependencies>;
49
50 fn render_inner(
51 &self,
52 asset_id: AssetId,
53 gathered_data: &Vec<u8>,
54 schema_set: &SchemaSet,
55 thumbnail_api: &ThumbnailApi,
56 ) -> PipelineResult<ThumbnailImage>;
57}
58
59struct ThumbnailProviderWrapper<T: ThumbnailProvider>(T);
60
61impl<T: ThumbnailProvider + Send + Sync> ThumbnailProviderAbstract for ThumbnailProviderWrapper<T>
62where
63 <T as ThumbnailProvider>::GatheredDataT:
64 Hash + for<'a> serde::Deserialize<'a> + serde::Serialize,
65{
66 fn asset_type_inner(&self) -> &'static str {
67 self.0.asset_type()
68 }
69
70 fn version_inner(&self) -> u32 {
71 self.0.version()
72 }
73
74 fn gather_inner(
75 &self,
76 asset_id: AssetId,
77 data_set: &DataSet,
78 schema_set: &SchemaSet,
79 ) -> PipelineResult<ThumbnailEnumeratedDependencies> {
80 let mut import_data = HashSet::default();
81 let gathered_data = self.0.gather(ThumbnailProviderGatherContext {
82 asset_id,
83 data_set,
84 schema_set,
85 import_data_dependencies: &Rc::new(RefCell::new(&mut import_data)),
86 });
87
88 let mut hasher = siphasher::sip128::SipHasher::default();
89 gathered_data.hash(&mut hasher);
90 let mut thumbnail_input_hash = hasher.finish128().as_u128();
91
92 for asset_id in &import_data {
94 let mut hasher_inner = siphasher::sip128::SipHasher::default();
95 asset_id.hash(&mut hasher_inner);
96 if let Some(import_data) = data_set.import_info(*asset_id) {
97 import_data
98 .import_data_contents_hash()
99 .hash(&mut hasher_inner);
100 }
101
102 thumbnail_input_hash ^= hasher_inner.finish128().as_u128();
103 }
104
105 let gathered_data = Arc::new(bincode::serialize(&gathered_data)?);
106
107 let thumbnail_input_hash = ThumbnailInputHash::from_u128(thumbnail_input_hash);
108 Ok(ThumbnailEnumeratedDependencies {
109 thumbnail_input_hash,
110 gathered_data,
111 })
112 }
113
114 fn render_inner(
115 &self,
116 asset_id: AssetId,
117 gathered_data: &Vec<u8>,
118 schema_set: &SchemaSet,
119 thumbnail_api: &ThumbnailApi,
120 ) -> PipelineResult<ThumbnailImage> {
121 let gathered_data: T::GatheredDataT = bincode::deserialize(&*gathered_data)?;
122 let mut fetched_import_data = HashMap::<AssetId, FetchedImportData>::default();
123 self.0.render(
124 &ThumbnailProviderRenderContext {
125 desired_thumbnail_width: 256,
126 desired_thumbnail_height: 256,
127 asset_id,
128 schema_set,
129 fetched_import_data: &Rc::new(RefCell::new(&mut fetched_import_data)),
130 thumbnail_api: thumbnail_api,
131 },
132 gathered_data,
133 )
134 }
135}