The message and enum types an environment knows, and how to read and build their values.
A provider is a {module, state} tuple, given to CEL.Env.build/1 as
:types. module implements this behaviour, and every callback receives
state first. Without :types there are no message or enum types; the
CEL types, including the protobuf well-known types CEL builds in
(google.protobuf.Timestamp, Duration, Any, Value, ListValue,
Struct and the wrappers), are always available.
PB.CEL.types/1 is the provider for protobuf messages:
CEL.Env.build(types: PB.CEL.types(MyApp.Schema), container: "my.pkg")Names
A message, enum or extension name is whatever term the provider uses for
it, an atom or a string. CEL only compares names with == and shows them
with to_string/1, and never makes one from text itself: names in an
expression become the provider's through find_type/2, field names
through find_field/3. to_string(name) must be the fully qualified
name that find_type/2 resolves back to name.
Values carry the provider's names: a message is {:message, name, payload},
where the provider owns payload, and an enum value is
{:enum, name, number}.
Summary
Types
A message, enum or extension name, in the provider's form.
A message value's payload, owned by the provider.
The provider's own state, passed to every callback.
A provider: a module implementing this behaviour, and its state.
Callbacks
The number of an enum value, by the value's name.
Whether two messages of the type message are equal.
Looks up a field of a message type by name, or an extension by its fully qualified name.
Resolves a fully qualified name, without a leading dot, to a message or enum type.
Converts a variable's binding into a CEL value when the variable is declared with one of the provider's message or enum types and is not bound to a CEL value already.
Reads a field of a message, its default when the field is unset. field
is one find_field/3 returned for the message's type.
Whether a field of a message is set, as CEL's has() tests it.
Builds the value of a message literal from the fields it sets, in the order written. Fields set to an empty optional are left out.
The fields a message literal must set, by name. Optional; without it, none are required.
Unpacks the payload of a google.protobuf.Any literal: the message its type
URL names, decoded from value. :error when the provider does not know
the type, which leaves the literal an object value. Optional; without it,
every Any literal stays an object value.
Types
Callbacks
The number of an enum value, by the value's name.
Whether two messages of the type message are equal.
@callback find_field(state(), message :: name(), field :: String.t()) :: {:ok, CEL.Field.t()} | :error
Looks up a field of a message type by name, or an extension by its fully qualified name.
Resolves a fully qualified name, without a leading dot, to a message or enum type.
@callback from_native(state(), name(), term()) :: {:ok, CEL.Value.t()} | {:error, term()}
Converts a variable's binding into a CEL value when the variable is declared with one of the provider's message or enum types and is not bound to a CEL value already.
@callback get_field(state(), payload(), CEL.Field.t()) :: {:ok, CEL.Value.t()} | {:error, term()}
Reads a field of a message, its default when the field is unset. field
is one find_field/3 returned for the message's type.
@callback has_field?(state(), payload(), CEL.Field.t()) :: boolean()
Whether a field of a message is set, as CEL's has() tests it.
@callback new_message(state(), message :: name(), [{CEL.Field.t(), CEL.Value.t()}]) :: {:ok, CEL.Value.t()} | {:error, term()}
Builds the value of a message literal from the fields it sets, in the order written. Fields set to an empty optional are left out.
The fields a message literal must set, by name. Optional; without it, none are required.
@callback unpack_any(state(), type_url :: String.t(), value :: binary()) :: {:ok, CEL.Value.t()} | :error | {:error, term()}
Unpacks the payload of a google.protobuf.Any literal: the message its type
URL names, decoded from value. :error when the provider does not know
the type, which leaves the literal an object value. Optional; without it,
every Any literal stays an object value.