Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Firefox/third_party/rust/icu_provider/src/export/   (Firefox Browser Version 153.0.1©)  Datei vom 27.6.2026 mit Größe 10 kB image not shown  

Quelle  payload.rs

  Sprache: Rust
 

// 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 core::any::Any;

use crate::prelude::*;
use crate::ule::MaybeEncodeAsVarULE;
use crate::{dynutil::UpcastDataPayload, ule::MaybeAsVarULE};
use alloc::sync::Arc;
use databake::{Bake, BakeSize, CrateEnv, TokenStream};
use yoke::*;
use zerovec::VarZeroVec;

#[cfg(doc)]
use zerovec::ule::VarULE;

trait ExportableDataPayload {
    fn bake_yoke(&self, ctx: &CrateEnv) -> TokenStream;
    fn bake_size(&self) -> usize;
    fn serialize_yoke(
        &self,
        serializer: &mut dyn erased_serde::Serializer,
    ) -> Result<(), DataError>;
    fn maybe_bake_varule_encoded(
        &self,
        rest: &[&DataPayload<ExportMarker>],
        ctx: &CrateEnv,
    ) -> Option<TokenStream>;
    fn as_any(&self) -> &dyn Any;
    fn eq_dyn(&self, other: &dyn ExportableDataPayload) -> bool;
}

impl<M: DynamicDataMarker> ExportableDataPayload for DataPayload<M>
where
    for<'a> <M::DataStruct as Yokeable<'a>>::Output:
        Bake + BakeSize + serde::Serialize + MaybeEncodeAsVarULE + PartialEq,
{
    fn bake_yoke(&self, ctx: &CrateEnv) -> TokenStream {
        self.get().bake(ctx)
    }

    fn bake_size(&self) -> usize {
        core::mem::size_of::<<M::DataStruct as Yokeable>::Output>() + self.get().borrows_size()
    }

    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(())
    }

    fn maybe_bake_varule_encoded(
        &self,
        rest: &[&DataPayload<ExportMarker>],
        ctx: &CrateEnv,
    ) -> Option<TokenStream> {
        let first_varule = self.get().maybe_encode_as_varule()?;
        let recovered_vec: Vec<
            &<<M::DataStruct as Yokeable<'_>>::Output as MaybeAsVarULE>::EncodedStruct,
        > = core::iter::once(first_varule)
            .chain(rest.iter().map(|v| {
                #[expect(clippy::expect_used)] // exporter code
                v.get()
                    .payload
                    .as_any()
                    .downcast_ref::<Self>()
                    .expect("payloads expected to be same type")
                    .get()
                    .maybe_encode_as_varule()
                    .expect("MaybeEncodeAsVarULE impl should be symmetric")
            }))
            .collect();
        let vzv: VarZeroVec<
            <<M::DataStruct as Yokeable<'_>>::Output as MaybeAsVarULE>::EncodedStruct,
        > = VarZeroVec::from(&recovered_vec);
        let vzs = vzv.as_slice();
        Some(vzs.bake(ctx))
    }

    fn as_any(&self) -> &dyn Any {
        self
    }

    fn eq_dyn(&self, other: &dyn ExportableDataPayload) -> bool {
        match other.as_any().downcast_ref::<Self>() {
            Some(downcasted) => (*self).eq(downcasted),
            None => {
                debug_assert!(
                    false,
                    "cannot compare ExportableDataPayloads of different types: self is {:?} but other is {:?}",
                    self.type_id(),
                    other.as_any().type_id(),
                );
                false
            }
        }
    }
}

#[derive(yoke::Yokeable, Clone)]
#[allow(missing_docs)]
pub struct ExportBox {
    payload: Arc<dyn ExportableDataPayload + Sync + Send>,
}

impl PartialEq for ExportBox {
    fn eq(&self, other: &Self) -> bool {
        self.payload.eq_dyn(&*other.payload)
    }
}

impl Eq for ExportBox {}

impl core::fmt::Debug for ExportBox {
    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
        f.debug_struct("ExportBox")
            .field("payload", &"<payload>")
            .finish()
    }
}

impl<M> UpcastDataPayload<M> for ExportMarker
where
    M: DynamicDataMarker,
    M::DataStruct: Sync + Send,
    for<'a> <M::DataStruct as Yokeable<'a>>::Output:
        Bake + BakeSize + serde::Serialize + MaybeEncodeAsVarULE + PartialEq,
{
    fn upcast(other: DataPayload<M>) -> DataPayload<ExportMarker> {
        DataPayload::from_owned(ExportBox {
            payload: Arc::new(other),
        })
    }
}

impl DataPayload<ExportMarker> {
    /// Serializes this [`DataPayload`] into a serializer using Serde.
    ///
    /// # Examples
    ///
    /// ```
    /// use icu_provider::dynutil::UpcastDataPayload;
    /// use icu_provider::export::*;
    /// use icu_provider::hello_world::HelloWorldV1;
    /// use icu_provider::prelude::*;
    ///
    /// // Create an example DataPayload
    /// let payload: DataPayload<HelloWorldV1> = 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!(r#"{"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::dynutil::UpcastDataPayload;
    /// use icu_provider::export::*;
    /// use icu_provider::hello_world::HelloWorldV1;
    /// use icu_provider::prelude::*;
    /// # use databake::quote;
    /// # use std::collections::BTreeSet;
    ///
    /// // Create an example DataPayload
    /// let payload: DataPayload<HelloWorldV1> = 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::HelloWorld {
    ///             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, ctx: &CrateEnv) -> TokenStream {
        self.get().payload.bake_yoke(ctx)
    }

    /// If this payload's struct can be dereferenced as a [`VarULE`],
    /// returns a [`TokenStream`] of the slice encoded as a [`VarZeroVec`].
    pub fn tokenize_encoded_seq(structs: &[&Self], ctx: &CrateEnv) -> Option<TokenStream> {
        let (first, rest) = structs.split_first()?;
        first.get().payload.maybe_bake_varule_encoded(rest, ctx)
    }

    /// Returns the data size using postcard encoding
    pub fn postcard_size(&self) -> usize {
        use postcard::ser_flavors::{Flavor, Size};
        let mut serializer = postcard::Serializer {
            output: Size::default(),
        };
        let _infallible = self
            .get()
            .payload
            .serialize_yoke(&mut <dyn erased_serde::Serializer>::erase(&n style='color:red'>mut serializer));

        serializer.output.finalize().unwrap_or_default()
    }

    /// Returns an estimate of the baked size, made up of the size of the struct itself,
    /// as well as the sizes of all its static borrows.
    ///
    /// As static borrows are deduplicated by the linker, this is often overcounting.
    pub fn baked_size(&self) -> usize {
        self.get().payload.bake_size()
    }
}

impl core::hash::Hash for DataPayload<ExportMarker> {
    fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
        self.hash_and_postcard_size(state);
    }
}

impl DataPayload<ExportMarker> {
    /// Calculates a payload hash and the postcard size
    pub fn hash_and_postcard_size<H: core::hash::Hasher>(&self, state: &mut H) -> usize {
        use postcard::ser_flavors::Flavor;

        struct HashFlavor<'a, H>(&'mut H, usize);
        impl<H: core::hash::Hasher> Flavor for HashFlavor<'_, H> {
            type Output = usize;

            fn try_push(&mut self, data: u8) -> postcard::Result<()> {
                self.0.write_u8(data);
                self.1 += 1;
                Ok(())
            }

            fn finalize(self) -> postcard::Result<Self::Output> {
                Ok(self.1)
            }
        }

        let mut serializer = postcard::Serializer {
            output: HashFlavor(state, 0),
        };

        let _infallible = self
            .get()
            .payload
            .serialize_yoke(&mut <dyn erased_serde::Serializer>::erase(&n style='color:red'>mut serializer));

        serializer.output.1
    }
}

/// Marker type for [`ExportBox`].
#[allow(clippy::exhaustive_structs)] // marker type
#[derive(Debug)]
pub struct ExportMarker {}

impl DynamicDataMarker for ExportMarker {
    type DataStruct = ExportBox;
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::hello_world::*;

    #[test]
    fn test_compare_with_dyn() {
        let payload1: DataPayload<HelloWorldV1> = DataPayload::from_owned(HelloWorld {
            message: "abc".into(),
        });
        let payload2: DataPayload<HelloWorldV1> = DataPayload::from_owned(HelloWorld {
            message: "abc".into(),
        });
        let payload3: DataPayload<HelloWorldV1> = DataPayload::from_owned(HelloWorld {
            message: "def".into(),
        });

        assert!(payload1.eq_dyn(&payload2));
        assert!(payload2.eq_dyn(&payload1));

        assert!(!payload1.eq_dyn(&payload3));
        assert!(!payload3.eq_dyn(&payload1));
    }

    #[test]
    fn test_export_marker_partial_eq() {
        let payload1: DataPayload<ExportMarker> =
            UpcastDataPayload::upcast(DataPayload::<HelloWorldV1>::from_owned(HelloWorld {
                message: "abc".into(),
            }));
        let payload2: DataPayload<ExportMarker> =
            UpcastDataPayload::upcast(DataPayload::<HelloWorldV1>::from_owned(HelloWorld {
                message: "abc".into(),
            }));
        let payload3: DataPayload<ExportMarker> =
            UpcastDataPayload::upcast(DataPayload::<HelloWorldV1>::from_owned(HelloWorld {
                message: "def".into(),
            }));

        assert_eq!(payload1, payload2);
        assert_eq!(payload2, payload1);
        assert_ne!(payload1, payload3);
        assert_ne!(payload3, payload1);
    }
}

Messung V0.5 in Prozent
C=92 H=99 G=95

¤ Dauer der Verarbeitung: 0.18 Sekunden  (vorverarbeitet am  2026-08-26) ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover

NIST Cobol Testsuite

Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.