Skip to main content

alux_shape_morph/
patch.rs

1//! Every member of a shape, made optional.
2
3use crate::delegate::delegate_shape_except_named;
4use alux_shape::{FieldAlg, ShapeAlg, Words};
5
6/// A shape whose members may all be absent, under a name of its own.
7///
8/// What a caller sends to change part of a value: the same shape, with nothing required. The name
9/// moves with it, so the patch and the whole can be told apart wherever both are declared.
10#[derive(Debug, Clone, Copy, Default)]
11pub struct Patch<A>(pub A);
12
13impl<A> Patch<A> {
14    /// The algebra beneath this transformation.
15    fn inner(&self) -> &A {
16        &self.0
17    }
18}
19
20impl<A> Patch<A>
21where
22    A: ShapeAlg,
23{
24    /// States the name this transformation answers under: the shape's own, and one word more.
25    fn rename(&self, words: Words<'_>, body: A::Ty) -> A::Ty {
26        let mut named: Vec<&str> = words.to_vec();
27        named.push("patch");
28
29        self.inner().named(&named, body)
30    }
31}
32
33delegate_shape_except_named!(Patch);
34
35impl<A> FieldAlg for Patch<A>
36where
37    A: ShapeAlg + FieldAlg,
38{
39    fn field(&self, words: Words<'_>, shape: A::Ty) -> A::Field {
40        // The one operation this transformation is: a member that need not be there.
41        self.inner().field(words, self.inner().opt(shape))
42    }
43
44    fn merge(&self, shape: A::Ty) -> A::Field {
45        // A merged product has already been transformed, since it was folded by this algebra too.
46        self.inner().merge(shape)
47    }
48}