Skip to content

Commit

Permalink
canload
Browse files Browse the repository at this point in the history
  • Loading branch information
robertbastian committed Jun 28, 2024
1 parent b021268 commit c7c009c
Show file tree
Hide file tree
Showing 3 changed files with 70 additions and 3 deletions.
36 changes: 34 additions & 2 deletions provider/core/src/buf/serde.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@

use crate::buf::BufferFormat;
use crate::buf::BufferProvider;
use crate::data_provider::DynamicCanLoad;
use crate::prelude::*;
use crate::CanLoad;
use serde::de::Deserialize;
use yoke::trait_hack::YokeTraitHack;
use yoke::Yokeable;
Expand Down Expand Up @@ -149,7 +151,7 @@ impl DataPayload<BufferMarker> {
impl<P, M> DynamicDataProvider<M> for DeserializingBufferProvider<'_, P>
where
M: DynamicDataMarker,
P: BufferProvider + ?Sized,
P: DynamicDataProvider<BufferMarker> + ?Sized,
// Actual bound:
// for<'de> <M::Yokeable as Yokeable<'de>>::Output: serde::de::Deserialize<'de>,
// Necessary workaround bound (see `yoke::trait_hack` docs):
Expand Down Expand Up @@ -184,10 +186,25 @@ where
}
}

impl<P, M> DynamicCanLoad<M> for DeserializingBufferProvider<'_, P>
where
M: DynamicDataMarker,
P: DynamicCanLoad<BufferMarker> + ?Sized,
// Actual bound:
// for<'de> <M::Yokeable as Yokeable<'de>>::Output: serde::de::Deserialize<'de>,
// Necessary workaround bound (see `yoke::trait_hack` docs):
for<'de> YokeTraitHack<<M::Yokeable as Yokeable<'de>>::Output>: Deserialize<'de>,
{
fn can_load_data(&self, marker: DataMarkerInfo, req: DataRequest) -> Result<bool, DataError> {
// Avoids deserialization, deserialization cannot produce `DataErrorKind::MissingLocale`
self.0.can_load_data(marker, req)
}
}

impl<P, M> DataProvider<M> for DeserializingBufferProvider<'_, P>
where
M: DataMarker,
P: BufferProvider + ?Sized,
P: DynamicDataProvider<BufferMarker> + ?Sized,
// Actual bound:
// for<'de> <M::Yokeable as Yokeable<'de>>::Output: Deserialize<'de>,
// Necessary workaround bound (see `yoke::trait_hack` docs):
Expand All @@ -206,6 +223,21 @@ where
}
}

impl<P, M> CanLoad<M> for DeserializingBufferProvider<'_, P>
where
M: DataMarker,
P: DynamicCanLoad<BufferMarker> + ?Sized,
// Actual bound:
// for<'de> <M::Yokeable as Yokeable<'de>>::Output: Deserialize<'de>,
// Necessary workaround bound (see `yoke::trait_hack` docs):
for<'de> YokeTraitHack<<M::Yokeable as Yokeable<'de>>::Output>: Deserialize<'de>,
{
fn can_load(&self, req: DataRequest) -> Result<bool, DataError> {
// Avoids deserialization, deserialization cannot produce `DataErrorKind::MissingLocale`
self.0.can_load_data(M::INFO, req)
}
}

#[cfg(feature = "deserialize_json")]
impl From<serde_json::error::Error> for crate::DataError {
fn from(e: serde_json::error::Error) -> Self {
Expand Down
34 changes: 34 additions & 0 deletions provider/core/src/data_provider.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,23 @@ where
}
}

/// A data provider that can determine whehter it can load a particular data identifier,
/// potentially cheaper than performing the load.
pub trait CanLoad<M: DataMarker>: DataProvider<M> {
/// This method returns false iff [`load`] fails with a [`DataErrorKind::IdentifierNotFound`].
///
/// Other errors are returned as [`load`] would.
///
/// [`load`]: DataProvider::load
fn can_load(&self, req: DataRequest) -> Result<bool, DataError> {
match self.load(req) {
Ok(_) => Ok(true),
Err(e) if e.kind == DataErrorKind::IdentifierNotFound => Ok(false),
Err(e) => Err(e),
}
}
}

/// A data provider that loads data for a specific data type.
///
/// Unlike [`DataProvider`], there may be multiple markers corresponding to the same data type.
Expand All @@ -95,6 +112,23 @@ where
) -> Result<DataResponse<M>, DataError>;
}

/// A dynanmic data provider that can determine whehter it can load a particular data identifier,
/// potentially cheaper than performing the load.
pub trait DynamicCanLoad<M: DynamicDataMarker>: DynamicDataProvider<M> {
/// This method returns false iff [`load_data`] fails with a [`DataErrorKind::IdentifierNotFound`].
///
/// Other errors are returned as [`load_data`] would.
///
/// [`load_data`]: DynamicDataProvider::load_data
fn can_load_data(&self, marker: DataMarkerInfo, req: DataRequest) -> Result<bool, DataError> {
match self.load_data(marker, req) {
Ok(_) => Ok(true),
Err(e) if e.kind == DataErrorKind::IdentifierNotFound => Ok(false),
Err(e) => Err(e),
}
}
}

impl<'a, M, P> DynamicDataProvider<M> for &'a P
where
M: DynamicDataMarker,
Expand Down
3 changes: 2 additions & 1 deletion provider/core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,8 @@ pub mod serde_borrow_de_utils;

mod data_provider;
pub use data_provider::{
BoundDataProvider, DataProvider, DataProviderWithMarker, DynamicDataProvider,
BoundDataProvider, CanLoad, DataProvider, DataProviderWithMarker, DynamicCanLoad,
DynamicDataProvider,
};
#[cfg(feature = "std")]
pub use data_provider::{IterableDataProvider, IterableDynamicDataProvider};
Expand Down

0 comments on commit c7c009c

Please sign in to comment.