1use core::marker::PhantomData;
6use yoke::Yokeable;
7
8use crate::error::DataError;
9use crate::key::DataKey;
10use crate::marker::{DataMarker, KeyedDataMarker};
11use crate::request::DataRequest;
12use crate::response::DataResponse;
13
14pub trait DataProvider<M>
16where
17 M: KeyedDataMarker,
18{
19 fn load(&self, req: DataRequest) -> Result<DataResponse<M>, DataError>;
24}
25
26impl<'a, M, P> DataProvider<M> for &'a P
27where
28 M: KeyedDataMarker,
29 P: DataProvider<M> + ?Sized,
30{
31 #[inline]
32 fn load(&self, req: DataRequest) -> Result<DataResponse<M>, DataError> {
33 (*self).load(req)
34 }
35}
36
37impl<M, P> DataProvider<M> for alloc::boxed::Box<P>
38where
39 M: KeyedDataMarker,
40 P: DataProvider<M> + ?Sized,
41{
42 #[inline]
43 fn load(&self, req: DataRequest) -> Result<DataResponse<M>, DataError> {
44 (**self).load(req)
45 }
46}
47
48impl<M, P> DataProvider<M> for alloc::rc::Rc<P>
49where
50 M: KeyedDataMarker,
51 P: DataProvider<M> + ?Sized,
52{
53 #[inline]
54 fn load(&self, req: DataRequest) -> Result<DataResponse<M>, DataError> {
55 (**self).load(req)
56 }
57}
58
59#[cfg(target_has_atomic = "ptr")]
60impl<M, P> DataProvider<M> for alloc::sync::Arc<P>
61where
62 M: KeyedDataMarker,
63 P: DataProvider<M> + ?Sized,
64{
65 #[inline]
66 fn load(&self, req: DataRequest) -> Result<DataResponse<M>, DataError> {
67 (**self).load(req)
68 }
69}
70
71pub trait DynamicDataProvider<M>
78where
79 M: DataMarker,
80{
81 fn load_data(&self, key: DataKey, req: DataRequest) -> Result<DataResponse<M>, DataError>;
86}
87
88impl<'a, M, P> DynamicDataProvider<M> for &'a P
89where
90 M: DataMarker,
91 P: DynamicDataProvider<M> + ?Sized,
92{
93 #[inline]
94 fn load_data(&self, key: DataKey, req: DataRequest) -> Result<DataResponse<M>, DataError> {
95 (*self).load_data(key, req)
96 }
97}
98
99impl<M, P> DynamicDataProvider<M> for alloc::boxed::Box<P>
100where
101 M: DataMarker,
102 P: DynamicDataProvider<M> + ?Sized,
103{
104 #[inline]
105 fn load_data(&self, key: DataKey, req: DataRequest) -> Result<DataResponse<M>, DataError> {
106 (**self).load_data(key, req)
107 }
108}
109
110impl<M, P> DynamicDataProvider<M> for alloc::rc::Rc<P>
111where
112 M: DataMarker,
113 P: DynamicDataProvider<M> + ?Sized,
114{
115 #[inline]
116 fn load_data(&self, key: DataKey, req: DataRequest) -> Result<DataResponse<M>, DataError> {
117 (**self).load_data(key, req)
118 }
119}
120
121#[cfg(target_has_atomic = "ptr")]
122impl<M, P> DynamicDataProvider<M> for alloc::sync::Arc<P>
123where
124 M: DataMarker,
125 P: DynamicDataProvider<M> + ?Sized,
126{
127 #[inline]
128 fn load_data(&self, key: DataKey, req: DataRequest) -> Result<DataResponse<M>, DataError> {
129 (**self).load_data(key, req)
130 }
131}
132
133pub trait BoundDataProvider<M>
144where
145 M: DataMarker,
146{
147 fn load_bound(&self, req: DataRequest) -> Result<DataResponse<M>, DataError>;
152 fn bound_key(&self) -> DataKey;
154}
155
156impl<'a, M, P> BoundDataProvider<M> for &'a P
157where
158 M: DataMarker,
159 P: BoundDataProvider<M> + ?Sized,
160{
161 #[inline]
162 fn load_bound(&self, req: DataRequest) -> Result<DataResponse<M>, DataError> {
163 (*self).load_bound(req)
164 }
165 #[inline]
166 fn bound_key(&self) -> DataKey {
167 (*self).bound_key()
168 }
169}
170
171impl<M, P> BoundDataProvider<M> for alloc::boxed::Box<P>
172where
173 M: DataMarker,
174 P: BoundDataProvider<M> + ?Sized,
175{
176 #[inline]
177 fn load_bound(&self, req: DataRequest) -> Result<DataResponse<M>, DataError> {
178 (**self).load_bound(req)
179 }
180 #[inline]
181 fn bound_key(&self) -> DataKey {
182 (**self).bound_key()
183 }
184}
185
186impl<M, P> BoundDataProvider<M> for alloc::rc::Rc<P>
187where
188 M: DataMarker,
189 P: BoundDataProvider<M> + ?Sized,
190{
191 #[inline]
192 fn load_bound(&self, req: DataRequest) -> Result<DataResponse<M>, DataError> {
193 (**self).load_bound(req)
194 }
195 #[inline]
196 fn bound_key(&self) -> DataKey {
197 (**self).bound_key()
198 }
199}
200
201#[cfg(target_has_atomic = "ptr")]
202impl<M, P> BoundDataProvider<M> for alloc::sync::Arc<P>
203where
204 M: DataMarker,
205 P: BoundDataProvider<M> + ?Sized,
206{
207 #[inline]
208 fn load_bound(&self, req: DataRequest) -> Result<DataResponse<M>, DataError> {
209 (**self).load_bound(req)
210 }
211 #[inline]
212 fn bound_key(&self) -> DataKey {
213 (**self).bound_key()
214 }
215}
216
217#[derive(Debug)]
221pub struct DataProviderWithKey<M, P> {
222 inner: P,
223 _marker: PhantomData<M>,
224}
225
226impl<M, P> DataProviderWithKey<M, P>
227where
228 M: KeyedDataMarker,
229 P: DataProvider<M>,
230{
231 pub const fn new(inner: P) -> Self {
233 Self {
234 inner,
235 _marker: PhantomData,
236 }
237 }
238}
239
240impl<M, M0, Y, P> BoundDataProvider<M0> for DataProviderWithKey<M, P>
241where
242 M: KeyedDataMarker<Yokeable = Y>,
243 M0: DataMarker<Yokeable = Y>,
244 Y: for<'a> Yokeable<'a>,
245 P: DataProvider<M>,
246{
247 #[inline]
248 fn load_bound(&self, req: DataRequest) -> Result<DataResponse<M0>, DataError> {
249 self.inner.load(req).map(DataResponse::cast)
250 }
251 #[inline]
252 fn bound_key(&self) -> DataKey {
253 M::KEY
254 }
255}
256
257#[cfg(test)]
258mod test {
259
260 use super::*;
261 use crate::hello_world::*;
262 use crate::prelude::*;
263 use alloc::borrow::Cow;
264 use alloc::string::String;
265 use core::fmt::Debug;
266 use serde::{Deserialize, Serialize};
267
268 const HELLO_ALT_KEY: DataKey = crate::data_key!("core/helloalt@1");
273
274 #[derive(
276 Serialize, Deserialize, Debug, Clone, Default, PartialEq, yoke::Yokeable, zerofrom::ZeroFrom,
277 )]
278 struct HelloAlt {
279 #[zerofrom(clone)]
280 message: String,
281 }
282
283 struct HelloAltMarker {}
285
286 impl DataMarker for HelloAltMarker {
287 type Yokeable = HelloAlt;
288 }
289
290 impl KeyedDataMarker for HelloAltMarker {
291 const KEY: DataKey = HELLO_ALT_KEY;
292 }
293
294 #[derive(Deserialize, Debug, Clone, Default, PartialEq)]
295 struct HelloCombined<'data> {
296 #[serde(borrow)]
297 pub hello_v1: HelloWorldV1<'data>,
298 pub hello_alt: HelloAlt,
299 }
300
301 #[derive(Debug)]
304 struct DataWarehouse {
305 hello_v1: HelloWorldV1<'static>,
306 hello_alt: HelloAlt,
307 }
308
309 impl DataProvider<HelloWorldV1Marker> for DataWarehouse {
310 fn load(&self, _: DataRequest) -> Result<DataResponse<HelloWorldV1Marker>, DataError> {
311 Ok(DataResponse {
312 metadata: DataResponseMetadata::default(),
313 payload: Some(DataPayload::from_owned(self.hello_v1.clone())),
314 })
315 }
316 }
317
318 crate::impl_dynamic_data_provider!(DataWarehouse, [HelloWorldV1Marker,], AnyMarker);
319
320 #[derive(Debug)]
322 struct DataProvider2 {
323 data: DataWarehouse,
324 }
325
326 impl From<DataWarehouse> for DataProvider2 {
327 fn from(warehouse: DataWarehouse) -> Self {
328 DataProvider2 { data: warehouse }
329 }
330 }
331
332 impl DataProvider<HelloWorldV1Marker> for DataProvider2 {
333 fn load(&self, _: DataRequest) -> Result<DataResponse<HelloWorldV1Marker>, DataError> {
334 Ok(DataResponse {
335 metadata: DataResponseMetadata::default(),
336 payload: Some(DataPayload::from_owned(self.data.hello_v1.clone())),
337 })
338 }
339 }
340
341 impl DataProvider<HelloAltMarker> for DataProvider2 {
342 fn load(&self, _: DataRequest) -> Result<DataResponse<HelloAltMarker>, DataError> {
343 Ok(DataResponse {
344 metadata: DataResponseMetadata::default(),
345 payload: Some(DataPayload::from_owned(self.data.hello_alt.clone())),
346 })
347 }
348 }
349
350 crate::impl_dynamic_data_provider!(
351 DataProvider2,
352 [HelloWorldV1Marker, HelloAltMarker,],
353 AnyMarker
354 );
355
356 const DATA: &str = r#"{
357 "hello_v1": {
358 "message": "Hello V1"
359 },
360 "hello_alt": {
361 "message": "Hello Alt"
362 }
363 }"#;
364
365 fn get_warehouse(data: &'static str) -> DataWarehouse {
366 let data: HelloCombined = serde_json::from_str(data).expect("Well-formed data");
367 DataWarehouse {
368 hello_v1: data.hello_v1,
369 hello_alt: data.hello_alt,
370 }
371 }
372
373 fn get_payload_v1<P: DataProvider<HelloWorldV1Marker> + ?Sized>(
374 provider: &P,
375 ) -> Result<DataPayload<HelloWorldV1Marker>, DataError> {
376 provider.load(Default::default())?.take_payload()
377 }
378
379 fn get_payload_alt<P: DataProvider<HelloAltMarker> + ?Sized>(
380 provider: &P,
381 ) -> Result<DataPayload<HelloAltMarker>, DataError> {
382 provider.load(Default::default())?.take_payload()
383 }
384
385 #[test]
386 fn test_warehouse_owned() {
387 let warehouse = get_warehouse(DATA);
388 let hello_data = get_payload_v1(&warehouse).unwrap();
389 assert!(matches!(
390 hello_data.get(),
391 HelloWorldV1 {
392 message: Cow::Borrowed(_),
393 }
394 ));
395 }
396
397 #[test]
398 fn test_warehouse_owned_dyn_erased() {
399 let warehouse = get_warehouse(DATA);
400 let hello_data = get_payload_v1(&warehouse.as_any_provider().as_downcasting()).unwrap();
401 assert!(matches!(
402 hello_data.get(),
403 HelloWorldV1 {
404 message: Cow::Borrowed(_),
405 }
406 ));
407 }
408
409 #[test]
410 fn test_warehouse_owned_dyn_generic() {
411 let warehouse = get_warehouse(DATA);
412 let hello_data =
413 get_payload_v1(&warehouse as &dyn DataProvider<HelloWorldV1Marker>).unwrap();
414 assert!(matches!(
415 hello_data.get(),
416 HelloWorldV1 {
417 message: Cow::Borrowed(_),
418 }
419 ));
420 }
421
422 #[test]
423 fn test_warehouse_owned_dyn_erased_alt() {
424 let warehouse = get_warehouse(DATA);
425 let response = get_payload_alt(&warehouse.as_any_provider().as_downcasting());
426 assert!(matches!(
427 response,
428 Err(DataError {
429 kind: DataErrorKind::MissingDataKey,
430 ..
431 })
432 ));
433 }
434
435 #[test]
436 fn test_provider2() {
437 let warehouse = get_warehouse(DATA);
438 let provider = DataProvider2::from(warehouse);
439 let hello_data = get_payload_v1(&provider).unwrap();
440 assert!(matches!(
441 hello_data.get(),
442 HelloWorldV1 {
443 message: Cow::Borrowed(_),
444 }
445 ));
446 }
447
448 #[test]
449 fn test_provider2_dyn_erased() {
450 let warehouse = get_warehouse(DATA);
451 let provider = DataProvider2::from(warehouse);
452 let hello_data = get_payload_v1(&provider.as_any_provider().as_downcasting()).unwrap();
453 assert!(matches!(
454 hello_data.get(),
455 HelloWorldV1 {
456 message: Cow::Borrowed(_),
457 }
458 ));
459 }
460
461 #[test]
462 fn test_provider2_dyn_erased_alt() {
463 let warehouse = get_warehouse(DATA);
464 let provider = DataProvider2::from(warehouse);
465 let hello_data = get_payload_alt(&provider.as_any_provider().as_downcasting()).unwrap();
466 assert!(matches!(hello_data.get(), HelloAlt { .. }));
467 }
468
469 #[test]
470 fn test_provider2_dyn_generic() {
471 let warehouse = get_warehouse(DATA);
472 let provider = DataProvider2::from(warehouse);
473 let hello_data =
474 get_payload_v1(&provider as &dyn DataProvider<HelloWorldV1Marker>).unwrap();
475 assert!(matches!(
476 hello_data.get(),
477 HelloWorldV1 {
478 message: Cow::Borrowed(_),
479 }
480 ));
481 }
482
483 #[test]
484 fn test_provider2_dyn_generic_alt() {
485 let warehouse = get_warehouse(DATA);
486 let provider = DataProvider2::from(warehouse);
487 let hello_data = get_payload_alt(&provider as &dyn DataProvider<HelloAltMarker>).unwrap();
488 assert!(matches!(hello_data.get(), HelloAlt { .. }));
489 }
490
491 #[test]
492 fn test_mismatched_types() {
493 let warehouse = get_warehouse(DATA);
494 let provider = DataProvider2::from(warehouse);
495 let response: Result<DataResponse<HelloWorldV1Marker>, DataError> = AnyProvider::load_any(
497 &provider.as_any_provider(),
498 HELLO_ALT_KEY,
499 Default::default(),
500 )
501 .unwrap()
502 .downcast();
503 assert!(matches!(
504 response,
505 Err(DataError {
506 kind: DataErrorKind::MismatchedType(_),
507 ..
508 })
509 ));
510 }
511
512 fn check_v1_v2<P>(d: &P)
513 where
514 P: DataProvider<HelloWorldV1Marker> + DataProvider<HelloAltMarker> + ?Sized,
515 {
516 let v1: DataPayload<HelloWorldV1Marker> =
517 d.load(Default::default()).unwrap().take_payload().unwrap();
518 let v2: DataPayload<HelloAltMarker> =
519 d.load(Default::default()).unwrap().take_payload().unwrap();
520 if v1.get().message == v2.get().message {
521 panic!()
522 }
523 }
524
525 #[test]
526 fn test_v1_v2_generic() {
527 let warehouse = get_warehouse(DATA);
528 let provider = DataProvider2::from(warehouse);
529 check_v1_v2(&provider);
530 }
531
532 #[test]
533 fn test_v1_v2_dyn_erased() {
534 let warehouse = get_warehouse(DATA);
535 let provider = DataProvider2::from(warehouse);
536 check_v1_v2(&provider.as_any_provider().as_downcasting());
537 }
538}