Coverage Report

Created: 2026-05-27 07:00

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/proc/self/cwd/runtime/function_registry.h
Line
Count
Source
1
// Copyright 2023 Google LLC
2
//
3
// Licensed under the Apache License, Version 2.0 (the "License");
4
// you may not use this file except in compliance with the License.
5
// You may obtain a copy of the License at
6
//
7
//     https://www.apache.org/licenses/LICENSE-2.0
8
//
9
// Unless required by applicable law or agreed to in writing, software
10
// distributed under the License is distributed on an "AS IS" BASIS,
11
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
// See the License for the specific language governing permissions and
13
// limitations under the License.
14
15
#ifndef THIRD_PARTY_CEL_CPP_RUNTIME_FUNCTION_REGISTRY_H_
16
#define THIRD_PARTY_CEL_CPP_RUNTIME_FUNCTION_REGISTRY_H_
17
18
#include <cstddef>
19
#include <memory>
20
#include <string>
21
#include <utility>
22
#include <vector>
23
24
#include "absl/container/flat_hash_map.h"
25
#include "absl/container/node_hash_map.h"
26
#include "absl/status/status.h"
27
#include "absl/strings/string_view.h"
28
#include "absl/types/span.h"
29
#include "common/function_descriptor.h"
30
#include "common/kind.h"
31
#include "runtime/function.h"
32
#include "runtime/function_overload_reference.h"
33
#include "runtime/function_provider.h"
34
35
namespace cel {
36
37
// FunctionRegistry manages binding builtin or custom CEL functions to
38
// implementations.
39
//
40
// The registry is consulted during program planning to tie overload candidates
41
// to the CEL function in the AST getting planned.
42
//
43
// The registry takes ownership of the cel::Function objects -- the registry
44
// must outlive any program planned using it.
45
//
46
// This class is move-only.
47
class FunctionRegistry {
48
 public:
49
  // Represents a single overload for a lazily provided function.
50
  struct LazyOverload {
51
    const cel::FunctionDescriptor& descriptor;
52
    const cel::runtime_internal::FunctionProvider& provider;
53
  };
54
55
14.5k
  FunctionRegistry() = default;
56
57
  // Move-only
58
  FunctionRegistry(FunctionRegistry&&) = default;
59
  FunctionRegistry& operator=(FunctionRegistry&&) = default;
60
61
  // Register a function implementation for the given descriptor.
62
  // Function registration should be performed prior to CelExpression creation.
63
  absl::Status Register(const cel::FunctionDescriptor& descriptor,
64
                        std::unique_ptr<cel::Function> implementation);
65
66
  // Register a lazily provided function.
67
  // Internally, the registry binds a FunctionProvider that provides an overload
68
  // at evaluation time by resolving against the overloads provided by an
69
  // implementation of cel::ActivationInterface.
70
  absl::Status RegisterLazyFunction(const cel::FunctionDescriptor& descriptor);
71
72
  // Find subset of cel::Function implementations that match overload conditions
73
  // As types may not be available during expression compilation,
74
  // further narrowing of this subset will happen at evaluation stage.
75
  //
76
  // name - the name of CEL function (as distinct from overload ID);
77
  // receiver_style - indicates whether function has receiver style;
78
  // types - argument types. If  type is not known during compilation,
79
  // cel::Kind::kAny should be passed.
80
  //
81
  // Results refer to underlying registry entries by reference. Results are
82
  // invalid after the registry is deleted.
83
  std::vector<cel::FunctionOverloadReference> FindStaticOverloads(
84
      absl::string_view name, bool receiver_style,
85
      absl::Span<const cel::Kind> types) const;
86
87
  std::vector<cel::FunctionOverloadReference> FindStaticOverloadsByArity(
88
      absl::string_view name, bool receiver_style, size_t arity) const;
89
90
  // Find subset of cel::Function providers that match overload conditions.
91
  // As types may not be available during expression compilation,
92
  // further narrowing of this subset will happen at evaluation stage.
93
  //
94
  // name - the name of CEL function (as distinct from overload ID);
95
  // receiver_style - indicates whether function has receiver style;
96
  // types - argument types. If  type is not known during compilation,
97
  // cel::Kind::kAny should be passed.
98
  //
99
  // Results refer to underlying registry entries by reference. Results are
100
  // invalid after the registry is deleted.
101
  std::vector<LazyOverload> FindLazyOverloads(
102
      absl::string_view name, bool receiver_style,
103
      absl::Span<const cel::Kind> types) const;
104
105
  std::vector<LazyOverload> FindLazyOverloadsByArity(absl::string_view name,
106
                                                     bool receiver_style,
107
                                                     size_t arity) const;
108
109
  // Retrieve list of registered function descriptors. This includes both
110
  // static and lazy functions.
111
  absl::node_hash_map<std::string, std::vector<const cel::FunctionDescriptor*>>
112
  ListFunctions() const;
113
114
 private:
115
  struct StaticFunctionEntry {
116
    StaticFunctionEntry(const cel::FunctionDescriptor& descriptor,
117
                        std::unique_ptr<cel::Function> impl)
118
2.55M
        : descriptor(std::make_unique<cel::FunctionDescriptor>(descriptor)),
119
2.55M
          implementation(std::move(impl)) {}
120
121
    // Extra indirection needed to preserve pointer stability for the
122
    // descriptors.
123
    std::unique_ptr<cel::FunctionDescriptor> descriptor;
124
    std::unique_ptr<cel::Function> implementation;
125
  };
126
127
  struct LazyFunctionEntry {
128
    LazyFunctionEntry(
129
        const cel::FunctionDescriptor& descriptor,
130
        std::unique_ptr<cel::runtime_internal::FunctionProvider> provider)
131
0
        : descriptor(std::make_unique<cel::FunctionDescriptor>(descriptor)),
132
0
          function_provider(std::move(provider)) {}
133
134
    // Extra indirection needed to preserve pointer stability for the
135
    // descriptors.
136
    std::unique_ptr<cel::FunctionDescriptor> descriptor;
137
    std::unique_ptr<cel::runtime_internal::FunctionProvider> function_provider;
138
  };
139
140
  struct RegistryEntry {
141
    std::vector<StaticFunctionEntry> static_overloads;
142
    std::vector<LazyFunctionEntry> lazy_overloads;
143
  };
144
145
  // Returns whether the descriptor is registered either as a lazy function or
146
  // as a static function.
147
  bool DescriptorRegistered(const cel::FunctionDescriptor& descriptor) const;
148
149
  // Returns true if after adding this function, the rule "a non-strict
150
  // function should have only a single overload" will be preserved.
151
  bool ValidateNonStrictOverload(
152
      const cel::FunctionDescriptor& descriptor) const;
153
154
  // indexed by function name (not type checker overload id).
155
  absl::flat_hash_map<std::string, RegistryEntry> functions_;
156
};
157
158
}  // namespace cel
159
160
#endif  // THIRD_PARTY_CEL_CPP_RUNTIME_FUNCTION_REGISTRY_H_