Skip to main content

doublets/decorators/
constants.rs

1//! Decorators that give a service constant a meaning inside a substitution.
2//!
3//! Ports of C# `LinksItselfConstantToSelfReferenceResolver` and
4//! `LinksNullConstantToSelfReferenceResolver`.
5
6use std::{
7    fmt::{self, Debug, Formatter},
8    marker::PhantomData,
9};
10
11use data::{Flow, LinkReference, LinksConstants};
12
13use super::{
14    helpers,
15    macros::{decorator_struct, forward},
16};
17use crate::{
18    data::{ReadHandler, WriteHandler},
19    Doublets, Error, Link, Links,
20};
21
22decorator_struct! {
23    /// Turns the `itself` constant into a reference to the link being written.
24    ///
25    /// Port of C# `LinksItselfConstantToSelfReferenceResolver`. A query that contains
26    /// `itself` can never match a stored link, so [`Links::each_links`] short-circuits to
27    /// an empty result.
28    ItselfConstantToSelfReferenceResolver
29}
30
31impl<T: LinkReference, L: Doublets<T>> Links<T> for ItselfConstantToSelfReferenceResolver<T, L> {
32    forward!(count_links, create_links, delete_links);
33
34    #[inline]
35    fn each_links(&self, query: &[T], handler: ReadHandler<'_, T>) -> Flow {
36        let constants = self.links.constants();
37        if constants.any != constants.itself && query.contains(&constants.itself) {
38            return Flow::Continue;
39        }
40        self.links.each_links(query, handler)
41    }
42
43    #[inline]
44    fn update_links(
45        &mut self,
46        query: &[T],
47        change: &[T],
48        handler: WriteHandler<'_, T>,
49    ) -> Result<Flow, Error<T>> {
50        let constants = self.links.constants();
51        let change =
52            helpers::resolve_constant_as_self_reference(constants.itself, query, change, constants);
53        self.links.update_links(query, &change, handler)
54    }
55}
56
57decorator_struct! {
58    /// Turns the `null` constant into a reference to the link being written, and makes a
59    /// bare create produce a self-referential point.
60    ///
61    /// Port of C# `LinksNullConstantToSelfReferenceResolver`.
62    NullConstantToSelfReferenceResolver
63}
64
65impl<T: LinkReference, L: Doublets<T>> Links<T> for NullConstantToSelfReferenceResolver<T, L> {
66    forward!(count_links, each_links, delete_links);
67
68    #[inline]
69    fn create_links(
70        &mut self,
71        _query: &[T],
72        handler: WriteHandler<'_, T>,
73    ) -> Result<Flow, Error<T>> {
74        helpers::create_point_with(&mut self.links, &mut *handler)
75    }
76
77    #[inline]
78    fn update_links(
79        &mut self,
80        query: &[T],
81        change: &[T],
82        handler: WriteHandler<'_, T>,
83    ) -> Result<Flow, Error<T>> {
84        let constants = self.links.constants();
85        let change =
86            helpers::resolve_constant_as_self_reference(constants.null, query, change, constants);
87        self.links.update_links(query, &change, handler)
88    }
89}