query_flow/loading.rs
1//! Loading state for async resource handling.
2
3use std::sync::Arc;
4
5use crate::asset::{AssetKey, PendingAsset};
6use crate::QueryError;
7
8/// Loading state with asset key information for error reporting.
9///
10/// This is returned by `ctx.asset()` and provides information about
11/// whether an asset is loading or ready, along with the key for
12/// error reporting on suspend.
13///
14/// # Example
15///
16/// ```ignore
17/// #[query]
18/// fn process_file(ctx: &mut QueryContext, path: FilePath) -> Result<Output, QueryError> {
19/// let content = ctx.asset(path)?.suspend()?;
20/// // Process content...
21/// Ok(output)
22/// }
23/// ```
24pub struct AssetLoadingState<K: AssetKey> {
25 value: Option<Arc<K::Asset>>,
26 key: K,
27}
28
29impl<K: AssetKey> AssetLoadingState<K> {
30 /// Create a loading state (asset not yet available).
31 pub fn loading(key: K) -> Self {
32 Self { value: None, key }
33 }
34
35 /// Create a ready state with the asset value.
36 pub fn ready(key: K, value: Arc<K::Asset>) -> Self {
37 Self {
38 value: Some(value),
39 key,
40 }
41 }
42
43 /// Check if the resource is still loading.
44 pub fn is_loading(&self) -> bool {
45 self.value.is_none()
46 }
47
48 /// Check if the resource is ready.
49 pub fn is_ready(&self) -> bool {
50 self.value.is_some()
51 }
52
53 /// Get the value if ready, None if loading.
54 pub fn get(&self) -> Option<&Arc<K::Asset>> {
55 self.value.as_ref()
56 }
57
58 /// Get the value if ready, None if loading (consuming version).
59 pub fn into_inner(self) -> Option<Arc<K::Asset>> {
60 self.value
61 }
62
63 /// Convert to Result - Loading becomes Err(QueryError::Suspend).
64 ///
65 /// Use this with the `?` operator to propagate loading state upward.
66 /// The returned error includes the asset key for debugging.
67 ///
68 /// # Example
69 ///
70 /// ```ignore
71 /// fn query(&self, ctx: &mut QueryContext) -> Result<MyOutput, QueryError> {
72 /// let data = ctx.asset(key)?.suspend()?;
73 /// // `data` is guaranteed to be ready here
74 /// Ok(process(data))
75 /// }
76 /// ```
77 pub fn suspend(self) -> Result<Arc<K::Asset>, QueryError> {
78 match self.value {
79 None => Err(QueryError::Suspend {
80 asset: PendingAsset::new(self.key),
81 }),
82 Some(v) => Ok(v),
83 }
84 }
85
86 /// Get a reference to the key.
87 pub fn key(&self) -> &K {
88 &self.key
89 }
90}
91
92impl<K: AssetKey> std::fmt::Debug for AssetLoadingState<K>
93where
94 K::Asset: std::fmt::Debug,
95{
96 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
97 match &self.value {
98 None => write!(f, "AssetLoadingState::Loading({:?})", self.key),
99 Some(v) => write!(f, "AssetLoadingState::Ready({:?}, {:?})", self.key, v),
100 }
101 }
102}