1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
use std::{collections::HashMap, path::PathBuf};

use crossbeam_channel::Sender;
use distill_core::{ArtifactId, ArtifactMetadata, AssetMetadata, AssetUuid};

use crate::{loader::LoaderState, storage::IndirectIdentifier, LoadHandle, Result};

/// Provides [`Loader`](crate::loader::Loader) with data.
pub trait LoaderIO: Send + Sync {
    fn get_asset_metadata_with_dependencies(&mut self, request: MetadataRequest);
    fn get_asset_candidates(&mut self, requests: Vec<ResolveRequest>);
    fn get_artifacts(&mut self, requests: Vec<DataRequest>);
    fn tick(&mut self, loader: &mut LoaderState);
    fn with_runtime(&self, f: &mut dyn FnMut(&tokio::runtime::Runtime));
}

/// A request for an asset artifact's data.
pub struct DataRequest {
    pub(crate) tx: Sender<(Result<Vec<u8>>, LoadHandle, u32)>,
    pub(crate) asset_id: AssetUuid,
    pub(crate) artifact_id: ArtifactId,
    pub(crate) request_data: Option<(LoadHandle, u32)>,
}
impl DataRequest {
    pub fn asset_id(&self) -> AssetUuid {
        self.asset_id
    }

    pub fn artifact_id(&self) -> ArtifactId {
        self.artifact_id
    }

    pub fn error<T: std::error::Error + Send + 'static>(mut self, err: T) {
        if let Some(request_data) = self.request_data.take() {
            let _ = self
                .tx
                .send((Err(Box::new(err)), request_data.0, request_data.1));
        }
    }

    pub fn complete(mut self, data: Vec<u8>) {
        if let Some(request_data) = self.request_data.take() {
            let _ = self.tx.send((Ok(data), request_data.0, request_data.1));
        }
    }
}
impl Drop for DataRequest {
    fn drop(&mut self) {
        if let Some(request_data) = self.request_data.take() {
            let _ = self.tx.send((
                Err(Box::new(RequestDropError)),
                request_data.0,
                request_data.1,
            ));
        }
    }
}

/// A request for possible candidates for an [`IndirectIdentifier`].
#[allow(clippy::type_complexity)]
pub struct ResolveRequest {
    pub(crate) tx: Sender<(
        Result<Vec<(PathBuf, Vec<AssetMetadata>)>>,
        IndirectIdentifier,
        LoadHandle,
    )>,
    pub(crate) id: Option<(IndirectIdentifier, LoadHandle)>,
}
impl ResolveRequest {
    pub fn identifier(&self) -> &IndirectIdentifier {
        self.id.as_ref().map(|v| &v.0).unwrap()
    }

    pub fn error<T: std::error::Error + Send + 'static>(mut self, err: T) {
        if let Some(id) = self.id.take() {
            let _ = self.tx.send((Err(Box::new(err)), id.0, id.1));
        }
    }

    pub fn complete(mut self, data: Vec<(PathBuf, Vec<AssetMetadata>)>) {
        if let Some(id) = self.id.take() {
            let _ = self.tx.send((Ok(data), id.0, id.1));
        }
    }
}
impl Drop for ResolveRequest {
    fn drop(&mut self) {
        if let Some(id) = self.id.take() {
            let _ = self.tx.send((Err(Box::new(RequestDropError)), id.0, id.1));
        }
    }
}
#[derive(Debug)]
struct RequestDropError;
impl std::fmt::Display for RequestDropError {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        f.write_str("request dropped")
    }
}
impl std::error::Error for RequestDropError {}

pub struct MetadataRequestResult {
    pub artifact_metadata: ArtifactMetadata,
    pub asset_metadata: Option<AssetMetadata>,
}
/// A request for artifact metadata covering the dependency graphs of the requested asset IDs.
#[allow(clippy::type_complexity)]
pub struct MetadataRequest {
    pub(crate) tx: Sender<(
        Result<Vec<MetadataRequestResult>>,
        HashMap<AssetUuid, (LoadHandle, u32)>,
    )>,
    pub(crate) requests: Option<HashMap<AssetUuid, (LoadHandle, u32)>>,
    pub(crate) include_asset_metadata: bool,
}
impl MetadataRequest {
    pub fn requested_assets(&self) -> impl Iterator<Item = &AssetUuid> {
        self.requests.as_ref().unwrap().keys()
    }

    /// Whether the response should include asset metadata or not, for debugging purposes.
    pub fn include_asset_metadata(&self) -> bool {
        self.include_asset_metadata
    }

    pub fn error<T: std::error::Error + Send + 'static>(mut self, err: T) {
        if let Some(requests) = self.requests.take() {
            let _ = self.tx.send((Err(Box::new(err)), requests));
        }
    }

    pub fn complete(mut self, metadata: Vec<MetadataRequestResult>) {
        if let Some(requests) = self.requests.take() {
            let _ = self.tx.send((Ok(metadata), requests));
        }
    }
}

impl Drop for MetadataRequest {
    fn drop(&mut self) {
        if let Some(requests) = self.requests.take() {
            let _ = self.tx.send((Err(Box::new(RequestDropError)), requests));
        }
    }
}