1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
// 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 ).

//! Types having to do with the exporting of data.

use crate::error::Error;
use crate::iter::IterableDataProvider;
use crate::prelude::*;
use std::fmt::Debug;

/// An object capable of serializing data payloads to be read by a [`DataProvider`].
///
/// A [`DataProvider`] by itself is "read-only"; this trait enables it to be "read-write".
pub trait DataExporter<'s, T>
where
    T: 's + ToOwned + ?Sized,
    <T as ToOwned>::Owned: Debug,
{
    /// Save a `payload` corresponding to the given data request (resource path).
    fn put_payload(
        &mut self,
        req: &DataRequest,
        payload: &T,
    ) -> Result<(), Box<dyn std::error::Error>>;

    /// Whether to load and dump data for the given entry. This function enables the
    /// [`DataExporter`] to filter out certain data entries.
    fn include_resource_options(&self, resc_options: &ResourceOptions) -> bool;

    /// Auto-implemented function that loads data from an [`IterableDataProvider`] and dumps it
    /// into this [`DataExporter`].
    fn put_key_from_provider<'d>(
        &mut self,
        resc_key: &ResourceKey,
        provider: &impl IterableDataProvider<'d, T>,
    ) -> Result<(), Error>
    where
        's: 'd,
    {
        use std::borrow::Borrow;
        for resc_options in provider.supported_options_for_key(resc_key)? {
            if !self.include_resource_options(&resc_options) {
                continue;
            }
            let req = DataRequest {
                resource_path: ResourcePath {
                    key: *resc_key,
                    options: resc_options,
                },
            };
            let payload = provider.load_payload(&req)?.payload.take()?;
            self.put_payload(&req, payload.borrow())?;
        }
        Ok(())
    }
}