1 // This file is part of ICU4X. For terms of use, please see the file 2 // called LICENSE at the top level of the ICU4X source tree 3 // (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ). 4 5 use core::marker::PhantomData; 6 use yoke::Yokeable; 7 8 use crate::prelude::*; 9 10 /// A data provider that loads data for a specific [`DataMarkerInfo`]. 11 pub trait DataProvider<M> 12 where 13 M: DataMarker, 14 { 15 /// Query the provider for data, returning the result. 16 /// 17 /// Returns [`Ok`] if the request successfully loaded data. If data failed to load, returns an 18 /// Error with more information. load(&self, req: DataRequest) -> Result<DataResponse<M>, DataError>19 fn load(&self, req: DataRequest) -> Result<DataResponse<M>, DataError>; 20 } 21 22 impl<M, P> DataProvider<M> for &P 23 where 24 M: DataMarker, 25 P: DataProvider<M> + ?Sized, 26 { 27 #[inline] load(&self, req: DataRequest) -> Result<DataResponse<M>, DataError>28 fn load(&self, req: DataRequest) -> Result<DataResponse<M>, DataError> { 29 (*self).load(req) 30 } 31 } 32 33 #[cfg(feature = "alloc")] 34 impl<M, P> DataProvider<M> for alloc::boxed::Box<P> 35 where 36 M: DataMarker, 37 P: DataProvider<M> + ?Sized, 38 { 39 #[inline] load(&self, req: DataRequest) -> Result<DataResponse<M>, DataError>40 fn load(&self, req: DataRequest) -> Result<DataResponse<M>, DataError> { 41 (**self).load(req) 42 } 43 } 44 45 #[cfg(feature = "alloc")] 46 impl<M, P> DataProvider<M> for alloc::rc::Rc<P> 47 where 48 M: DataMarker, 49 P: DataProvider<M> + ?Sized, 50 { 51 #[inline] load(&self, req: DataRequest) -> Result<DataResponse<M>, DataError>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")] 59 impl<M, P> DataProvider<M> for alloc::sync::Arc<P> 60 where 61 M: DataMarker, 62 P: DataProvider<M> + ?Sized, 63 { 64 #[inline] load(&self, req: DataRequest) -> Result<DataResponse<M>, DataError>65 fn load(&self, req: DataRequest) -> Result<DataResponse<M>, DataError> { 66 (**self).load(req) 67 } 68 } 69 70 /// A data provider that can determine whether it can load a particular data identifier, 71 /// potentially cheaper than actually performing the load. 72 pub trait DryDataProvider<M: DataMarker>: DataProvider<M> { 73 /// This method goes through the motions of [`load`], but only returns the metadata. 74 /// 75 /// If `dry_load` returns an error, [`load`] must return the same error, but 76 /// not vice-versa. Concretely, [`load`] could return deserialization or I/O errors 77 /// that `dry_load` cannot predict. 78 /// 79 /// [`load`]: DataProvider::load dry_load(&self, req: DataRequest) -> Result<DataResponseMetadata, DataError>80 fn dry_load(&self, req: DataRequest) -> Result<DataResponseMetadata, DataError>; 81 } 82 83 impl<M, P> DryDataProvider<M> for &P 84 where 85 M: DataMarker, 86 P: DryDataProvider<M> + ?Sized, 87 { 88 #[inline] dry_load(&self, req: DataRequest) -> Result<DataResponseMetadata, DataError>89 fn dry_load(&self, req: DataRequest) -> Result<DataResponseMetadata, DataError> { 90 (*self).dry_load(req) 91 } 92 } 93 94 #[cfg(feature = "alloc")] 95 impl<M, P> DryDataProvider<M> for alloc::boxed::Box<P> 96 where 97 M: DataMarker, 98 P: DryDataProvider<M> + ?Sized, 99 { 100 #[inline] dry_load(&self, req: DataRequest) -> Result<DataResponseMetadata, DataError>101 fn dry_load(&self, req: DataRequest) -> Result<DataResponseMetadata, DataError> { 102 (**self).dry_load(req) 103 } 104 } 105 106 #[cfg(feature = "alloc")] 107 impl<M, P> DryDataProvider<M> for alloc::rc::Rc<P> 108 where 109 M: DataMarker, 110 P: DryDataProvider<M> + ?Sized, 111 { 112 #[inline] dry_load(&self, req: DataRequest) -> Result<DataResponseMetadata, DataError>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")] 120 impl<M, P> DryDataProvider<M> for alloc::sync::Arc<P> 121 where 122 M: DataMarker, 123 P: DryDataProvider<M> + ?Sized, 124 { 125 #[inline] dry_load(&self, req: DataRequest) -> Result<DataResponseMetadata, DataError>126 fn dry_load(&self, req: DataRequest) -> Result<DataResponseMetadata, DataError> { 127 (**self).dry_load(req) 128 } 129 } 130 131 /// A [`DataProvider`] that can iterate over all supported [`DataIdentifierCow`]s. 132 /// 133 /// The provider is not allowed to return `Ok` for requests that were not returned by `iter_ids`, 134 /// and must not fail with a [`DataErrorKind::IdentifierNotFound`] for requests that were returned. 135 #[cfg(feature = "alloc")] 136 pub trait IterableDataProvider<M: DataMarker>: DataProvider<M> { 137 /// Returns a set of [`DataIdentifierCow`]. iter_ids(&self) -> Result<alloc::collections::BTreeSet<DataIdentifierCow>, DataError>138 fn iter_ids(&self) -> Result<alloc::collections::BTreeSet<DataIdentifierCow>, DataError>; 139 } 140 141 /// A data provider that loads data for a specific data type. 142 /// 143 /// Unlike [`DataProvider`], there may be multiple markers corresponding to the same data type. 144 pub trait DynamicDataProvider<M> 145 where 146 M: DynamicDataMarker, 147 { 148 /// Query the provider for data, returning the result. 149 /// 150 /// Returns [`Ok`] if the request successfully loaded data. If data failed to load, returns an 151 /// Error with more information. load_data( &self, marker: DataMarkerInfo, req: DataRequest, ) -> Result<DataResponse<M>, DataError>152 fn load_data( 153 &self, 154 marker: DataMarkerInfo, 155 req: DataRequest, 156 ) -> Result<DataResponse<M>, DataError>; 157 } 158 159 impl<M, P> DynamicDataProvider<M> for &P 160 where 161 M: DynamicDataMarker, 162 P: DynamicDataProvider<M> + ?Sized, 163 { 164 #[inline] load_data( &self, marker: DataMarkerInfo, req: DataRequest, ) -> Result<DataResponse<M>, DataError>165 fn load_data( 166 &self, 167 marker: DataMarkerInfo, 168 req: DataRequest, 169 ) -> Result<DataResponse<M>, DataError> { 170 (*self).load_data(marker, req) 171 } 172 } 173 174 #[cfg(feature = "alloc")] 175 impl<M, P> DynamicDataProvider<M> for alloc::boxed::Box<P> 176 where 177 M: DynamicDataMarker, 178 P: DynamicDataProvider<M> + ?Sized, 179 { 180 #[inline] load_data( &self, marker: DataMarkerInfo, req: DataRequest, ) -> Result<DataResponse<M>, DataError>181 fn load_data( 182 &self, 183 marker: DataMarkerInfo, 184 req: DataRequest, 185 ) -> Result<DataResponse<M>, DataError> { 186 (**self).load_data(marker, req) 187 } 188 } 189 190 #[cfg(feature = "alloc")] 191 impl<M, P> DynamicDataProvider<M> for alloc::rc::Rc<P> 192 where 193 M: DynamicDataMarker, 194 P: DynamicDataProvider<M> + ?Sized, 195 { 196 #[inline] load_data( &self, marker: DataMarkerInfo, req: DataRequest, ) -> Result<DataResponse<M>, DataError>197 fn load_data( 198 &self, 199 marker: DataMarkerInfo, 200 req: DataRequest, 201 ) -> Result<DataResponse<M>, DataError> { 202 (**self).load_data(marker, req) 203 } 204 } 205 206 #[cfg(target_has_atomic = "ptr")] 207 #[cfg(feature = "alloc")] 208 impl<M, P> DynamicDataProvider<M> for alloc::sync::Arc<P> 209 where 210 M: DynamicDataMarker, 211 P: DynamicDataProvider<M> + ?Sized, 212 { 213 #[inline] load_data( &self, marker: DataMarkerInfo, req: DataRequest, ) -> Result<DataResponse<M>, DataError>214 fn load_data( 215 &self, 216 marker: DataMarkerInfo, 217 req: DataRequest, 218 ) -> Result<DataResponse<M>, DataError> { 219 (**self).load_data(marker, req) 220 } 221 } 222 223 /// A dynanmic data provider that can determine whether it can load a particular data identifier, 224 /// potentially cheaper than actually performing the load. 225 pub trait DynamicDryDataProvider<M: DynamicDataMarker>: DynamicDataProvider<M> { 226 /// This method goes through the motions of [`load_data`], but only returns the metadata. 227 /// 228 /// If `dry_load_data` returns an error, [`load_data`] must return the same error, but 229 /// not vice-versa. Concretely, [`load_data`] could return deserialization or I/O errors 230 /// that `dry_load_data` cannot predict. 231 /// 232 /// [`load_data`]: DynamicDataProvider::load_data dry_load_data( &self, marker: DataMarkerInfo, req: DataRequest, ) -> Result<DataResponseMetadata, DataError>233 fn dry_load_data( 234 &self, 235 marker: DataMarkerInfo, 236 req: DataRequest, 237 ) -> Result<DataResponseMetadata, DataError>; 238 } 239 240 impl<M, P> DynamicDryDataProvider<M> for &P 241 where 242 M: DynamicDataMarker, 243 P: DynamicDryDataProvider<M> + ?Sized, 244 { 245 #[inline] dry_load_data( &self, marker: DataMarkerInfo, req: DataRequest, ) -> Result<DataResponseMetadata, DataError>246 fn dry_load_data( 247 &self, 248 marker: DataMarkerInfo, 249 req: DataRequest, 250 ) -> Result<DataResponseMetadata, DataError> { 251 (*self).dry_load_data(marker, req) 252 } 253 } 254 255 #[cfg(feature = "alloc")] 256 impl<M, P> DynamicDryDataProvider<M> for alloc::boxed::Box<P> 257 where 258 M: DynamicDataMarker, 259 P: DynamicDryDataProvider<M> + ?Sized, 260 { 261 #[inline] dry_load_data( &self, marker: DataMarkerInfo, req: DataRequest, ) -> Result<DataResponseMetadata, DataError>262 fn dry_load_data( 263 &self, 264 marker: DataMarkerInfo, 265 req: DataRequest, 266 ) -> Result<DataResponseMetadata, DataError> { 267 (**self).dry_load_data(marker, req) 268 } 269 } 270 271 #[cfg(feature = "alloc")] 272 impl<M, P> DynamicDryDataProvider<M> for alloc::rc::Rc<P> 273 where 274 M: DynamicDataMarker, 275 P: DynamicDryDataProvider<M> + ?Sized, 276 { 277 #[inline] dry_load_data( &self, marker: DataMarkerInfo, req: DataRequest, ) -> Result<DataResponseMetadata, DataError>278 fn dry_load_data( 279 &self, 280 marker: DataMarkerInfo, 281 req: DataRequest, 282 ) -> Result<DataResponseMetadata, DataError> { 283 (**self).dry_load_data(marker, req) 284 } 285 } 286 287 #[cfg(target_has_atomic = "ptr")] 288 #[cfg(feature = "alloc")] 289 impl<M, P> DynamicDryDataProvider<M> for alloc::sync::Arc<P> 290 where 291 M: DynamicDataMarker, 292 P: DynamicDryDataProvider<M> + ?Sized, 293 { 294 #[inline] dry_load_data( &self, marker: DataMarkerInfo, req: DataRequest, ) -> Result<DataResponseMetadata, DataError>295 fn dry_load_data( 296 &self, 297 marker: DataMarkerInfo, 298 req: DataRequest, 299 ) -> Result<DataResponseMetadata, DataError> { 300 (**self).dry_load_data(marker, req) 301 } 302 } 303 304 /// A [`DynamicDataProvider`] that can iterate over all supported [`DataIdentifierCow`]s for a certain marker. 305 /// 306 /// The provider is not allowed to return `Ok` for requests that were not returned by `iter_ids`, 307 /// and must not fail with a [`DataErrorKind::IdentifierNotFound`] for requests that were returned. 308 #[cfg(feature = "alloc")] 309 pub trait IterableDynamicDataProvider<M: DynamicDataMarker>: DynamicDataProvider<M> { 310 /// Given a [`DataMarkerInfo`], returns a set of [`DataIdentifierCow`]. iter_ids_for_marker( &self, marker: DataMarkerInfo, ) -> Result<alloc::collections::BTreeSet<DataIdentifierCow>, DataError>311 fn iter_ids_for_marker( 312 &self, 313 marker: DataMarkerInfo, 314 ) -> Result<alloc::collections::BTreeSet<DataIdentifierCow>, DataError>; 315 } 316 317 #[cfg(feature = "alloc")] 318 impl<M, P> IterableDynamicDataProvider<M> for alloc::boxed::Box<P> 319 where 320 M: DynamicDataMarker, 321 P: IterableDynamicDataProvider<M> + ?Sized, 322 { iter_ids_for_marker( &self, marker: DataMarkerInfo, ) -> Result<alloc::collections::BTreeSet<DataIdentifierCow>, DataError>323 fn iter_ids_for_marker( 324 &self, 325 marker: DataMarkerInfo, 326 ) -> Result<alloc::collections::BTreeSet<DataIdentifierCow>, DataError> { 327 (**self).iter_ids_for_marker(marker) 328 } 329 } 330 331 /// A data provider that loads data for a specific data type. 332 /// 333 /// Unlike [`DataProvider`], the provider is bound to a specific marker ahead of time. 334 /// 335 /// This crate provides [`DataProviderWithMarker`] which implements this trait on a single provider 336 /// with a single marker. However, this trait can also be implemented on providers that fork between 337 /// multiple markers that all return the same data type. For example, it can abstract over many 338 /// calendar systems in the datetime formatter. 339 pub trait BoundDataProvider<M> 340 where 341 M: DynamicDataMarker, 342 { 343 /// Query the provider for data, returning the result. 344 /// 345 /// Returns [`Ok`] if the request successfully loaded data. If data failed to load, returns an 346 /// Error with more information. load_bound(&self, req: DataRequest) -> Result<DataResponse<M>, DataError>347 fn load_bound(&self, req: DataRequest) -> Result<DataResponse<M>, DataError>; 348 /// Returns the [`DataMarkerInfo`] that this provider uses for loading data. bound_marker(&self) -> DataMarkerInfo349 fn bound_marker(&self) -> DataMarkerInfo; 350 } 351 352 impl<M, P> BoundDataProvider<M> for &P 353 where 354 M: DynamicDataMarker, 355 P: BoundDataProvider<M> + ?Sized, 356 { 357 #[inline] load_bound(&self, req: DataRequest) -> Result<DataResponse<M>, DataError>358 fn load_bound(&self, req: DataRequest) -> Result<DataResponse<M>, DataError> { 359 (*self).load_bound(req) 360 } 361 #[inline] bound_marker(&self) -> DataMarkerInfo362 fn bound_marker(&self) -> DataMarkerInfo { 363 (*self).bound_marker() 364 } 365 } 366 367 #[cfg(feature = "alloc")] 368 impl<M, P> BoundDataProvider<M> for alloc::boxed::Box<P> 369 where 370 M: DynamicDataMarker, 371 P: BoundDataProvider<M> + ?Sized, 372 { 373 #[inline] load_bound(&self, req: DataRequest) -> Result<DataResponse<M>, DataError>374 fn load_bound(&self, req: DataRequest) -> Result<DataResponse<M>, DataError> { 375 (**self).load_bound(req) 376 } 377 #[inline] bound_marker(&self) -> DataMarkerInfo378 fn bound_marker(&self) -> DataMarkerInfo { 379 (**self).bound_marker() 380 } 381 } 382 383 #[cfg(feature = "alloc")] 384 impl<M, P> BoundDataProvider<M> for alloc::rc::Rc<P> 385 where 386 M: DynamicDataMarker, 387 P: BoundDataProvider<M> + ?Sized, 388 { 389 #[inline] load_bound(&self, req: DataRequest) -> Result<DataResponse<M>, DataError>390 fn load_bound(&self, req: DataRequest) -> Result<DataResponse<M>, DataError> { 391 (**self).load_bound(req) 392 } 393 #[inline] bound_marker(&self) -> DataMarkerInfo394 fn bound_marker(&self) -> DataMarkerInfo { 395 (**self).bound_marker() 396 } 397 } 398 399 #[cfg(target_has_atomic = "ptr")] 400 #[cfg(feature = "alloc")] 401 impl<M, P> BoundDataProvider<M> for alloc::sync::Arc<P> 402 where 403 M: DynamicDataMarker, 404 P: BoundDataProvider<M> + ?Sized, 405 { 406 #[inline] load_bound(&self, req: DataRequest) -> Result<DataResponse<M>, DataError>407 fn load_bound(&self, req: DataRequest) -> Result<DataResponse<M>, DataError> { 408 (**self).load_bound(req) 409 } 410 #[inline] bound_marker(&self) -> DataMarkerInfo411 fn bound_marker(&self) -> DataMarkerInfo { 412 (**self).bound_marker() 413 } 414 } 415 416 /// A [`DataProvider`] associated with a specific marker. 417 /// 418 /// Implements [`BoundDataProvider`]. 419 #[derive(Debug)] 420 pub struct DataProviderWithMarker<M, P> { 421 inner: P, 422 _marker: PhantomData<M>, 423 } 424 425 impl<M, P> DataProviderWithMarker<M, P> 426 where 427 M: DataMarker, 428 P: DataProvider<M>, 429 { 430 /// Creates a [`DataProviderWithMarker`] from a [`DataProvider`] with a [`DataMarker`]. new(inner: P) -> Self431 pub const fn new(inner: P) -> Self { 432 Self { 433 inner, 434 _marker: PhantomData, 435 } 436 } 437 } 438 439 impl<M, M0, Y, P> BoundDataProvider<M0> for DataProviderWithMarker<M, P> 440 where 441 M: DataMarker<DataStruct = Y>, 442 M0: DynamicDataMarker<DataStruct = Y>, 443 Y: for<'a> Yokeable<'a>, 444 P: DataProvider<M>, 445 { 446 #[inline] load_bound(&self, req: DataRequest) -> Result<DataResponse<M0>, DataError>447 fn load_bound(&self, req: DataRequest) -> Result<DataResponse<M0>, DataError> { 448 self.inner.load(req).map(DataResponse::cast) 449 } 450 #[inline] bound_marker(&self) -> DataMarkerInfo451 fn bound_marker(&self) -> DataMarkerInfo { 452 M::INFO 453 } 454 } 455 456 #[cfg(test)] 457 mod test { 458 459 use super::*; 460 use crate::hello_world::*; 461 use alloc::borrow::Cow; 462 use alloc::string::String; 463 use core::fmt::Debug; 464 use serde::{Deserialize, Serialize}; 465 466 // This tests DataProvider borrow semantics with a dummy data provider based on a 467 // JSON string. It also exercises most of the data provider code paths. 468 469 /// A data struct serialization-compatible with HelloWorld used for testing mismatched types 470 #[derive(Serialize, Deserialize, Debug, Clone, Default, PartialEq, yoke::Yokeable)] 471 pub struct HelloAlt { 472 message: String, 473 } 474 475 data_marker!(HelloAltMarkerV1, HelloAlt); 476 477 #[derive(Deserialize, Debug, Clone, Default, PartialEq)] 478 struct HelloCombined<'data> { 479 #[serde(borrow)] 480 pub hello_v1: HelloWorld<'data>, 481 pub hello_alt: HelloAlt, 482 } 483 484 /// A DataProvider that owns its data, returning an Rc-variant DataPayload. 485 /// Supports only key::HELLO_WORLD_V1. Uses `impl_dynamic_data_provider!()`. 486 #[derive(Debug)] 487 struct DataWarehouse { 488 hello_v1: HelloWorld<'static>, 489 hello_alt: HelloAlt, 490 } 491 492 impl DataProvider<HelloWorldV1> for DataWarehouse { load(&self, _: DataRequest) -> Result<DataResponse<HelloWorldV1>, DataError>493 fn load(&self, _: DataRequest) -> Result<DataResponse<HelloWorldV1>, DataError> { 494 Ok(DataResponse { 495 metadata: DataResponseMetadata::default(), 496 payload: DataPayload::from_owned(self.hello_v1.clone()), 497 }) 498 } 499 } 500 501 /// A DataProvider that supports both key::HELLO_WORLD_V1 and HELLO_ALT. 502 #[derive(Debug)] 503 struct DataProvider2 { 504 data: DataWarehouse, 505 } 506 507 impl From<DataWarehouse> for DataProvider2 { from(warehouse: DataWarehouse) -> Self508 fn from(warehouse: DataWarehouse) -> Self { 509 DataProvider2 { data: warehouse } 510 } 511 } 512 513 impl DataProvider<HelloWorldV1> for DataProvider2 { load(&self, _: DataRequest) -> Result<DataResponse<HelloWorldV1>, DataError>514 fn load(&self, _: DataRequest) -> Result<DataResponse<HelloWorldV1>, DataError> { 515 Ok(DataResponse { 516 metadata: DataResponseMetadata::default(), 517 payload: DataPayload::from_owned(self.data.hello_v1.clone()), 518 }) 519 } 520 } 521 522 impl DataProvider<HelloAltMarkerV1> for DataProvider2 { load(&self, _: DataRequest) -> Result<DataResponse<HelloAltMarkerV1>, DataError>523 fn load(&self, _: DataRequest) -> Result<DataResponse<HelloAltMarkerV1>, DataError> { 524 Ok(DataResponse { 525 metadata: DataResponseMetadata::default(), 526 payload: DataPayload::from_owned(self.data.hello_alt.clone()), 527 }) 528 } 529 } 530 531 const DATA: &str = r#"{ 532 "hello_v1": { 533 "message": "Hello " 534 }, 535 "hello_alt": { 536 "message": "Hello Alt" 537 } 538 }"#; 539 get_warehouse(data: &'static str) -> DataWarehouse540 fn get_warehouse(data: &'static str) -> DataWarehouse { 541 let data: HelloCombined = serde_json::from_str(data).expect("Well-formed data"); 542 DataWarehouse { 543 hello_v1: data.hello_v1, 544 hello_alt: data.hello_alt, 545 } 546 } 547 get_payload_v1<P: DataProvider<HelloWorldV1> + ?Sized>( provider: &P, ) -> Result<DataPayload<HelloWorldV1>, DataError>548 fn get_payload_v1<P: DataProvider<HelloWorldV1> + ?Sized>( 549 provider: &P, 550 ) -> Result<DataPayload<HelloWorldV1>, DataError> { 551 provider.load(Default::default()).map(|r| r.payload) 552 } 553 get_payload_alt<P: DataProvider<HelloAltMarkerV1> + ?Sized>( provider: &P, ) -> Result<DataPayload<HelloAltMarkerV1>, DataError>554 fn get_payload_alt<P: DataProvider<HelloAltMarkerV1> + ?Sized>( 555 provider: &P, 556 ) -> Result<DataPayload<HelloAltMarkerV1>, DataError> { 557 provider.load(Default::default()).map(|r| r.payload) 558 } 559 560 #[test] test_warehouse_owned()561 fn test_warehouse_owned() { 562 let warehouse = get_warehouse(DATA); 563 let hello_data = get_payload_v1(&warehouse).unwrap(); 564 assert!(matches!( 565 hello_data.get(), 566 HelloWorld { 567 message: Cow::Borrowed(_), 568 } 569 )); 570 } 571 572 #[test] test_warehouse_owned_dyn_generic()573 fn test_warehouse_owned_dyn_generic() { 574 let warehouse = get_warehouse(DATA); 575 let hello_data = get_payload_v1(&warehouse as &dyn DataProvider<HelloWorldV1>).unwrap(); 576 assert!(matches!( 577 hello_data.get(), 578 HelloWorld { 579 message: Cow::Borrowed(_), 580 } 581 )); 582 } 583 584 #[test] test_provider2()585 fn test_provider2() { 586 let warehouse = get_warehouse(DATA); 587 let provider = DataProvider2::from(warehouse); 588 let hello_data = get_payload_v1(&provider).unwrap(); 589 assert!(matches!( 590 hello_data.get(), 591 HelloWorld { 592 message: Cow::Borrowed(_), 593 } 594 )); 595 } 596 597 #[test] test_provider2_dyn_generic()598 fn test_provider2_dyn_generic() { 599 let warehouse = get_warehouse(DATA); 600 let provider = DataProvider2::from(warehouse); 601 let hello_data = get_payload_v1(&provider as &dyn DataProvider<HelloWorldV1>).unwrap(); 602 assert!(matches!( 603 hello_data.get(), 604 HelloWorld { 605 message: Cow::Borrowed(_), 606 } 607 )); 608 } 609 610 #[test] test_provider2_dyn_generic_alt()611 fn test_provider2_dyn_generic_alt() { 612 let warehouse = get_warehouse(DATA); 613 let provider = DataProvider2::from(warehouse); 614 let hello_data = get_payload_alt(&provider as &dyn DataProvider<HelloAltMarkerV1>).unwrap(); 615 assert!(matches!(hello_data.get(), HelloAlt { .. })); 616 } 617 check_v1_v2<P>(d: &P) where P: DataProvider<HelloWorldV1> + DataProvider<HelloAltMarkerV1> + ?Sized,618 fn check_v1_v2<P>(d: &P) 619 where 620 P: DataProvider<HelloWorldV1> + DataProvider<HelloAltMarkerV1> + ?Sized, 621 { 622 let v1: DataPayload<HelloWorldV1> = d.load(Default::default()).unwrap().payload; 623 let v2: DataPayload<HelloAltMarkerV1> = d.load(Default::default()).unwrap().payload; 624 if v1.get().message == v2.get().message { 625 panic!() 626 } 627 } 628 629 #[test] test_v1_v2_generic()630 fn test_v1_v2_generic() { 631 let warehouse = get_warehouse(DATA); 632 let provider = DataProvider2::from(warehouse); 633 check_v1_v2(&provider); 634 } 635 } 636