1use crate::{
2 initial_value, FromEncodedStr, IntoEncodedString,
3 IS_SUPPRESSING_RESOURCE_LOAD,
4};
5#[cfg(feature = "rkyv")]
6use codee::binary::RkyvCodec;
7#[cfg(feature = "serde-wasm-bindgen")]
8use codee::string::JsonSerdeWasmCodec;
9#[cfg(feature = "miniserde")]
10use codee::string::MiniserdeCodec;
11#[cfg(feature = "serde-lite")]
12use codee::SerdeLite;
13use codee::{
14 string::{FromToStringCodec, JsonSerdeCodec},
15 Decoder, Encoder,
16};
17use core::{fmt::Debug, marker::PhantomData};
18use futures::Future;
19use or_poisoned::OrPoisoned;
20use reactive_graph::{
21 computed::{
22 suspense::SuspenseContext, AsyncDerivedReadyFuture, ScopedFuture,
23 },
24 diagnostics::{SpecialNonReactiveFuture, SpecialNonReactiveZone},
25 graph::{AnySource, ToAnySource},
26 owner::{use_context, ArenaItem, Owner},
27 prelude::*,
28 signal::{
29 guards::{Plain, ReadGuard},
30 ArcTrigger,
31 },
32 unwrap_signal,
33};
34use std::{
35 future::IntoFuture,
36 mem,
37 panic::Location,
38 pin::Pin,
39 sync::{
40 atomic::{AtomicBool, Ordering},
41 Arc, RwLock,
42 },
43 task::{Context, Poll, Waker},
44};
45
46#[derive(Debug)]
56pub struct ArcOnceResource<T, Ser = JsonSerdeCodec> {
57 trigger: ArcTrigger,
58 value: Arc<RwLock<Option<T>>>,
59 wakers: Arc<RwLock<Vec<Waker>>>,
60 suspenses: Arc<RwLock<Vec<SuspenseContext>>>,
61 loading: Arc<AtomicBool>,
62 ser: PhantomData<fn() -> Ser>,
63 #[cfg(any(debug_assertions, leptos_debuginfo))]
64 defined_at: &'static Location<'static>,
65}
66
67impl<T, Ser> Clone for ArcOnceResource<T, Ser> {
68 fn clone(&self) -> Self {
69 Self {
70 trigger: self.trigger.clone(),
71 value: self.value.clone(),
72 wakers: self.wakers.clone(),
73 suspenses: self.suspenses.clone(),
74 loading: self.loading.clone(),
75 ser: self.ser,
76 #[cfg(any(debug_assertions, leptos_debuginfo))]
77 defined_at: self.defined_at,
78 }
79 }
80}
81
82impl<T, Ser> ArcOnceResource<T, Ser>
83where
84 T: Send + Sync + 'static,
85 Ser: Encoder<T> + Decoder<T>,
86 <Ser as Encoder<T>>::Error: Debug,
87 <Ser as Decoder<T>>::Error: Debug,
88 <<Ser as Decoder<T>>::Encoded as FromEncodedStr>::DecodingError: Debug,
89 <Ser as Encoder<T>>::Encoded: IntoEncodedString,
90 <Ser as Decoder<T>>::Encoded: FromEncodedStr,
91{
92 #[track_caller]
99 pub fn new_with_options(
100 fut: impl Future<Output = T> + Send + 'static,
101 #[allow(unused)] blocking: bool,
103 ) -> Self {
104 let shared_context = Owner::current_shared_context();
105 let id = shared_context
106 .as_ref()
107 .map(|sc| sc.next_id())
108 .unwrap_or_default();
109
110 let initial = initial_value::<T, Ser>(&id, shared_context.as_ref());
111 let is_ready = initial.is_some();
112 let value = Arc::new(RwLock::new(initial));
113 let wakers = Arc::new(RwLock::new(Vec::<Waker>::new()));
114 let suspenses = Arc::new(RwLock::new(Vec::<SuspenseContext>::new()));
115 let loading = Arc::new(AtomicBool::new(!is_ready));
116 let trigger = ArcTrigger::new();
117
118 let fut = ScopedFuture::new(fut);
119
120 if !is_ready && !IS_SUPPRESSING_RESOURCE_LOAD.load(Ordering::Relaxed) {
121 let value = Arc::clone(&value);
122 let wakers = Arc::clone(&wakers);
123 let loading = Arc::clone(&loading);
124 let trigger = trigger.clone();
125 reactive_graph::spawn(async move {
126 let loaded = fut.await;
127 *value.write().or_poisoned() = Some(loaded);
128 loading.store(false, Ordering::Relaxed);
129 for waker in mem::take(&mut *wakers.write().or_poisoned()) {
130 waker.wake();
131 }
132 trigger.notify();
133 });
134 }
135
136 let data = Self {
137 trigger,
138 value: value.clone(),
139 loading,
140 wakers,
141 suspenses,
142 ser: PhantomData,
143 #[cfg(any(debug_assertions, leptos_debuginfo))]
144 defined_at: Location::caller(),
145 };
146
147 #[cfg(feature = "ssr")]
148 if let Some(shared_context) = shared_context {
149 let value = Arc::clone(&value);
150 let ready_fut = data.ready();
151
152 if blocking {
153 shared_context.defer_stream(Box::pin(data.ready()));
154 }
155
156 if shared_context.get_is_hydrating() {
157 shared_context.write_async(
158 id,
159 Box::pin(async move {
160 ready_fut.await;
161 let value = value.read().or_poisoned();
162 let value = value.as_ref().unwrap();
163 Ser::encode(value).unwrap().into_encoded_string()
164 }),
165 );
166 }
167 }
168
169 data
170 }
171
172 #[track_caller]
175 pub fn map<U>(&self, f: impl FnOnce(&T) -> U) -> Option<U>
176 where
177 T: Send + Sync + 'static,
178 {
179 self.try_with(|n| n.as_ref().map(f))?
180 }
181}
182
183impl<T, E, Ser> ArcOnceResource<Result<T, E>, Ser>
184where
185 Ser: Encoder<Result<T, E>> + Decoder<Result<T, E>>,
186 <Ser as Encoder<Result<T, E>>>::Error: Debug,
187 <Ser as Decoder<Result<T, E>>>::Error: Debug,
188 <<Ser as Decoder<Result<T, E>>>::Encoded as FromEncodedStr>::DecodingError:
189 Debug,
190 <Ser as Encoder<Result<T, E>>>::Encoded: IntoEncodedString,
191 <Ser as Decoder<Result<T, E>>>::Encoded: FromEncodedStr,
192 T: Send + Sync + 'static,
193 E: Send + Sync + Clone + 'static,
194{
195 #[track_caller]
203 pub fn and_then<U>(&self, f: impl FnOnce(&T) -> U) -> Option<Result<U, E>> {
204 self.map(|data| data.as_ref().map(f).map_err(|e| e.clone()))
205 }
206}
207
208impl<T, Ser> ArcOnceResource<T, Ser> {
209 pub fn ready(&self) -> AsyncDerivedReadyFuture {
211 AsyncDerivedReadyFuture::new(
212 self.to_any_source(),
213 &self.loading,
214 &self.wakers,
215 )
216 }
217}
218
219impl<T, Ser> DefinedAt for ArcOnceResource<T, Ser> {
220 fn defined_at(&self) -> Option<&'static Location<'static>> {
221 #[cfg(not(any(debug_assertions, leptos_debuginfo)))]
222 {
223 None
224 }
225 #[cfg(any(debug_assertions, leptos_debuginfo))]
226 {
227 Some(self.defined_at)
228 }
229 }
230}
231
232impl<T, Ser> IsDisposed for ArcOnceResource<T, Ser> {
233 #[inline(always)]
234 fn is_disposed(&self) -> bool {
235 false
236 }
237}
238
239impl<T, Ser> ToAnySource for ArcOnceResource<T, Ser> {
240 fn to_any_source(&self) -> AnySource {
241 self.trigger.to_any_source()
242 }
243}
244
245impl<T, Ser> Track for ArcOnceResource<T, Ser> {
246 fn track(&self) {
247 self.trigger.track();
248 }
249}
250
251impl<T, Ser> ReadUntracked for ArcOnceResource<T, Ser>
252where
253 T: 'static,
254{
255 type Value = ReadGuard<Option<T>, Plain<Option<T>>>;
256
257 fn try_read_untracked(&self) -> Option<Self::Value> {
258 if let Some(suspense_context) = use_context::<SuspenseContext>() {
259 if self.value.read().or_poisoned().is_none() {
260 let handle = suspense_context.task_id();
261 let ready = SpecialNonReactiveFuture::new(self.ready());
262 reactive_graph::spawn(async move {
263 ready.await;
264 drop(handle);
265 });
266 self.suspenses.write().or_poisoned().push(suspense_context);
267 }
268 }
269 Plain::try_new(Arc::clone(&self.value)).map(ReadGuard::new)
270 }
271}
272
273impl<T, Ser> IntoFuture for ArcOnceResource<T, Ser>
274where
275 T: Clone + 'static,
276{
277 type Output = T;
278 type IntoFuture = OnceResourceFuture<T>;
279
280 fn into_future(self) -> Self::IntoFuture {
281 OnceResourceFuture {
282 source: self.to_any_source(),
283 value: Arc::clone(&self.value),
284 loading: Arc::clone(&self.loading),
285 wakers: Arc::clone(&self.wakers),
286 suspenses: Arc::clone(&self.suspenses),
287 }
288 }
289}
290
291pub struct OnceResourceFuture<T> {
295 source: AnySource,
296 value: Arc<RwLock<Option<T>>>,
297 loading: Arc<AtomicBool>,
298 wakers: Arc<RwLock<Vec<Waker>>>,
299 suspenses: Arc<RwLock<Vec<SuspenseContext>>>,
300}
301
302impl<T> Future for OnceResourceFuture<T>
303where
304 T: Clone + 'static,
305{
306 type Output = T;
307
308 #[track_caller]
309 fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
310 #[cfg(any(debug_assertions, leptos_debuginfo))]
311 let _guard = SpecialNonReactiveZone::enter();
312 let waker = cx.waker();
313 self.source.track();
314
315 if let Some(suspense_context) = use_context::<SuspenseContext>() {
316 self.suspenses.write().or_poisoned().push(suspense_context);
317 }
318
319 if self.loading.load(Ordering::Relaxed) {
320 self.wakers.write().or_poisoned().push(waker.clone());
321 Poll::Pending
322 } else {
323 Poll::Ready(
324 self.value.read().or_poisoned().as_ref().unwrap().clone(),
325 )
326 }
327 }
328}
329
330impl<T> ArcOnceResource<T, JsonSerdeCodec>
331where
332 T: Send + Sync + 'static,
333 JsonSerdeCodec: Encoder<T> + Decoder<T>,
334 <JsonSerdeCodec as Encoder<T>>::Error: Debug,
335 <JsonSerdeCodec as Decoder<T>>::Error: Debug,
336 <<JsonSerdeCodec as Decoder<T>>::Encoded as FromEncodedStr>::DecodingError:
337 Debug,
338 <JsonSerdeCodec as Encoder<T>>::Encoded: IntoEncodedString,
339 <JsonSerdeCodec as Decoder<T>>::Encoded: FromEncodedStr,
340{
341 #[track_caller]
343 pub fn new(fut: impl Future<Output = T> + Send + 'static) -> Self {
344 ArcOnceResource::new_with_options(fut, false)
345 }
346
347 #[track_caller]
353 pub fn new_blocking(fut: impl Future<Output = T> + Send + 'static) -> Self {
354 ArcOnceResource::new_with_options(fut, true)
355 }
356}
357
358impl<T> ArcOnceResource<T, FromToStringCodec>
359where
360T: Send + Sync + 'static,
361 FromToStringCodec: Encoder<T> + Decoder<T>,
362 <FromToStringCodec as Encoder<T>>::Error: Debug, <FromToStringCodec as Decoder<T>>::Error: Debug,
363 <<FromToStringCodec as Decoder<T>>::Encoded as FromEncodedStr>::DecodingError: Debug,
364 <FromToStringCodec as Encoder<T>>::Encoded: IntoEncodedString,
365 <FromToStringCodec as Decoder<T>>::Encoded: FromEncodedStr,
366{
367 pub fn new_str(
369 fut: impl Future<Output = T> + Send + 'static
370 ) -> Self
371 {
372 ArcOnceResource::new_with_options(fut, false)
373 }
374
375 pub fn new_str_blocking(
381 fut: impl Future<Output = T> + Send + 'static
382 ) -> Self
383 {
384 ArcOnceResource::new_with_options(fut, true)
385 }
386}
387
388#[cfg(feature = "serde-wasm-bindgen")]
389impl<T> ArcOnceResource<T, JsonSerdeWasmCodec>
390where
391T: Send + Sync + 'static,
392 JsonSerdeWasmCodec: Encoder<T> + Decoder<T>,
393 <JsonSerdeWasmCodec as Encoder<T>>::Error: Debug, <JsonSerdeWasmCodec as Decoder<T>>::Error: Debug,
394 <<JsonSerdeWasmCodec as Decoder<T>>::Encoded as FromEncodedStr>::DecodingError: Debug,
395 <JsonSerdeWasmCodec as Encoder<T>>::Encoded: IntoEncodedString,
396 <JsonSerdeWasmCodec as Decoder<T>>::Encoded: FromEncodedStr,
397{
398 #[track_caller]
400 pub fn new_serde_wb(
401fut: impl Future<Output = T> + Send + 'static
402 ) -> Self
403 {
404 ArcOnceResource::new_with_options(fut, false)
405 }
406
407 #[track_caller]
413 pub fn new_serde_wb_blocking(
414fut: impl Future<Output = T> + Send + 'static
415 ) -> Self
416 {
417 ArcOnceResource::new_with_options(fut, true)
418 }
419}
420#[cfg(feature = "miniserde")]
421impl<T> ArcOnceResource<T, MiniserdeCodec>
422where
423 T: Send + Sync + 'static,
424 MiniserdeCodec: Encoder<T> + Decoder<T>,
425 <MiniserdeCodec as Encoder<T>>::Error: Debug,
426 <MiniserdeCodec as Decoder<T>>::Error: Debug,
427 <<MiniserdeCodec as Decoder<T>>::Encoded as FromEncodedStr>::DecodingError:
428 Debug,
429 <MiniserdeCodec as Encoder<T>>::Encoded: IntoEncodedString,
430 <MiniserdeCodec as Decoder<T>>::Encoded: FromEncodedStr,
431{
432 #[track_caller]
434 pub fn new_miniserde(
435 fut: impl Future<Output = T> + Send + 'static,
436 ) -> Self {
437 ArcOnceResource::new_with_options(fut, false)
438 }
439
440 #[track_caller]
446 pub fn new_miniserde_blocking(
447 fut: impl Future<Output = T> + Send + 'static,
448 ) -> Self {
449 ArcOnceResource::new_with_options(fut, true)
450 }
451}
452
453#[cfg(feature = "serde-lite")]
454impl<T> ArcOnceResource<T, SerdeLite<JsonSerdeCodec>>
455where
456T: Send + Sync + 'static,
457 SerdeLite<JsonSerdeCodec>: Encoder<T> + Decoder<T>,
458 <SerdeLite<JsonSerdeCodec> as Encoder<T>>::Error: Debug, <SerdeLite<JsonSerdeCodec> as Decoder<T>>::Error: Debug,
459 <<SerdeLite<JsonSerdeCodec> as Decoder<T>>::Encoded as FromEncodedStr>::DecodingError: Debug,
460 <SerdeLite<JsonSerdeCodec> as Encoder<T>>::Encoded: IntoEncodedString,
461 <SerdeLite<JsonSerdeCodec> as Decoder<T>>::Encoded: FromEncodedStr,
462{
463 #[track_caller]
465 pub fn new_serde_lite(
466fut: impl Future<Output = T> + Send + 'static
467 ) -> Self
468 {
469 ArcOnceResource::new_with_options(fut, false)
470 }
471
472 #[track_caller]
478 pub fn new_serde_lite_blocking(
479fut: impl Future<Output = T> + Send + 'static
480 ) -> Self
481 {
482 ArcOnceResource::new_with_options(fut, true)
483 }
484}
485
486#[cfg(feature = "rkyv")]
487impl<T> ArcOnceResource<T, RkyvCodec>
488where
489 T: Send + Sync + 'static,
490 RkyvCodec: Encoder<T> + Decoder<T>,
491 <RkyvCodec as Encoder<T>>::Error: Debug,
492 <RkyvCodec as Decoder<T>>::Error: Debug,
493 <<RkyvCodec as Decoder<T>>::Encoded as FromEncodedStr>::DecodingError:
494 Debug,
495 <RkyvCodec as Encoder<T>>::Encoded: IntoEncodedString,
496 <RkyvCodec as Decoder<T>>::Encoded: FromEncodedStr,
497{
498 #[track_caller]
500 pub fn new_rkyv(fut: impl Future<Output = T> + Send + 'static) -> Self {
501 ArcOnceResource::new_with_options(fut, false)
502 }
503
504 #[track_caller]
510 pub fn new_rkyv_blocking(
511 fut: impl Future<Output = T> + Send + 'static,
512 ) -> Self {
513 ArcOnceResource::new_with_options(fut, true)
514 }
515}
516
517#[derive(Debug)]
527pub struct OnceResource<T, Ser = JsonSerdeCodec> {
528 inner: ArenaItem<ArcOnceResource<T, Ser>>,
529 #[cfg(any(debug_assertions, leptos_debuginfo))]
530 defined_at: &'static Location<'static>,
531}
532
533impl<T, Ser> Clone for OnceResource<T, Ser> {
534 fn clone(&self) -> Self {
535 *self
536 }
537}
538
539impl<T, Ser> Copy for OnceResource<T, Ser> {}
540
541impl<T, Ser> OnceResource<T, Ser>
542where
543 T: Send + Sync + 'static,
544 Ser: Encoder<T> + Decoder<T>,
545 <Ser as Encoder<T>>::Error: Debug,
546 <Ser as Decoder<T>>::Error: Debug,
547 <<Ser as Decoder<T>>::Encoded as FromEncodedStr>::DecodingError: Debug,
548 <Ser as Encoder<T>>::Encoded: IntoEncodedString,
549 <Ser as Decoder<T>>::Encoded: FromEncodedStr,
550{
551 #[track_caller]
558 pub fn new_with_options(
559 fut: impl Future<Output = T> + Send + 'static,
560 blocking: bool,
561 ) -> Self {
562 #[cfg(any(debug_assertions, leptos_debuginfo))]
563 let defined_at = Location::caller();
564 Self {
565 inner: ArenaItem::new(ArcOnceResource::new_with_options(
566 fut, blocking,
567 )),
568 #[cfg(any(debug_assertions, leptos_debuginfo))]
569 defined_at,
570 }
571 }
572
573 pub fn map<U>(&self, f: impl FnOnce(&T) -> U) -> Option<U> {
576 self.try_with(|n| n.as_ref().map(|n| Some(f(n))))?.flatten()
577 }
578}
579
580impl<T, E, Ser> OnceResource<Result<T, E>, Ser>
581where
582 Ser: Encoder<Result<T, E>> + Decoder<Result<T, E>>,
583 <Ser as Encoder<Result<T, E>>>::Error: Debug,
584 <Ser as Decoder<Result<T, E>>>::Error: Debug,
585 <<Ser as Decoder<Result<T, E>>>::Encoded as FromEncodedStr>::DecodingError:
586 Debug,
587 <Ser as Encoder<Result<T, E>>>::Encoded: IntoEncodedString,
588 <Ser as Decoder<Result<T, E>>>::Encoded: FromEncodedStr,
589 T: Send + Sync + 'static,
590 E: Send + Sync + Clone + 'static,
591{
592 #[track_caller]
600 pub fn and_then<U>(&self, f: impl FnOnce(&T) -> U) -> Option<Result<U, E>> {
601 self.map(|data| data.as_ref().map(f).map_err(|e| e.clone()))
602 }
603}
604
605impl<T, Ser> OnceResource<T, Ser>
606where
607 T: Send + Sync + 'static,
608 Ser: 'static,
609{
610 pub fn ready(&self) -> AsyncDerivedReadyFuture {
612 self.inner
613 .try_with_value(|inner| inner.ready())
614 .unwrap_or_else(unwrap_signal!(self))
615 }
616}
617
618impl<T, Ser> DefinedAt for OnceResource<T, Ser> {
619 fn defined_at(&self) -> Option<&'static Location<'static>> {
620 #[cfg(not(any(debug_assertions, leptos_debuginfo)))]
621 {
622 None
623 }
624 #[cfg(any(debug_assertions, leptos_debuginfo))]
625 {
626 Some(self.defined_at)
627 }
628 }
629}
630
631impl<T, Ser> IsDisposed for OnceResource<T, Ser> {
632 #[inline(always)]
633 fn is_disposed(&self) -> bool {
634 false
635 }
636}
637
638impl<T, Ser> ToAnySource for OnceResource<T, Ser>
639where
640 T: Send + Sync + 'static,
641 Ser: 'static,
642{
643 fn to_any_source(&self) -> AnySource {
644 self.inner
645 .try_with_value(|inner| inner.to_any_source())
646 .unwrap_or_else(unwrap_signal!(self))
647 }
648}
649
650impl<T, Ser> Track for OnceResource<T, Ser>
651where
652 T: Send + Sync + 'static,
653 Ser: 'static,
654{
655 fn track(&self) {
656 if let Some(inner) = self.inner.try_get_value() {
657 inner.track();
658 }
659 }
660}
661
662impl<T, Ser> ReadUntracked for OnceResource<T, Ser>
663where
664 T: Send + Sync + 'static,
665 Ser: 'static,
666{
667 type Value = ReadGuard<Option<T>, Plain<Option<T>>>;
668
669 fn try_read_untracked(&self) -> Option<Self::Value> {
670 self.inner
671 .try_with_value(|inner| inner.try_read_untracked())
672 .flatten()
673 }
674}
675
676impl<T, Ser> IntoFuture for OnceResource<T, Ser>
677where
678 T: Clone + Send + Sync + 'static,
679 Ser: 'static,
680{
681 type Output = T;
682 type IntoFuture = OnceResourceFuture<T>;
683
684 fn into_future(self) -> Self::IntoFuture {
685 self.inner
686 .try_get_value()
687 .unwrap_or_else(unwrap_signal!(self))
688 .into_future()
689 }
690}
691
692impl<T> OnceResource<T, JsonSerdeCodec>
693where
694 T: Send + Sync + 'static,
695 JsonSerdeCodec: Encoder<T> + Decoder<T>,
696 <JsonSerdeCodec as Encoder<T>>::Error: Debug,
697 <JsonSerdeCodec as Decoder<T>>::Error: Debug,
698 <<JsonSerdeCodec as Decoder<T>>::Encoded as FromEncodedStr>::DecodingError:
699 Debug,
700 <JsonSerdeCodec as Encoder<T>>::Encoded: IntoEncodedString,
701 <JsonSerdeCodec as Decoder<T>>::Encoded: FromEncodedStr,
702{
703 #[track_caller]
705 pub fn new(fut: impl Future<Output = T> + Send + 'static) -> Self {
706 OnceResource::new_with_options(fut, false)
707 }
708
709 #[track_caller]
715 pub fn new_blocking(fut: impl Future<Output = T> + Send + 'static) -> Self {
716 OnceResource::new_with_options(fut, true)
717 }
718}
719
720impl<T> OnceResource<T, FromToStringCodec>
721where
722T: Send + Sync + 'static,
723 FromToStringCodec: Encoder<T> + Decoder<T>,
724 <FromToStringCodec as Encoder<T>>::Error: Debug, <FromToStringCodec as Decoder<T>>::Error: Debug,
725 <<FromToStringCodec as Decoder<T>>::Encoded as FromEncodedStr>::DecodingError: Debug,
726 <FromToStringCodec as Encoder<T>>::Encoded: IntoEncodedString,
727 <FromToStringCodec as Decoder<T>>::Encoded: FromEncodedStr,
728{
729 pub fn new_str(
731 fut: impl Future<Output = T> + Send + 'static
732 ) -> Self
733 {
734 OnceResource::new_with_options(fut, false)
735 }
736
737 pub fn new_str_blocking(
743 fut: impl Future<Output = T> + Send + 'static
744 ) -> Self
745 {
746 OnceResource::new_with_options(fut, true)
747 }
748}
749
750#[cfg(feature = "serde-wasm-bindgen")]
751impl<T> OnceResource<T, JsonSerdeWasmCodec>
752where
753T: Send + Sync + 'static,
754 JsonSerdeWasmCodec: Encoder<T> + Decoder<T>,
755 <JsonSerdeWasmCodec as Encoder<T>>::Error: Debug, <JsonSerdeWasmCodec as Decoder<T>>::Error: Debug,
756 <<JsonSerdeWasmCodec as Decoder<T>>::Encoded as FromEncodedStr>::DecodingError: Debug,
757 <JsonSerdeWasmCodec as Encoder<T>>::Encoded: IntoEncodedString,
758 <JsonSerdeWasmCodec as Decoder<T>>::Encoded: FromEncodedStr,
759{
760 #[track_caller]
762 pub fn new_serde_wb(
763fut: impl Future<Output = T> + Send + 'static
764 ) -> Self
765 {
766 OnceResource::new_with_options(fut, false)
767 }
768
769 #[track_caller]
775 pub fn new_serde_wb_blocking(
776fut: impl Future<Output = T> + Send + 'static
777 ) -> Self
778 {
779 OnceResource::new_with_options(fut, true)
780 }
781}
782#[cfg(feature = "miniserde")]
783impl<T> OnceResource<T, MiniserdeCodec>
784where
785 T: Send + Sync + 'static,
786 MiniserdeCodec: Encoder<T> + Decoder<T>,
787 <MiniserdeCodec as Encoder<T>>::Error: Debug,
788 <MiniserdeCodec as Decoder<T>>::Error: Debug,
789 <<MiniserdeCodec as Decoder<T>>::Encoded as FromEncodedStr>::DecodingError:
790 Debug,
791 <MiniserdeCodec as Encoder<T>>::Encoded: IntoEncodedString,
792 <MiniserdeCodec as Decoder<T>>::Encoded: FromEncodedStr,
793{
794 #[track_caller]
796 pub fn new_miniserde(
797 fut: impl Future<Output = T> + Send + 'static,
798 ) -> Self {
799 OnceResource::new_with_options(fut, false)
800 }
801
802 #[track_caller]
808 pub fn new_miniserde_blocking(
809 fut: impl Future<Output = T> + Send + 'static,
810 ) -> Self {
811 OnceResource::new_with_options(fut, true)
812 }
813}
814
815#[cfg(feature = "serde-lite")]
816impl<T> OnceResource<T, SerdeLite<JsonSerdeCodec>>
817where
818T: Send + Sync + 'static,
819 SerdeLite<JsonSerdeCodec>: Encoder<T> + Decoder<T>,
820 <SerdeLite<JsonSerdeCodec> as Encoder<T>>::Error: Debug, <SerdeLite<JsonSerdeCodec> as Decoder<T>>::Error: Debug,
821 <<SerdeLite<JsonSerdeCodec> as Decoder<T>>::Encoded as FromEncodedStr>::DecodingError: Debug,
822 <SerdeLite<JsonSerdeCodec> as Encoder<T>>::Encoded: IntoEncodedString,
823 <SerdeLite<JsonSerdeCodec> as Decoder<T>>::Encoded: FromEncodedStr,
824{
825 #[track_caller]
827 pub fn new_serde_lite(
828fut: impl Future<Output = T> + Send + 'static
829 ) -> Self
830 {
831 OnceResource::new_with_options(fut, false)
832 }
833
834 #[track_caller]
840 pub fn new_serde_lite_blocking(
841fut: impl Future<Output = T> + Send + 'static
842 ) -> Self
843 {
844 OnceResource::new_with_options(fut, true)
845 }
846}
847
848#[cfg(feature = "rkyv")]
849impl<T> OnceResource<T, RkyvCodec>
850where
851 T: Send + Sync + 'static,
852 RkyvCodec: Encoder<T> + Decoder<T>,
853 <RkyvCodec as Encoder<T>>::Error: Debug,
854 <RkyvCodec as Decoder<T>>::Error: Debug,
855 <<RkyvCodec as Decoder<T>>::Encoded as FromEncodedStr>::DecodingError:
856 Debug,
857 <RkyvCodec as Encoder<T>>::Encoded: IntoEncodedString,
858 <RkyvCodec as Decoder<T>>::Encoded: FromEncodedStr,
859{
860 #[track_caller]
862 pub fn new_rkyv(fut: impl Future<Output = T> + Send + 'static) -> Self {
863 OnceResource::new_with_options(fut, false)
864 }
865
866 #[track_caller]
872 pub fn new_rkyv_blocking(
873 fut: impl Future<Output = T> + Send + 'static,
874 ) -> Self {
875 OnceResource::new_with_options(fut, true)
876 }
877}