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
use crate::AnySpecDataType;
/// Runtime logic of how to look up values for each field in this struct.
///
/// This trait is automatically implemented by `#[derive(Params)]` on an
/// `Item::Params`, as well as in the `peace_params` crate for standard
/// library types.
pub trait AnySpecRt {
/// Whether this `Spec` is usable to resolve values.
///
/// This is only `false` for `*Spec::MappingFn`s that have been
/// deserialized, as mapping functions cannot be deserialized back into
/// logic without embedding a script interpreter or compiler.
fn is_usable(&self) -> bool;
/// Deep merges the provided `AnySpecRt` with `self`, where `self` takes
/// priority, except for `Self::Stored`.
///
/// This means where `self` is `Self::Value`, `Self::InMemory`,
/// `Self::MappingFn`, and `Self::FieldWise`, these would take priority over
/// any stored item variants.
///
/// For `Self::FieldWise`, a recursive merge would happen per field
/// `ValueSpec`.
///
/// # Design
///
/// This can't be `Self` or `&Self` because that makes the trait non-object
/// safe. Adding a `where: Self: Sized` bound prevents the method from being
/// called from `cmd_ctx_builder`.
fn merge(&mut self, other: &dyn AnySpecDataType);
}
impl<T> AnySpecRt for Box<T>
where
T: AnySpecRt,
{
fn is_usable(&self) -> bool {
self.as_ref().is_usable()
}
fn merge(&mut self, other: &dyn AnySpecDataType)
where
Self: Sized,
{
self.as_mut().merge(other)
}
}