pub struct Terms<'t, E, N: Normalize = Equality> { /* private fields */ }Expand description
A sink that collects one Term per scalar with an equality domain,
in walk order.
Generic over its error type so it adopts its Tee partner’s. To
collect terms without encrypting, call terms, whose error type is
TermsError. Generic too over the Normalize that encodes each
scalar, Equality unless by is given another, so an
index of another kind collects its terms through this same walk.
Under Equality every null has a term, typed or plain, at the
null’s path and under domain::NULL, so an
absent value is indexed like any other. A layer that must keep a SQL
NULL for some column drops that term; its domain says it is a null.
A scalar whose kind has no domain (a boolean, an undefined, or a
null under a normalizer that gives nulls none) produces no term and
does not stop the walk: an unindexable value is an ordinary thing to
find in a document, and the caller has the paths to see which fields
were indexed. A scalar whose logical
type has no domain (Logical::Unknown, or a type this crate does
not know) stops the walk instead: it came from a newer client and
means something, and encrypting it with no term and no error would
leave an index silently incomplete.
Passthrough subtrees travel in the clear and get no terms.
§Only what can be encrypted
A Terms refuses every value EncryptSink refuses, for the same
Unencryptable reason and at the same path, so an index never holds
terms for a value that cannot be stored. It keeps the
shape rules through the code EncryptSink
keeps them with: nothing deeper than the transport’s depth limit, every
scalar valid for its logical type, every passthrough subtree framable,
no map key given twice, no child sink dropped without a value, and
something sealed in every container with children. The last rule is
about sealing, and this walk seals nothing, but a value that breaks it
cannot be encrypted, so it is refused here too. A passthrough is framed
as encryption frames it, to check that it can be, and the frame is
dropped.
So terms accepts a value exactly when encrypt_with_terms does
with a cipher that does not fail, and refuses it for the same reason at
the same path. plan_with_terms, and the encrypting functions built
on it, pair EncryptSink with a Terms that leaves the shape rules to
it, so they are kept once.
§Errors
The walk stops with E::source(SourceError::new(error)), where error
is one of:
- a
Refusal: the value breaks a shape rule, as above. A scalar not valid for its logical type is refused this way, asUnencryptable::InvalidValue, before it is normalized. Throughtermsit isTermsError::refusal. BesideEncryptSink, which refuses it first, it isEncryptError::Shape. - a
TermErrorholding the scalar’s path and theNormalizeError: the scalar’s logical type has no domain (NoDomain), or its text holds a code point unassigned in Unicode 16 (UnassignedCodePoint). BesideEncryptSinkthat arrives asEncryptError::Source, andsource.inner().downcast_ref::<TermError>()recovers it. Alone, throughterms, it isTermsError::term. Either way theNormalizeErroris on thesource()chain.
§Cost
A path costs nothing until a term is pushed or a refusal is built. Each child sink holds a link to its container’s place and its own index, or the position of its key in one buffer of the keys on the path being walked, which the whole walk shares and reuses. So the walk allocates that buffer, as long as the keys on the longest path, and otherwise only what each pushed term needs.
The shape rules cost what they cost encryption: a map keeps one copy
of each of its keys until it ends, which is what checking for a repeat
exactly takes, and a passthrough is framed. Beside EncryptSink,
through plan_with_terms, none of that is paid twice. A caller that
tees Terms::new beside EncryptSink itself has both keep the rules.
Implementations§
Trait Implementations§
Source§impl<'t, E: Error, N: Normalize> Sink for Terms<'t, E, N>
impl<'t, E: Error, N: Normalize> Sink for Terms<'t, E, N>
Source§fn typed_null(self, _: FixedType) -> Result<(), E>
fn typed_null(self, _: FixedType) -> Result<(), E>
Indexed as a plain null. Equality has no width, so the type adds
nothing: under Equality a typed null is the same term as a
plain one.
Source§fn passthrough<P: Encrypt + Clone>(self, value: P) -> Result<(), E>
fn passthrough<P: Encrypt + Clone>(self, value: P) -> Result<(), E>
No terms. Keeping the shape rules, the subtree is framed, as encryption frames it, and the frame dropped.
Source§type Error = E
type Error = E
SourceError.