summaryrefslogtreecommitdiffstats
path: root/vendor/icu_provider/src/datagen/payload.rs
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/icu_provider/src/datagen/payload.rs')
-rw-r--r--vendor/icu_provider/src/datagen/payload.rs137
1 files changed, 137 insertions, 0 deletions
diff --git a/vendor/icu_provider/src/datagen/payload.rs b/vendor/icu_provider/src/datagen/payload.rs
new file mode 100644
index 000000000..b6ea8049f
--- /dev/null
+++ b/vendor/icu_provider/src/datagen/payload.rs
@@ -0,0 +1,137 @@
+// This file is part of ICU4X. For terms of use, please see the file
+// called LICENSE at the top level of the ICU4X source tree
+// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ).
+
+use crate::dynutil::UpcastDataPayload;
+use crate::prelude::*;
+use crate::yoke::*;
+use alloc::boxed::Box;
+use databake::{Bake, CrateEnv, TokenStream};
+
+trait ExportableYoke {
+ fn bake_yoke(&self, env: &CrateEnv) -> TokenStream;
+ fn serialize_yoke(
+ &self,
+ serializer: &mut dyn erased_serde::Serializer,
+ ) -> Result<(), DataError>;
+}
+
+impl<Y, C> ExportableYoke for Yoke<Y, C>
+where
+ Y: for<'a> Yokeable<'a>,
+ for<'a> <Y as Yokeable<'a>>::Output: Bake + serde::Serialize,
+{
+ fn bake_yoke(&self, ctx: &CrateEnv) -> TokenStream {
+ self.get().bake(ctx)
+ }
+
+ fn serialize_yoke(
+ &self,
+ serializer: &mut dyn erased_serde::Serializer,
+ ) -> Result<(), DataError> {
+ use erased_serde::Serialize;
+ self.get()
+ .erased_serialize(serializer)
+ .map_err(|e| DataError::custom("Serde export").with_display_context(&e))?;
+ Ok(())
+ }
+}
+
+#[doc(hidden)] // exposed for make_exportable_provider
+#[derive(yoke::Yokeable)]
+pub struct ExportBox {
+ payload: Box<dyn ExportableYoke + Sync>,
+}
+
+impl<M> UpcastDataPayload<M> for ExportMarker
+where
+ M: DataMarker,
+ M::Yokeable: Sync,
+ for<'a> <M::Yokeable as Yokeable<'a>>::Output: Bake + serde::Serialize,
+{
+ fn upcast(other: DataPayload<M>) -> DataPayload<ExportMarker> {
+ DataPayload::from_owned(ExportBox {
+ payload: Box::new(other.yoke),
+ })
+ }
+}
+
+impl DataPayload<ExportMarker> {
+ /// Serializes this [`DataPayload`] into a serializer using Serde.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use icu_provider::datagen::*;
+ /// use icu_provider::dynutil::UpcastDataPayload;
+ /// use icu_provider::hello_world::HelloWorldV1Marker;
+ /// use icu_provider::prelude::*;
+ ///
+ /// // Create an example DataPayload
+ /// let payload: DataPayload<HelloWorldV1Marker> = Default::default();
+ /// let export: DataPayload<ExportMarker> = UpcastDataPayload::upcast(payload);
+ ///
+ /// // Serialize the payload to a JSON string
+ /// let mut buffer: Vec<u8> = vec![];
+ /// export
+ /// .serialize(&mut serde_json::Serializer::new(&mut buffer))
+ /// .expect("Serialization should succeed");
+ /// assert_eq!("{\"message\":\"(und) Hello World\"}".as_bytes(), buffer);
+ /// ```
+ pub fn serialize<S>(&self, serializer: S) -> Result<(), DataError>
+ where
+ S: serde::Serializer,
+ S::Ok: 'static, // erased_serde requirement, cannot return values in `Ok`
+ {
+ self.get()
+ .payload
+ .serialize_yoke(&mut <dyn erased_serde::Serializer>::erase(serializer))
+ }
+
+ /// Serializes this [`DataPayload`]'s value into a [`TokenStream`]
+ /// using its [`Bake`] implementations.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use icu_provider::datagen::*;
+ /// use icu_provider::dynutil::UpcastDataPayload;
+ /// use icu_provider::hello_world::HelloWorldV1Marker;
+ /// use icu_provider::prelude::*;
+ /// # use databake::quote;
+ /// # use std::collections::BTreeSet;
+ ///
+ /// // Create an example DataPayload
+ /// let payload: DataPayload<HelloWorldV1Marker> = Default::default();
+ /// let export: DataPayload<ExportMarker> = UpcastDataPayload::upcast(payload);
+ ///
+ /// let env = databake::CrateEnv::default();
+ /// let tokens = export.tokenize(&env);
+ /// assert_eq!(
+ /// quote! {
+ /// ::icu_provider::hello_world::HelloWorldV1 {
+ /// message: alloc::borrow::Cow::Borrowed("(und) Hello World"),
+ /// }
+ /// }
+ /// .to_string(),
+ /// tokens.to_string()
+ /// );
+ /// assert_eq!(
+ /// env.into_iter().collect::<BTreeSet<_>>(),
+ /// ["icu_provider", "alloc"]
+ /// .into_iter()
+ /// .collect::<BTreeSet<_>>()
+ /// );
+ /// ```
+ pub fn tokenize(&self, env: &CrateEnv) -> TokenStream {
+ self.get().payload.bake_yoke(env)
+ }
+}
+
+/// Marker type for [`ExportBox`].
+#[allow(clippy::exhaustive_structs)] // marker type
+pub struct ExportMarker {}
+
+impl DataMarker for ExportMarker {
+ type Yokeable = ExportBox;
+}