1use core::marker::PhantomData;
6use yoke::Yokeable;
7
8use crate::prelude::*;
9
10pub trait DataProvider<M>
12where
13 M: DataMarker,
14{
15 fn load(&self, req: DataRequest) -> Result<DataResponse<M>, DataError>;
20}
21
22impl<M, P> DataProvider<M> for &P
23where
24 M: DataMarker,
25 P: DataProvider<M> + ?Sized,
26{
27 #[inline]
28 fn load(&self, req: DataRequest) -> Result<DataResponse<M>, DataError> {
29 (*self).load(req)
30 }
31}
32
33#[cfg(feature = "alloc")]
34impl<M, P> DataProvider<M> for alloc::boxed::Box<P>
35where
36 M: DataMarker,
37 P: DataProvider<M> + ?Sized,
38{
39 #[inline]
40 fn load(&self, req: DataRequest) -> Result<DataResponse<M>, DataError> {
41 (**self).load(req)
42 }
43}
44
45#[cfg(feature = "alloc")]
46impl<M, P> DataProvider<M> for alloc::rc::Rc<P>
47where
48 M: DataMarker,
49 P: DataProvider<M> + ?Sized,
50{
51 #[inline]
52 fn load(&self, req: DataRequest) -> Result<DataResponse<M>, DataError> {
53 (**self).load(req)
54 }
55}
56
57#[cfg(target_has_atomic = "ptr")]
58#[cfg(feature = "alloc")]
59impl<M, P> DataProvider<M> for alloc::sync::Arc<P>
60where
61 M: DataMarker,
62 P: DataProvider<M> + ?Sized,
63{
64 #[inline]
65 fn load(&self, req: DataRequest) -> Result<DataResponse<M>, DataError> {
66 (**self).load(req)
67 }
68}
69
70pub trait DryDataProvider<M: DataMarker>: DataProvider<M> {
73 fn dry_load(&self, req: DataRequest) -> Result<DataResponseMetadata, DataError>;
81}
82
83impl<M, P> DryDataProvider<M> for &P
84where
85 M: DataMarker,
86 P: DryDataProvider<M> + ?Sized,
87{
88 #[inline]
89 fn dry_load(&self, req: DataRequest) -> Result<DataResponseMetadata, DataError> {
90 (*self).dry_load(req)
91 }
92}
93
94#[cfg(feature = "alloc")]
95impl<M, P> DryDataProvider<M> for alloc::boxed::Box<P>
96where
97 M: DataMarker,
98 P: DryDataProvider<M> + ?Sized,
99{
100 #[inline]
101 fn dry_load(&self, req: DataRequest) -> Result<DataResponseMetadata, DataError> {
102 (**self).dry_load(req)
103 }
104}
105
106#[cfg(feature = "alloc")]
107impl<M, P> DryDataProvider<M> for alloc::rc::Rc<P>
108where
109 M: DataMarker,
110 P: DryDataProvider<M> + ?Sized,
111{
112 #[inline]
113 fn dry_load(&self, req: DataRequest) -> Result<DataResponseMetadata, DataError> {
114 (**self).dry_load(req)
115 }
116}
117
118#[cfg(target_has_atomic = "ptr")]
119#[cfg(feature = "alloc")]
120impl<M, P> DryDataProvider<M> for alloc::sync::Arc<P>
121where
122 M: DataMarker,
123 P: DryDataProvider<M> + ?Sized,
124{
125 #[inline]
126 fn dry_load(&self, req: DataRequest) -> Result<DataResponseMetadata, DataError> {
127 (**self).dry_load(req)
128 }
129}
130
131#[cfg(feature = "alloc")]
138pub trait IterableDataProvider<M: DataMarker>: DataProvider<M> {
139 fn iter_ids(&self) -> Result<alloc::collections::BTreeSet<DataIdentifierCow<'_>>, DataError>;
141}
142
143pub trait DynamicDataProvider<M>
147where
148 M: DynamicDataMarker,
149{
150 fn load_data(
155 &self,
156 marker: DataMarkerInfo,
157 req: DataRequest,
158 ) -> Result<DataResponse<M>, DataError>;
159}
160
161impl<M, P> DynamicDataProvider<M> for &P
162where
163 M: DynamicDataMarker,
164 P: DynamicDataProvider<M> + ?Sized,
165{
166 #[inline]
167 fn load_data(
168 &self,
169 marker: DataMarkerInfo,
170 req: DataRequest,
171 ) -> Result<DataResponse<M>, DataError> {
172 (*self).load_data(marker, req)
173 }
174}
175
176#[cfg(feature = "alloc")]
177impl<M, P> DynamicDataProvider<M> for alloc::boxed::Box<P>
178where
179 M: DynamicDataMarker,
180 P: DynamicDataProvider<M> + ?Sized,
181{
182 #[inline]
183 fn load_data(
184 &self,
185 marker: DataMarkerInfo,
186 req: DataRequest,
187 ) -> Result<DataResponse<M>, DataError> {
188 (**self).load_data(marker, req)
189 }
190}
191
192#[cfg(feature = "alloc")]
193impl<M, P> DynamicDataProvider<M> for alloc::rc::Rc<P>
194where
195 M: DynamicDataMarker,
196 P: DynamicDataProvider<M> + ?Sized,
197{
198 #[inline]
199 fn load_data(
200 &self,
201 marker: DataMarkerInfo,
202 req: DataRequest,
203 ) -> Result<DataResponse<M>, DataError> {
204 (**self).load_data(marker, req)
205 }
206}
207
208#[cfg(target_has_atomic = "ptr")]
209#[cfg(feature = "alloc")]
210impl<M, P> DynamicDataProvider<M> for alloc::sync::Arc<P>
211where
212 M: DynamicDataMarker,
213 P: DynamicDataProvider<M> + ?Sized,
214{
215 #[inline]
216 fn load_data(
217 &self,
218 marker: DataMarkerInfo,
219 req: DataRequest,
220 ) -> Result<DataResponse<M>, DataError> {
221 (**self).load_data(marker, req)
222 }
223}
224
225pub trait DynamicDryDataProvider<M: DynamicDataMarker>: DynamicDataProvider<M> {
228 fn dry_load_data(
236 &self,
237 marker: DataMarkerInfo,
238 req: DataRequest,
239 ) -> Result<DataResponseMetadata, DataError>;
240}
241
242impl<M, P> DynamicDryDataProvider<M> for &P
243where
244 M: DynamicDataMarker,
245 P: DynamicDryDataProvider<M> + ?Sized,
246{
247 #[inline]
248 fn dry_load_data(
249 &self,
250 marker: DataMarkerInfo,
251 req: DataRequest,
252 ) -> Result<DataResponseMetadata, DataError> {
253 (*self).dry_load_data(marker, req)
254 }
255}
256
257#[cfg(feature = "alloc")]
258impl<M, P> DynamicDryDataProvider<M> for alloc::boxed::Box<P>
259where
260 M: DynamicDataMarker,
261 P: DynamicDryDataProvider<M> + ?Sized,
262{
263 #[inline]
264 fn dry_load_data(
265 &self,
266 marker: DataMarkerInfo,
267 req: DataRequest,
268 ) -> Result<DataResponseMetadata, DataError> {
269 (**self).dry_load_data(marker, req)
270 }
271}
272
273#[cfg(feature = "alloc")]
274impl<M, P> DynamicDryDataProvider<M> for alloc::rc::Rc<P>
275where
276 M: DynamicDataMarker,
277 P: DynamicDryDataProvider<M> + ?Sized,
278{
279 #[inline]
280 fn dry_load_data(
281 &self,
282 marker: DataMarkerInfo,
283 req: DataRequest,
284 ) -> Result<DataResponseMetadata, DataError> {
285 (**self).dry_load_data(marker, req)
286 }
287}
288
289#[cfg(target_has_atomic = "ptr")]
290#[cfg(feature = "alloc")]
291impl<M, P> DynamicDryDataProvider<M> for alloc::sync::Arc<P>
292where
293 M: DynamicDataMarker,
294 P: DynamicDryDataProvider<M> + ?Sized,
295{
296 #[inline]
297 fn dry_load_data(
298 &self,
299 marker: DataMarkerInfo,
300 req: DataRequest,
301 ) -> Result<DataResponseMetadata, DataError> {
302 (**self).dry_load_data(marker, req)
303 }
304}
305
306#[cfg(feature = "alloc")]
313pub trait IterableDynamicDataProvider<M: DynamicDataMarker>: DynamicDataProvider<M> {
314 fn iter_ids_for_marker(
316 &self,
317 marker: DataMarkerInfo,
318 ) -> Result<alloc::collections::BTreeSet<DataIdentifierCow<'_>>, DataError>;
319}
320
321#[cfg(feature = "alloc")]
322impl<M, P> IterableDynamicDataProvider<M> for alloc::boxed::Box<P>
323where
324 M: DynamicDataMarker,
325 P: IterableDynamicDataProvider<M> + ?Sized,
326{
327 fn iter_ids_for_marker(
328 &self,
329 marker: DataMarkerInfo,
330 ) -> Result<alloc::collections::BTreeSet<DataIdentifierCow<'_>>, DataError> {
331 (**self).iter_ids_for_marker(marker)
332 }
333}
334
335pub trait BoundDataProvider<M>
344where
345 M: DynamicDataMarker,
346{
347 fn load_bound(&self, req: DataRequest) -> Result<DataResponse<M>, DataError>;
352 fn bound_marker(&self) -> DataMarkerInfo;
354}
355
356impl<M, P> BoundDataProvider<M> for &P
357where
358 M: DynamicDataMarker,
359 P: BoundDataProvider<M> + ?Sized,
360{
361 #[inline]
362 fn load_bound(&self, req: DataRequest) -> Result<DataResponse<M>, DataError> {
363 (*self).load_bound(req)
364 }
365 #[inline]
366 fn bound_marker(&self) -> DataMarkerInfo {
367 (*self).bound_marker()
368 }
369}
370
371#[cfg(feature = "alloc")]
372impl<M, P> BoundDataProvider<M> for alloc::boxed::Box<P>
373where
374 M: DynamicDataMarker,
375 P: BoundDataProvider<M> + ?Sized,
376{
377 #[inline]
378 fn load_bound(&self, req: DataRequest) -> Result<DataResponse<M>, DataError> {
379 (**self).load_bound(req)
380 }
381 #[inline]
382 fn bound_marker(&self) -> DataMarkerInfo {
383 (**self).bound_marker()
384 }
385}
386
387#[cfg(feature = "alloc")]
388impl<M, P> BoundDataProvider<M> for alloc::rc::Rc<P>
389where
390 M: DynamicDataMarker,
391 P: BoundDataProvider<M> + ?Sized,
392{
393 #[inline]
394 fn load_bound(&self, req: DataRequest) -> Result<DataResponse<M>, DataError> {
395 (**self).load_bound(req)
396 }
397 #[inline]
398 fn bound_marker(&self) -> DataMarkerInfo {
399 (**self).bound_marker()
400 }
401}
402
403#[cfg(target_has_atomic = "ptr")]
404#[cfg(feature = "alloc")]
405impl<M, P> BoundDataProvider<M> for alloc::sync::Arc<P>
406where
407 M: DynamicDataMarker,
408 P: BoundDataProvider<M> + ?Sized,
409{
410 #[inline]
411 fn load_bound(&self, req: DataRequest) -> Result<DataResponse<M>, DataError> {
412 (**self).load_bound(req)
413 }
414 #[inline]
415 fn bound_marker(&self) -> DataMarkerInfo {
416 (**self).bound_marker()
417 }
418}
419
420#[derive(#[automatically_derived]
impl<M: ::core::fmt::Debug, P: ::core::fmt::Debug> ::core::fmt::Debug for
DataProviderWithMarker<M, P> {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field2_finish(f,
"DataProviderWithMarker", "inner", &self.inner, "_marker",
&&self._marker)
}
}Debug)]
424pub struct DataProviderWithMarker<M, P> {
425 inner: P,
426 _marker: PhantomData<M>,
427}
428
429impl<M, P> DataProviderWithMarker<M, P>
430where
431 M: DataMarker,
432 P: DataProvider<M>,
433{
434 pub const fn new(inner: P) -> Self {
436 Self {
437 inner,
438 _marker: PhantomData,
439 }
440 }
441}
442
443impl<M, M0, Y, P> BoundDataProvider<M0> for DataProviderWithMarker<M, P>
444where
445 M: DataMarker<DataStruct = Y>,
446 M0: DynamicDataMarker<DataStruct = Y>,
447 Y: for<'a> Yokeable<'a>,
448 P: DataProvider<M>,
449{
450 #[inline]
451 fn load_bound(&self, req: DataRequest) -> Result<DataResponse<M0>, DataError> {
452 self.inner.load(req).map(DataResponse::cast)
453 }
454 #[inline]
455 fn bound_marker(&self) -> DataMarkerInfo {
456 M::INFO
457 }
458}
459
460#[cfg(test)]
461mod test {
462
463 use super::*;
464 use crate::hello_world::*;
465 use alloc::borrow::Cow;
466 use alloc::string::String;
467 use core::fmt::Debug;
468 use serde::{Deserialize, Serialize};
469
470 #[derive(Serialize, Deserialize, Debug, Clone, Default, PartialEq, yoke::Yokeable)]
475 pub struct HelloAlt {
476 message: String,
477 }
478
479 data_marker!(HelloAltMarkerV1, HelloAlt);
480
481 #[derive(Deserialize, Debug, Clone, Default, PartialEq)]
482 struct HelloCombined<'data> {
483 #[serde(borrow)]
484 pub hello_v1: HelloWorld<'data>,
485 pub hello_alt: HelloAlt,
486 }
487
488 #[derive(Debug)]
491 struct DataWarehouse {
492 hello_v1: HelloWorld<'static>,
493 hello_alt: HelloAlt,
494 }
495
496 impl DataProvider<HelloWorldV1> for DataWarehouse {
497 fn load(&self, _: DataRequest) -> Result<DataResponse<HelloWorldV1>, DataError> {
498 Ok(DataResponse {
499 metadata: DataResponseMetadata::default(),
500 payload: DataPayload::from_owned(self.hello_v1.clone()),
501 })
502 }
503 }
504
505 #[derive(Debug)]
507 struct DataProvider2 {
508 data: DataWarehouse,
509 }
510
511 impl From<DataWarehouse> for DataProvider2 {
512 fn from(warehouse: DataWarehouse) -> Self {
513 DataProvider2 { data: warehouse }
514 }
515 }
516
517 impl DataProvider<HelloWorldV1> for DataProvider2 {
518 fn load(&self, _: DataRequest) -> Result<DataResponse<HelloWorldV1>, DataError> {
519 Ok(DataResponse {
520 metadata: DataResponseMetadata::default(),
521 payload: DataPayload::from_owned(self.data.hello_v1.clone()),
522 })
523 }
524 }
525
526 impl DataProvider<HelloAltMarkerV1> for DataProvider2 {
527 fn load(&self, _: DataRequest) -> Result<DataResponse<HelloAltMarkerV1>, DataError> {
528 Ok(DataResponse {
529 metadata: DataResponseMetadata::default(),
530 payload: DataPayload::from_owned(self.data.hello_alt.clone()),
531 })
532 }
533 }
534
535 const DATA: &str = r#"{
536 "hello_v1": {
537 "message": "Hello "
538 },
539 "hello_alt": {
540 "message": "Hello Alt"
541 }
542 }"#;
543
544 fn get_warehouse(data: &'static str) -> DataWarehouse {
545 let data: HelloCombined = serde_json::from_str(data).expect("Well-formed data");
546 DataWarehouse {
547 hello_v1: data.hello_v1,
548 hello_alt: data.hello_alt,
549 }
550 }
551
552 fn get_payload_v1<P: DataProvider<HelloWorldV1> + ?Sized>(
553 provider: &P,
554 ) -> Result<DataPayload<HelloWorldV1>, DataError> {
555 provider.load(Default::default()).map(|r| r.payload)
556 }
557
558 fn get_payload_alt<P: DataProvider<HelloAltMarkerV1> + ?Sized>(
559 provider: &P,
560 ) -> Result<DataPayload<HelloAltMarkerV1>, DataError> {
561 provider.load(Default::default()).map(|r| r.payload)
562 }
563
564 #[test]
565 fn test_warehouse_owned() {
566 let warehouse = get_warehouse(DATA);
567 let hello_data = get_payload_v1(&warehouse).unwrap();
568 assert!(matches!(
569 hello_data.get(),
570 HelloWorld {
571 message: Cow::Borrowed(_),
572 }
573 ));
574 }
575
576 #[test]
577 fn test_warehouse_owned_dyn_generic() {
578 let warehouse = get_warehouse(DATA);
579 let hello_data = get_payload_v1(&warehouse as &dyn DataProvider<HelloWorldV1>).unwrap();
580 assert!(matches!(
581 hello_data.get(),
582 HelloWorld {
583 message: Cow::Borrowed(_),
584 }
585 ));
586 }
587
588 #[test]
589 fn test_provider2() {
590 let warehouse = get_warehouse(DATA);
591 let provider = DataProvider2::from(warehouse);
592 let hello_data = get_payload_v1(&provider).unwrap();
593 assert!(matches!(
594 hello_data.get(),
595 HelloWorld {
596 message: Cow::Borrowed(_),
597 }
598 ));
599 }
600
601 #[test]
602 fn test_provider2_dyn_generic() {
603 let warehouse = get_warehouse(DATA);
604 let provider = DataProvider2::from(warehouse);
605 let hello_data = get_payload_v1(&provider as &dyn DataProvider<HelloWorldV1>).unwrap();
606 assert!(matches!(
607 hello_data.get(),
608 HelloWorld {
609 message: Cow::Borrowed(_),
610 }
611 ));
612 }
613
614 #[test]
615 fn test_provider2_dyn_generic_alt() {
616 let warehouse = get_warehouse(DATA);
617 let provider = DataProvider2::from(warehouse);
618 let hello_data = get_payload_alt(&provider as &dyn DataProvider<HelloAltMarkerV1>).unwrap();
619 assert!(matches!(hello_data.get(), HelloAlt { .. }));
620 }
621
622 fn check_v1_v2<P>(d: &P)
623 where
624 P: DataProvider<HelloWorldV1> + DataProvider<HelloAltMarkerV1> + ?Sized,
625 {
626 let v1: DataPayload<HelloWorldV1> = d.load(Default::default()).unwrap().payload;
627 let v2: DataPayload<HelloAltMarkerV1> = d.load(Default::default()).unwrap().payload;
628 if v1.get().message == v2.get().message {
629 panic!()
630 }
631 }
632
633 #[test]
634 fn test_v1_v2_generic() {
635 let warehouse = get_warehouse(DATA);
636 let provider = DataProvider2::from(warehouse);
637 check_v1_v2(&provider);
638 }
639}