Coverage Report

Created: 2026-05-27 07:00

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/proc/self/cwd/runtime/standard/string_functions.cc
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
#include "runtime/standard/string_functions.h"
16
17
#include <cstdint>
18
19
#include "absl/base/nullability.h"
20
#include "absl/status/status.h"
21
#include "absl/status/statusor.h"
22
#include "absl/strings/str_cat.h"
23
#include "absl/strings/string_view.h"
24
#include "base/builtins.h"
25
#include "base/function_adapter.h"
26
#include "common/value.h"
27
#include "internal/status_macros.h"
28
#include "runtime/function_registry.h"
29
#include "runtime/runtime_options.h"
30
#include "google/protobuf/arena.h"
31
#include "google/protobuf/descriptor.h"
32
#include "google/protobuf/message.h"
33
34
namespace cel {
35
namespace {
36
37
// Concatenation for string type.
38
absl::StatusOr<StringValue> ConcatString(
39
    const StringValue& value1, const StringValue& value2,
40
    const google::protobuf::DescriptorPool* absl_nonnull,
41
2.17k
    google::protobuf::MessageFactory* absl_nonnull, google::protobuf::Arena* absl_nonnull arena) {
42
2.17k
  return StringValue::Concat(value1, value2, arena);
43
2.17k
}
44
45
// Concatenation for bytes type.
46
absl::StatusOr<BytesValue> ConcatBytes(
47
    const BytesValue& value1, const BytesValue& value2,
48
    const google::protobuf::DescriptorPool* absl_nonnull,
49
558
    google::protobuf::MessageFactory* absl_nonnull, google::protobuf::Arena* absl_nonnull arena) {
50
558
  return BytesValue::Concat(value1, value2, arena);
51
558
}
52
53
0
bool StringContains(const StringValue& value, const StringValue& substr) {
54
0
  return value.Contains(substr);
55
0
}
56
57
0
bool StringEndsWith(const StringValue& value, const StringValue& suffix) {
58
0
  return value.EndsWith(suffix);
59
0
}
60
61
0
bool StringStartsWith(const StringValue& value, const StringValue& prefix) {
62
0
  return value.StartsWith(prefix);
63
0
}
64
65
14.5k
absl::Status RegisterSizeFunctions(FunctionRegistry& registry) {
66
  // String size
67
14.5k
  auto size_func = [](const StringValue& value) -> int64_t {
68
47
    return value.Size();
69
47
  };
70
71
  // Support global and receiver style size() operations on strings.
72
14.5k
  using StrSizeFnAdapter = UnaryFunctionAdapter<int64_t, const StringValue&>;
73
14.5k
  CEL_RETURN_IF_ERROR(StrSizeFnAdapter::RegisterGlobalOverload(
74
14.5k
      cel::builtin::kSize, size_func, registry));
75
76
14.5k
  CEL_RETURN_IF_ERROR(StrSizeFnAdapter::RegisterMemberOverload(
77
14.5k
      cel::builtin::kSize, size_func, registry));
78
79
  // Bytes size
80
14.5k
  auto bytes_size_func = [](const BytesValue& value) -> int64_t {
81
2
    return value.Size();
82
2
  };
83
84
  // Support global and receiver style size() operations on bytes.
85
14.5k
  using BytesSizeFnAdapter = UnaryFunctionAdapter<int64_t, const BytesValue&>;
86
14.5k
  CEL_RETURN_IF_ERROR(BytesSizeFnAdapter::RegisterGlobalOverload(
87
14.5k
      cel::builtin::kSize, bytes_size_func, registry));
88
89
14.5k
  return BytesSizeFnAdapter::RegisterMemberOverload(cel::builtin::kSize,
90
14.5k
                                                    bytes_size_func, registry);
91
14.5k
}
92
93
14.5k
absl::Status RegisterConcatFunctions(FunctionRegistry& registry) {
94
14.5k
  using StrCatFnAdapter =
95
14.5k
      BinaryFunctionAdapter<absl::StatusOr<StringValue>, const StringValue&,
96
14.5k
                            const StringValue&>;
97
14.5k
  CEL_RETURN_IF_ERROR(StrCatFnAdapter::RegisterGlobalOverload(
98
14.5k
      cel::builtin::kAdd, &ConcatString, registry));
99
100
14.5k
  using BytesCatFnAdapter =
101
14.5k
      BinaryFunctionAdapter<absl::StatusOr<BytesValue>, const BytesValue&,
102
14.5k
                            const BytesValue&>;
103
14.5k
  return BytesCatFnAdapter::RegisterGlobalOverload(cel::builtin::kAdd,
104
14.5k
                                                   &ConcatBytes, registry);
105
14.5k
}
106
107
}  // namespace
108
109
absl::Status RegisterStringFunctions(FunctionRegistry& registry,
110
14.5k
                                     const RuntimeOptions& options) {
111
  // Basic substring tests (contains, startsWith, endsWith)
112
29.0k
  for (bool receiver_style : {true, false}) {
113
29.0k
    auto status =
114
29.0k
        BinaryFunctionAdapter<bool, const StringValue&, const StringValue&>::
115
29.0k
            Register(cel::builtin::kStringContains, receiver_style,
116
29.0k
                     StringContains, registry);
117
29.0k
    CEL_RETURN_IF_ERROR(status);
118
119
29.0k
    status =
120
29.0k
        BinaryFunctionAdapter<bool, const StringValue&, const StringValue&>::
121
29.0k
            Register(cel::builtin::kStringEndsWith, receiver_style,
122
29.0k
                     StringEndsWith, registry);
123
29.0k
    CEL_RETURN_IF_ERROR(status);
124
125
29.0k
    status =
126
29.0k
        BinaryFunctionAdapter<bool, const StringValue&, const StringValue&>::
127
29.0k
            Register(cel::builtin::kStringStartsWith, receiver_style,
128
29.0k
                     StringStartsWith, registry);
129
29.0k
    CEL_RETURN_IF_ERROR(status);
130
29.0k
  }
131
132
  // string concatenation if enabled
133
14.5k
  if (options.enable_string_concat) {
134
14.5k
    CEL_RETURN_IF_ERROR(RegisterConcatFunctions(registry));
135
14.5k
  }
136
137
14.5k
  return RegisterSizeFunctions(registry);
138
14.5k
}
139
140
}  // namespace cel