From 5570269f54dbc563c3d0e5a67390a82d61393a76 Mon Sep 17 00:00:00 2001 From: Justin King Date: Wed, 10 Jun 2026 09:35:06 -0700 Subject: [PATCH] Actually remove `*.c` files PiperOrigin-RevId: 929905227 --- cel-c/alloc.c | 140 - cel-c/arena.c | 128 - cel-c/assert.c | 78 - cel-c/ast.c | 1868 ------------ cel-c/ast_proto.c | 667 ----- cel-c/ast_proto_v1alpha1.c | 698 ----- cel-c/ast_traverse.c | 1426 --------- cel-c/constant.c | 67 - cel-c/constant_proto.c | 194 -- cel-c/constant_proto_v1alpha1.c | 203 -- cel-c/cstring_view.c | 90 - cel-c/decl.c | 344 --- cel-c/decl_proto.c | 183 -- cel-c/decl_proto_v1alpha1.c | 187 -- cel-c/duration.c | 109 - cel-c/duration_proto.c | 50 - cel-c/error.c | 290 -- cel-c/error_code.c | 96 - cel-c/error_proto.c | 105 - cel-c/error_space.c | 686 ----- cel-c/error_status.c | 70 - cel-c/hash.c | 249 -- cel-c/operators.c | 246 -- cel-c/ref.c | 189 -- cel-c/ref_proto.c | 86 - cel-c/ref_proto_v1alpha1.c | 88 - cel-c/src/any.c | 183 -- cel-c/src/bit.c | 129 - cel-c/src/bitset.c | 54 - cel-c/src/charconv.c | 393 --- cel-c/src/ctype.c | 98 - cel-c/src/empty_list_value.c | 170 -- cel-c/src/empty_map_value.c | 211 -- cel-c/src/generic_array.c | 374 --- cel-c/src/generic_deque.c | 771 ----- cel-c/src/generic_flat_hash.c | 505 ---- cel-c/src/generic_string.c | 939 ------ cel-c/src/list_value.c | 154 - cel-c/src/malloc.c | 159 - cel-c/src/map_value.c | 396 --- cel-c/src/memory.c | 169 -- cel-c/src/message_equality.c | 1342 --------- cel-c/src/mutable_list_value.c | 366 --- cel-c/src/mutable_map_value.c | 561 ---- cel-c/src/opaque_value.c | 66 - cel-c/src/optional_value.c | 625 ---- cel-c/src/parsed_map_field_value.c | 461 --- cel-c/src/parsed_message_value.c | 349 --- cel-c/src/parsed_repeated_field_value.c | 339 --- cel-c/src/runtime/activation.c | 104 - cel-c/src/runtime/interpretable.c | 3615 ----------------------- cel-c/src/runtime/interpreter.c | 2065 ------------- cel-c/src/runtime/program.c | 98 - cel-c/src/runtime/runtime.c | 133 - cel-c/src/struct_value.c | 248 -- cel-c/src/utf8.c | 228 -- cel-c/src/value.c | 734 ----- cel-c/status.c | 406 --- cel-c/status_code.c | 36 - cel-c/status_proto.c | 145 - cel-c/string_view.c | 98 - cel-c/timestamp.c | 134 - cel-c/timestamp_proto.c | 50 - cel-c/type.c | 829 ------ cel-c/type_proto.c | 299 -- cel-c/type_proto_v1alpha1.c | 310 -- cel-c/well_known_types.c | 738 ----- 67 files changed, 27621 deletions(-) delete mode 100644 cel-c/alloc.c delete mode 100644 cel-c/arena.c delete mode 100644 cel-c/assert.c delete mode 100644 cel-c/ast.c delete mode 100644 cel-c/ast_proto.c delete mode 100644 cel-c/ast_proto_v1alpha1.c delete mode 100644 cel-c/ast_traverse.c delete mode 100644 cel-c/constant.c delete mode 100644 cel-c/constant_proto.c delete mode 100644 cel-c/constant_proto_v1alpha1.c delete mode 100644 cel-c/cstring_view.c delete mode 100644 cel-c/decl.c delete mode 100644 cel-c/decl_proto.c delete mode 100644 cel-c/decl_proto_v1alpha1.c delete mode 100644 cel-c/duration.c delete mode 100644 cel-c/duration_proto.c delete mode 100644 cel-c/error.c delete mode 100644 cel-c/error_code.c delete mode 100644 cel-c/error_proto.c delete mode 100644 cel-c/error_space.c delete mode 100644 cel-c/error_status.c delete mode 100644 cel-c/hash.c delete mode 100644 cel-c/operators.c delete mode 100644 cel-c/ref.c delete mode 100644 cel-c/ref_proto.c delete mode 100644 cel-c/ref_proto_v1alpha1.c delete mode 100644 cel-c/src/any.c delete mode 100644 cel-c/src/bit.c delete mode 100644 cel-c/src/bitset.c delete mode 100644 cel-c/src/charconv.c delete mode 100644 cel-c/src/ctype.c delete mode 100644 cel-c/src/empty_list_value.c delete mode 100644 cel-c/src/empty_map_value.c delete mode 100644 cel-c/src/generic_array.c delete mode 100644 cel-c/src/generic_deque.c delete mode 100644 cel-c/src/generic_flat_hash.c delete mode 100644 cel-c/src/generic_string.c delete mode 100644 cel-c/src/list_value.c delete mode 100644 cel-c/src/malloc.c delete mode 100644 cel-c/src/map_value.c delete mode 100644 cel-c/src/memory.c delete mode 100644 cel-c/src/message_equality.c delete mode 100644 cel-c/src/mutable_list_value.c delete mode 100644 cel-c/src/mutable_map_value.c delete mode 100644 cel-c/src/opaque_value.c delete mode 100644 cel-c/src/optional_value.c delete mode 100644 cel-c/src/parsed_map_field_value.c delete mode 100644 cel-c/src/parsed_message_value.c delete mode 100644 cel-c/src/parsed_repeated_field_value.c delete mode 100644 cel-c/src/runtime/activation.c delete mode 100644 cel-c/src/runtime/interpretable.c delete mode 100644 cel-c/src/runtime/interpreter.c delete mode 100644 cel-c/src/runtime/program.c delete mode 100644 cel-c/src/runtime/runtime.c delete mode 100644 cel-c/src/struct_value.c delete mode 100644 cel-c/src/utf8.c delete mode 100644 cel-c/src/value.c delete mode 100644 cel-c/status.c delete mode 100644 cel-c/status_code.c delete mode 100644 cel-c/status_proto.c delete mode 100644 cel-c/string_view.c delete mode 100644 cel-c/timestamp.c delete mode 100644 cel-c/timestamp_proto.c delete mode 100644 cel-c/type.c delete mode 100644 cel-c/type_proto.c delete mode 100644 cel-c/type_proto_v1alpha1.c delete mode 100644 cel-c/well_known_types.c diff --git a/cel-c/alloc.c b/cel-c/alloc.c deleted file mode 100644 index f96205e..0000000 --- a/cel-c/alloc.c +++ /dev/null @@ -1,140 +0,0 @@ -// Copyright 2024 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "cel-c/alloc.h" - -#include -#include -#include -#include -#include - -#include "cel-c/assert.h" -#include "cel-c/config.h" -#include "cel-c/src/ckdint.h" -#include "cel-c/src/malloc.h" -#include "upb/mem/alloc.h" - -CEL_NULLABLE(void*) -cel_Allocator_Calloc(CEL_NONNULL(cel_Allocator*) alloc, size_t num, size_t size, - CEL_NULLABLE(size_t*) actual_num) { - CEL_ASSERT_NOT_NULL(alloc); - CEL_ASSERT_NOT_NULL(alloc->func); - - size_t total_size; - if (CEL_UNLIKELY(_cel_ckd_mul(&total_size, num, size))) { - errno = ENOMEM; - return cel_nullptr; - } - void* addr = (*alloc->func)(alloc, cel_nullptr, 0, total_size, actual_num); - if (actual_num != cel_nullptr && addr != cel_nullptr) { - *actual_num /= size; - } - return addr; -} - -static CEL_NULLABILITY_UNKNOWN(void*) _cel_DefaultAllocator_AllocFunc( - CEL_NULLABILITY_UNKNOWN(upb_alloc*) alloc, - CEL_NULLABILITY_UNKNOWN(void*) ptr, size_t oldsize, size_t size, - size_t* cel_nullability_unknown actual_size) { - CEL_ASSERT_NOT_NULL(alloc); - - if (ptr == cel_nullptr) { - CEL_ASSERT_EQ(oldsize, 0); - return _cel_Malloc(size, actual_size); - } - if (size == 0) { - if (oldsize != 0) { - _cel_FreeSized(ptr, oldsize); - } else { - _cel_Free(ptr); - } - if (actual_size != cel_nullptr) { - *actual_size = 0; - } - return cel_nullptr; - } - return _cel_Realloc(ptr, oldsize, size, actual_size); -} - -static cel_Allocator _cel_DefaultAllocator = { - .func = &_cel_DefaultAllocator_AllocFunc, -}; - -CEL_NONNULL(cel_Allocator*) const cel_DefaultAllocator = &_cel_DefaultAllocator; - -CEL_NULLABLE(char*) -cel_Allocator_StrDup(CEL_NONNULL(cel_Allocator*) alloc, - CEL_NULLABLE(size_t*) actual_size, - CEL_NONNULL(const char*) str) { - CEL_ASSERT_NOT_NULL(alloc); - CEL_ASSERT_NOT_NULL(str); - size_t len = strlen(str) + 1; - CEL_NULLABLE(char*) - dup = (CEL_NULLABLE(char*))cel_Allocator_Malloc(alloc, len, actual_size); - if (CEL_UNLIKELY(dup == cel_nullptr)) { - return cel_nullptr; - } - memcpy(dup, str, len); - return dup; -} - -CEL_NULLABLE(char*) -cel_Allocator_PrintF(CEL_NONNULL(cel_Allocator*) alloc, - CEL_NULLABLE(size_t*) actual_size, - CEL_NONNULL(const char*) fmt, ...) { - va_list args; - va_start(args, fmt); - CEL_NULLABLE(char*) - str = cel_Allocator_VPrintF(alloc, actual_size, fmt, args); - va_end(args); - return str; -} - -CEL_NULLABLE(char*) -cel_Allocator_VPrintF(CEL_NONNULL(cel_Allocator*) alloc, - CEL_NULLABLE(size_t*) actual_size, - CEL_NONNULL(const char*) fmt, va_list args) { - CEL_ASSERT_NOT_NULL(alloc); - CEL_ASSERT_NOT_NULL(fmt); - char buf[128]; - int size; - { - va_list args_copy; - va_copy(args_copy, args); - size = vsnprintf(buf, sizeof(buf), fmt, args_copy); - va_end(args_copy); - } - CEL_ASSERT_GE(size, 0); - if (CEL_UNLIKELY(size < 0)) { - errno = EINVAL; - if (actual_size != cel_nullptr) { - *actual_size = 0; - } - return cel_nullptr; - } - CEL_NULLABLE(char*) - str = (CEL_NULLABLE(char*))cel_Allocator_Malloc(alloc, ((size_t)size) + 1, - actual_size); - if (CEL_UNLIKELY(str == cel_nullptr)) { - return cel_nullptr; - } - if (size < sizeof(buf)) { - memcpy(str, buf, ((size_t)size) + 1); - } else { - const int size_copy = vsnprintf(str, ((size_t)size) + 1, fmt, args); - CEL_ASSERT_EQ(size_copy, size); - } - return str; -} diff --git a/cel-c/arena.c b/cel-c/arena.c deleted file mode 100644 index d30eae2..0000000 --- a/cel-c/arena.c +++ /dev/null @@ -1,128 +0,0 @@ -// Copyright 2024 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "cel-c/arena.h" - -#include -#include -#include -#include -#include - -#include "cel-c/assert.h" -#include "cel-c/config.h" -#include "cel-c/src/align.h" -#include "cel-c/src/ckdint.h" -#include "upb/base/string_view.h" -#include "upb/mem/arena.h" - -CEL_NULLABLE(void*) -cel_Arena_Calloc(CEL_NONNULL(cel_Arena*) arena, size_t num, size_t size, - CEL_NULLABLE(size_t*) actual_num) { - CEL_ASSERT_NOT_NULL(arena); - - if (CEL_UNLIKELY(num == 0 || size == 0)) { - if (actual_num != cel_nullptr) { - *actual_num = 0; - } - return cel_nullptr; - } - size_t total_size; - if (CEL_UNLIKELY(_cel_ckd_mul(&total_size, num, size))) { - if (actual_num != cel_nullptr) { - *actual_num = 0; - } - return cel_nullptr; - } - CEL_NULLABLE(void*) addr = upb_Arena_Malloc(arena, total_size); - CEL_ASSERT(addr == cel_nullptr || _cel_is_aligned(addr, cel_Arena_kMaxAlign)); - if (CEL_LIKELY(addr != cel_nullptr)) { - memset(addr, '\0', total_size); - } - if (actual_num != cel_nullptr) { - *actual_num = addr != cel_nullptr ? num : 0; - } - return addr; -} - -CEL_NULLABLE(void*) -cel_Arena_Realloc(CEL_NONNULL(cel_Arena*) arena, CEL_NULLABLE(void*) addr, - size_t old_size, size_t new_size, - CEL_NULLABLE(size_t*) actual_size) { - CEL_ASSERT_NOT_NULL(arena); - - if (old_size == 0) { - CEL_ASSERT_NULL(addr); - return cel_Arena_Malloc(arena, new_size, actual_size); - } - CEL_NULLABLE(void*) - new_addr = upb_Arena_Realloc(arena, addr, old_size, new_size); - CEL_ASSERT(addr == cel_nullptr || _cel_is_aligned(addr, cel_Arena_kMaxAlign)); - if (actual_size != cel_nullptr) { - *actual_size = new_addr != cel_nullptr ? new_size : 0; - } - return new_size != 0 ? new_addr : cel_nullptr; -} - -void cel_Arena_FreeSized(CEL_NONNULL(cel_Arena*) arena, - CEL_NULLABLE(void*) addr, size_t size) { - CEL_ASSERT_NOT_NULL(arena); - - if (CEL_UNLIKELY(size == 0)) { - CEL_ASSERT_NULL(addr); - return; - } - CEL_ASSERT_NOT_NULL(addr); - CEL_USED(upb_Arena_Realloc(arena, addr, size, 0)); -} - -bool cel_Arena_VPrintF(CEL_NONNULL(cel_Arena*) arena, - CEL_NONNULL(upb_StringView*) out, - CEL_NONNULL(const char*) fmt, va_list args) { - CEL_ASSERT_NOT_NULL(arena); - CEL_ASSERT_NOT_NULL(out); - CEL_ASSERT_NOT_NULL(fmt); - - char buf[128]; - int size; - { - va_list args_copy; - va_copy(args_copy, args); - size = vsnprintf(buf, sizeof(buf), fmt, args_copy); - va_end(args_copy); - } - CEL_ASSERT_GE(size, 0); - if (CEL_UNLIKELY(size < 0)) { - return false; - } - if (CEL_UNLIKELY(size == 0)) { - *out = upb_StringView_FromDataAndSize("", 0); - return true; - } - const bool fit = size < sizeof(buf); - CEL_NULLABLE(char*) - str = (CEL_NULLABLE(char*))cel_Arena_Malloc( - arena, ((size_t)size) + (fit ? 0 : 1), cel_nullptr); - if (CEL_UNLIKELY(str == cel_nullptr)) { - return false; - } - if (fit) { - memcpy(str, buf, (size_t)size); - } else { - const int size_copy = vsnprintf(str, ((size_t)size) + 1, fmt, args); - CEL_ASSERT_EQ(size_copy, size); - } - *out = upb_StringView_FromDataAndSize(str, (size_t)size); - return true; -} diff --git a/cel-c/assert.c b/cel-c/assert.c deleted file mode 100644 index fb0ac55..0000000 --- a/cel-c/assert.c +++ /dev/null @@ -1,78 +0,0 @@ -// Copyright 2024 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "cel-c/assert.h" - -#include -#include -#include - -#ifdef __ANDROID__ -#include -#if __ANDROID_API__ >= 21 -#include -extern void android_set_abort_message(const char* msg); -#else -#include -#endif -#endif - -#include "cel-c/config.h" - -#if defined(__APPLE__) && CEL_HAVE_INCLUDE() -#include -#endif - -#ifdef _MSC_VER -#include -#endif - -void cel_AssertionFailed(CEL_NONNULL(const char*) file, int line, - CEL_NONNULL(const char*) cond) { - CEL_USED(file); - CEL_USED(line); - CEL_USED(cond); -#ifndef NDEBUG - fprintf(stderr, "%s:%d: Assertion `%s' failed\n", file, line, cond); - fflush(stderr); -#ifdef __ANDROID__ - CEL_NULLABLE(char*) amsg = cel_nullptr; - asprintf(&amsg, "%s:%d: Assertion `%s' failed\n", file, line, cond); - if (amsg == cel_nullptr) { - amsg = (CEL_NULLABLE(char*))""; - } -#if __ANDROID_API__ >= 21 - android_set_abort_message(amsg); - openlog("cel", 0, 0); - syslog(LOG_CRIT, "%s", amsg); - closelog(); -#else - __assert2(file, line, __func__, amsg); -#endif -#elif defined(__APPLE__) && CEL_HAVE_INCLUDE() - CEL_NULLABLE(char*) amsg = cel_nullptr; - asprintf(&amsg, "%s:%d: Assertion `%s' failed\n", file, line, cond); - if (amsg == cel_nullptr) { - amsg = (CEL_NULLABLE(char*))""; - } - CRSetCrashLogMessage(amsg); -#endif -#endif -#if !defined(NDEBUG) && CEL_HAVE_BUILTIN(__builtin_debugtrap) - __builtin_debugtrap(); -#elif !defined(NDEBUG) && defined(_MSC_VER) - __debugbreak(); -#endif - abort(); -} diff --git a/cel-c/ast.c b/cel-c/ast.c deleted file mode 100644 index e5dedf7..0000000 --- a/cel-c/ast.c +++ /dev/null @@ -1,1868 +0,0 @@ -// Copyright 2025 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "cel-c/ast.h" - -#include -#include -#include -#include - -#include "cel-c/arena.h" -#include "cel-c/assert.h" -#include "cel-c/ast.h" -#include "cel-c/config.h" -#include "cel-c/constant.h" -#include "cel-c/operators.h" -#include "cel-c/ref.h" -#include "cel-c/source.h" -#include "cel-c/string_view.h" -#include "cel-c/type.h" - -typedef struct _cel_ExprLink _cel_ExprLink; - -struct _cel_ExprLink { - cel_ExprId id; - CEL_NONNULL(cel_Ast*) ast; - CEL_NULLABLE(cel_Expr*) parent; - cel_ExprKind kind; - cel_SourceRange range; - CEL_NULLABLE(const cel_Ref *) ref; - CEL_NULLABLE(cel_Type *) type; - - CEL_NULLABLE(_cel_ExprLink*) left; - CEL_NULLABLE(_cel_ExprLink*) right; - ptrdiff_t index; -}; - -struct cel_UnspecifiedExpr { - cel_ExprId id; - CEL_NONNULL(cel_Ast*) ast; - CEL_NULLABLE(cel_Expr*) parent; - cel_ExprKind kind; - cel_SourceRange range; - CEL_NULLABLE(const cel_Ref *) ref; - CEL_NULLABLE(cel_Type *) type; -}; - -struct cel_IdentExpr { - cel_ExprId id; - CEL_NONNULL(cel_Ast*) ast; - CEL_NULLABLE(cel_Expr*) parent; - cel_ExprKind kind; - cel_SourceRange range; - CEL_NULLABLE(const cel_Ref *) ref; - CEL_NULLABLE(cel_Type *) type; - - cel_StringView name; -}; - -struct cel_ConstExpr { - cel_ExprId id; - CEL_NONNULL(cel_Ast*) ast; - CEL_NULLABLE(cel_Expr*) parent; - cel_ExprKind kind; - cel_SourceRange range; - CEL_NULLABLE(const cel_Ref *) ref; - CEL_NULLABLE(cel_Type *) type; - - cel_Constant value; -}; - -struct cel_SelectExpr { - cel_ExprId id; - CEL_NONNULL(cel_Ast*) ast; - CEL_NULLABLE(cel_Expr*) parent; - cel_ExprKind kind; - cel_SourceRange range; - CEL_NULLABLE(const cel_Ref *) ref; - CEL_NULLABLE(cel_Type *) type; - - CEL_NULLABLE(cel_Expr*) operand; - cel_StringView field; - bool test_only; -}; - -struct cel_CallExpr { - cel_ExprId id; - CEL_NONNULL(cel_Ast*) ast; - CEL_NULLABLE(cel_Expr*) parent; - cel_ExprKind kind; - cel_SourceRange range; - CEL_NULLABLE(const cel_Ref *) ref; - CEL_NULLABLE(cel_Type *) type; - - cel_StringView function; - CEL_NULLABLE(cel_Expr*) target; - CEL_NULLABLE(_cel_ExprLink*) args_head; - CEL_NULLABLE(_cel_ExprLink*) args_tail; - size_t args; -}; - -struct cel_CallArgExpr { - cel_ExprId id; - CEL_NONNULL(cel_Ast*) ast; - CEL_NULLABLE(cel_Expr*) parent; - cel_ExprKind kind; - cel_SourceRange range; - CEL_NULLABLE(const cel_Ref *) ref; - CEL_NULLABLE(cel_Type *) type; - - CEL_NULLABLE(_cel_ExprLink*) left; - CEL_NULLABLE(_cel_ExprLink*) right; - ptrdiff_t index; - CEL_NULLABLE(cel_Expr*) value; -}; - -struct cel_UnaryExpr { - cel_ExprId id; - CEL_NONNULL(cel_Ast*) ast; - CEL_NULLABLE(cel_Expr*) parent; - cel_ExprKind kind; - cel_SourceRange range; - CEL_NULLABLE(const cel_Ref *) ref; - CEL_NULLABLE(cel_Type *) type; - - cel_UnaryOp op; - CEL_NULLABLE(cel_Expr*) args[1]; -}; - -struct cel_BinaryExpr { - cel_ExprId id; - CEL_NONNULL(cel_Ast*) ast; - CEL_NULLABLE(cel_Expr*) parent; - cel_ExprKind kind; - cel_SourceRange range; - CEL_NULLABLE(const cel_Ref *) ref; - CEL_NULLABLE(cel_Type *) type; - - cel_BinaryOp op; - CEL_NULLABLE(cel_Expr*) args[2]; -}; - -struct cel_TernaryExpr { - cel_ExprId id; - CEL_NONNULL(cel_Ast*) ast; - CEL_NULLABLE(cel_Expr*) parent; - cel_ExprKind kind; - cel_SourceRange range; - CEL_NULLABLE(const cel_Ref *) ref; - CEL_NULLABLE(cel_Type *) type; - - cel_TernaryOp op; - CEL_NULLABLE(cel_Expr*) args[3]; -}; - -struct cel_ListElementExpr { - cel_ExprId id; - CEL_NONNULL(cel_Ast*) ast; - CEL_NULLABLE(cel_Expr*) parent; - cel_ExprKind kind; - cel_SourceRange range; - CEL_NULLABLE(const cel_Ref *) ref; - CEL_NULLABLE(cel_Type *) type; - - CEL_NULLABLE(_cel_ExprLink*) left; - CEL_NULLABLE(_cel_ExprLink*) right; - ptrdiff_t index; - CEL_NULLABLE(cel_Expr*) value; - bool optional; -}; - -struct cel_ListExpr { - cel_ExprId id; - CEL_NONNULL(cel_Ast*) ast; - CEL_NULLABLE(cel_Expr*) parent; - cel_ExprKind kind; - cel_SourceRange range; - CEL_NULLABLE(const cel_Ref *) ref; - CEL_NULLABLE(cel_Type *) type; - - CEL_NULLABLE(_cel_ExprLink*) elems_head; - CEL_NULLABLE(_cel_ExprLink*) elems_tail; - size_t elems; -}; - -struct cel_MapEntryExpr { - cel_ExprId id; - CEL_NONNULL(cel_Ast*) ast; - CEL_NULLABLE(cel_Expr*) parent; - cel_ExprKind kind; - cel_SourceRange range; - CEL_NULLABLE(const cel_Ref *) ref; - CEL_NULLABLE(cel_Type *) type; - - CEL_NULLABLE(_cel_ExprLink*) left; - CEL_NULLABLE(_cel_ExprLink*) right; - ptrdiff_t index; - CEL_NULLABLE(cel_Expr*) key; - CEL_NULLABLE(cel_Expr*) value; - bool optional; -}; - -struct cel_MapExpr { - cel_ExprId id; - CEL_NONNULL(cel_Ast*) ast; - CEL_NULLABLE(cel_Expr*) parent; - cel_ExprKind kind; - cel_SourceRange range; - CEL_NULLABLE(const cel_Ref *) ref; - CEL_NULLABLE(cel_Type *) type; - - CEL_NULLABLE(_cel_ExprLink*) ents_head; - CEL_NULLABLE(_cel_ExprLink*) ents_tail; - size_t ents; -}; - -struct cel_StructFieldExpr { - cel_ExprId id; - CEL_NONNULL(cel_Ast*) ast; - CEL_NULLABLE(cel_Expr*) parent; - cel_ExprKind kind; - cel_SourceRange range; - CEL_NULLABLE(const cel_Ref *) ref; - CEL_NULLABLE(cel_Type *) type; - - CEL_NULLABLE(_cel_ExprLink*) left; - CEL_NULLABLE(_cel_ExprLink*) right; - ptrdiff_t index; - cel_StringView name; - CEL_NULLABLE(cel_Expr*) value; - bool optional; -}; - -struct cel_StructExpr { - cel_ExprId id; - CEL_NONNULL(cel_Ast*) ast; - CEL_NULLABLE(cel_Expr*) parent; - cel_ExprKind kind; - cel_SourceRange range; - CEL_NULLABLE(const cel_Ref *) ref; - CEL_NULLABLE(cel_Type *) type; - - cel_StringView name; - CEL_NULLABLE(_cel_ExprLink*) flds_head; - CEL_NULLABLE(_cel_ExprLink*) flds_tail; - size_t flds; -}; - -struct cel_ComprehensionExpr { - cel_ExprId id; - CEL_NONNULL(cel_Ast*) ast; - CEL_NULLABLE(cel_Expr*) parent; - cel_ExprKind kind; - cel_SourceRange range; - CEL_NULLABLE(const cel_Ref *) ref; - CEL_NULLABLE(cel_Type *) type; - - cel_StringView iter_var; - cel_StringView iter_var2; - CEL_NULLABLE(cel_Expr*) iter_range; - cel_StringView accu_var; - CEL_NULLABLE(cel_Expr*) accu_init; - CEL_NULLABLE(cel_Expr*) loop_condition; - CEL_NULLABLE(cel_Expr*) loop_step; - CEL_NULLABLE(cel_Expr*) result; -}; - -struct cel_Expr { - union { - struct { - cel_ExprId id; - CEL_NONNULL(cel_Ast*) ast; - CEL_NULLABLE(cel_Expr*) parent; - cel_ExprKind kind; - cel_SourceRange range; - CEL_NULLABLE(const cel_Ref *) ref; - CEL_NULLABLE(const cel_Type *) type; - }; - _cel_ExprLink link; - cel_UnspecifiedExpr unspecified_expr; - cel_IdentExpr ident_expr; - cel_ConstExpr const_expr; - cel_SelectExpr select_expr; - cel_CallExpr call_expr; - cel_UnaryExpr unary_expr; - cel_BinaryExpr binary_expr; - cel_TernaryExpr ternary_expr; - cel_ListElementExpr optional_expr; - cel_ListExpr list_expr; - cel_MapEntryExpr map_entry_expr; - cel_MapExpr map_expr; - cel_StructFieldExpr struct_field_expr; - cel_StructExpr struct_expr; - cel_ComprehensionExpr comprehension_expr; - }; -}; - -struct cel_Ast { - CEL_NONNULL(cel_Arena*) arena; - cel_ExprId next_id; - CEL_NULLABLE(cel_Expr*) expr; -}; - -cel_ExprId cel_Ast_NextId(CEL_NONNULL(cel_Ast*) ast) { - CEL_ASSERT_NOT_NULL(ast); - - return ++ast->next_id; -} - -cel_ExprId cel_Ast_MaxId(CEL_NONNULL(const cel_Ast*) ast) { - CEL_ASSERT_NOT_NULL(ast); - - return ast->next_id; -} - -CEL_NULLABLE(cel_Expr*) cel_Ast_Expr(CEL_NONNULL(const cel_Ast*) ast) { - CEL_ASSERT_NOT_NULL(ast); - CEL_ASSERT(ast->expr == cel_nullptr || - (ast->expr->ast == ast && ast->expr->parent == cel_nullptr)); - - return ast->expr; -} - -CEL_NULLABLE(cel_Expr*) -cel_Ast_SetExpr(CEL_NONNULL(cel_Ast*) ast, CEL_NULLABLE(cel_Expr*) expr) { - CEL_ASSERT_NOT_NULL(ast); - CEL_ASSERT(expr == cel_nullptr || - (expr->ast == ast && expr->parent == cel_nullptr)); - CEL_ASSERT(ast->expr == cel_nullptr || - (ast->expr->ast == ast && ast->expr->parent == cel_nullptr)); - - CEL_NULLABLE(cel_Expr*) old_expr = ast->expr; - ast->expr = expr; - return old_expr; -} - -CEL_NULLABLE(cel_Expr*) -cel_Ast_ReleaseExpr(CEL_NONNULL(cel_Ast*) ast) { - return cel_Ast_SetExpr(ast, cel_nullptr); -} - -CEL_NULLABLE(cel_Ast*) cel_Ast_New(CEL_NONNULL(cel_Arena*) arena) { - CEL_ASSERT_NOT_NULL(arena); - - CEL_NULLABLE(cel_Ast*) - ast = (CEL_NULLABLE(cel_Ast*))cel_Arena_Malloc(arena, sizeof(cel_Ast), - cel_nullptr); - if (ast != cel_nullptr) { - memset(ast, 0, sizeof(*ast)); - ast->arena = arena; - } - return ast; -} - -void cel_Ast_Delete(CEL_NULLABLE(cel_Ast*) ast) {} - -CEL_ATTRIBUTE_NODISCARD -static CEL_NULLABLE(cel_Expr*) - _cel_Expr_ReleaseChild(CEL_NONNULL(cel_Expr*) expr, - cel_Expr* cel_nullable* cel_nonnull child_ptr) { - CEL_NULLABLE(cel_Expr*) child = *child_ptr; - if (child != cel_nullptr) { - CEL_ASSERT_EQ(child->parent, expr); - *child_ptr = cel_nullptr; - child->parent = cel_nullptr; - } - return child; -} - -static CEL_NULLABLE(cel_Expr*) - _cel_Expr_SetChild(CEL_NONNULL(cel_Expr*) expr, - cel_Expr* cel_nullable* cel_nonnull child_ptr, - CEL_NULLABLE(cel_Expr*) child) { - CEL_ASSERT(child == cel_nullptr || - (child->ast == expr->ast && child->parent == cel_nullptr)); - - CEL_NULLABLE(cel_Expr*) old_child = _cel_Expr_ReleaseChild(expr, child_ptr); - *child_ptr = child; - if (child != cel_nullptr) { - child->parent = expr; - } - return old_child; -} - -CEL_ATTRIBUTE_NODISCARD -static CEL_NULLABLE(cel_Expr*) - _cel_Expr_Child(CEL_NONNULL(const cel_Expr*) expr, - CEL_NULLABLE(cel_Expr*) child) { - CEL_ASSERT(child == cel_nullptr || - (child->ast == expr->ast && child->parent == expr)); - - return child; -} - -static void _cel_Expr_LinkChild( - CEL_NONNULL(cel_Expr*) expr, - _cel_ExprLink* cel_nullable* cel_nonnull head_ptr, - _cel_ExprLink* cel_nullable* cel_nonnull tail_ptr, - CEL_NONNULL(size_t*) size_ptr, CEL_NULLABLE(_cel_ExprLink*) next, - CEL_NONNULL(_cel_ExprLink*) child) { - CEL_ASSERT(child != cel_nullptr && child->ast == expr->ast && - child->parent == cel_nullptr && child->left == cel_nullptr && - child->right == cel_nullptr && - (next == cel_nullptr || next->parent == expr)); - - if (next == cel_nullptr) { - // nullptr is end - CEL_NULLABLE(_cel_ExprLink*) head = *head_ptr; - CEL_NULLABLE(_cel_ExprLink*) tail = *tail_ptr; - child->left = tail; - if (tail != cel_nullptr) { - CEL_ASSERT_NOT_NULL(head); - tail->right = child; - child->index = tail->index + 1; - } else { - CEL_ASSERT_NULL(head); - *head_ptr = child; - child->index = 0; - } - *tail_ptr = child; - } else { - CEL_NULLABLE(_cel_ExprLink*) prev = next->left; - child->right = next; - child->index = next->index; - child->left = prev; - next->left = child; - if (prev != cel_nullptr) { - prev->right = child; - } else { - CEL_ASSERT_EQ(*head_ptr, next); - *head_ptr = child; - } - // Fixup indices. - do { - ++next->index; - next = next->right; - } while (next != cel_nullptr); - } - - child->parent = expr; - ++(*size_ptr); -} - -static void _cel_Expr_UnlinkChild( - CEL_NONNULL(cel_Expr*) expr, - _cel_ExprLink* cel_nullable* cel_nonnull head_ptr, - _cel_ExprLink* cel_nullable* cel_nonnull tail_ptr, - CEL_NONNULL(size_t*) size_ptr, CEL_NONNULL(_cel_ExprLink*) child) { - CEL_ASSERT(child != cel_nullptr && child->ast == expr->ast && - child->parent == expr); - - if (child->left != cel_nullptr) { - child->left->right = child->right; - } else { - CEL_ASSERT_EQ(*head_ptr, child); - *head_ptr = child->right; - } - - CEL_NULLABLE(_cel_ExprLink*) - right = child->right; - if (right != cel_nullptr) { - right->left = child->left; - // Fixup indices. - do { - --right->index; - right = right->right; - } while (right != cel_nullptr); - } else { - CEL_ASSERT_EQ(*tail_ptr, child); - *tail_ptr = child->left; - } - - --(*size_ptr); - - child->parent = cel_nullptr; - child->left = child->right = cel_nullptr; - child->index = -1; -} - -cel_ExprKind cel_Expr_Kind(CEL_NONNULL(const cel_Expr*) expr) { - CEL_ASSERT_NOT_NULL(expr); - - return expr->kind; -} - -cel_ExprId cel_Expr_Id(CEL_NONNULL(const cel_Expr*) expr) { - CEL_ASSERT_NOT_NULL(expr); - - return expr->id; -} - -void cel_Expr_SetId(CEL_NONNULL(cel_Expr*) expr, cel_ExprId id) { - CEL_ASSERT_NOT_NULL(expr); - CEL_ASSERT_GE(id, 0); - - if (id < 0) { - id = 0; - } - - if (id > expr->ast->next_id) { - expr->ast->next_id = id; - } - - expr->id = id; -} - -int32_t cel_Expr_SourcePosition(CEL_NONNULL(const cel_Expr*) expr) { - CEL_ASSERT_NOT_NULL(expr); - - return expr->range.begin; -} - -cel_SourceRange cel_Expr_SourceRange(CEL_NONNULL(const cel_Expr*) expr) { - CEL_ASSERT_NOT_NULL(expr); - - return expr->range; -} - -void cel_Expr_SetSourcePosition(CEL_NONNULL(cel_Expr*) expr, - int32_t source_position) { - CEL_ASSERT_NOT_NULL(expr); - CEL_ASSERT_GE(source_position, -1); - - if (source_position < -1) { - source_position = -1; - } - - expr->range.begin = source_position; - expr->range.end = -1; -} - -void cel_Expr_SetSourceRange(CEL_NONNULL(cel_Expr*) expr, - cel_SourceRange source_range) { - CEL_ASSERT_NOT_NULL(expr); - CEL_ASSERT_GE(source_range.begin, -1); - CEL_ASSERT_GE(source_range.end, -1); - CEL_ASSERT(source_range.begin <= source_range.end || source_range.end == -1); - - if (source_range.begin < -1) { - source_range.begin = -1; - } - if (source_range.end < -1) { - source_range.end = -1; - } - - expr->range = source_range; -} - -CEL_NULLABLE(cel_Expr*) -cel_Expr_Parent(CEL_NONNULL(const cel_Expr*) expr) { - CEL_ASSERT_NOT_NULL(expr); - - return expr->parent; -} - -size_t cel_Expr_Depth(CEL_NONNULL(const cel_Expr*) expr) { - CEL_ASSERT_NOT_NULL(expr); - - CEL_NULLABLE(const cel_Expr*) current = expr; - current = cel_Expr_Parent(current); - size_t depth = 0; - while (current != cel_nullptr) { - ++depth; - current = cel_Expr_Parent(current); - } - return depth; -} - -CEL_NULLABLE(const cel_Ref *) -cel_Expr_Ref(CEL_NONNULL(const cel_Expr *) expr) { - CEL_ASSERT_NOT_NULL(expr); - - return expr->ref; -} - -void cel_Expr_SetRef(CEL_NONNULL(cel_Expr *) expr, - CEL_NULLABLE(const cel_Ref *) ref) { - CEL_ASSERT_NOT_NULL(expr); - - expr->ref = ref; -} - -CEL_NONNULL(const cel_Type *) -cel_Expr_Type(CEL_NONNULL(const cel_Expr *) expr) { - CEL_ASSERT_NOT_NULL(expr); - - if (expr->type == cel_nullptr) { - return cel_DynType; - } - return expr->type; -} - -void cel_Expr_SetType(CEL_NONNULL(cel_Expr *) expr, - CEL_NONNULL(const cel_Type *) type) { - CEL_ASSERT_NOT_NULL(expr); - CEL_ASSERT_NOT_NULL(type); - - expr->type = type; -} - -CEL_NULLABLE(cel_UnspecifiedExpr*) -cel_UnspecifiedExpr_New(CEL_NONNULL(cel_Ast*) ast) { - CEL_ASSERT_NOT_NULL(ast); - - CEL_NULLABLE(cel_UnspecifiedExpr*) - expr = (CEL_NULLABLE(cel_UnspecifiedExpr*))cel_Arena_Malloc( - ast->arena, sizeof(cel_UnspecifiedExpr), cel_nullptr); - if (expr != cel_nullptr) { - memset(expr, 0, sizeof(*expr)); - expr->ast = ast; - expr->kind = cel_ExprKind_kUnspecified; - expr->range = cel_SourceRange(-1, -1); - } - return expr; -} - -CEL_NULLABLE(cel_IdentExpr*) -cel_IdentExpr_New(CEL_NONNULL(cel_Ast*) ast) { - CEL_ASSERT_NOT_NULL(ast); - - CEL_NULLABLE(cel_IdentExpr*) - expr = (CEL_NULLABLE(cel_IdentExpr*))cel_Arena_Malloc( - ast->arena, sizeof(cel_IdentExpr), cel_nullptr); - if (expr != cel_nullptr) { - memset(expr, 0, sizeof(*expr)); - expr->ast = ast; - expr->kind = cel_ExprKind_kIdent; - expr->range = cel_SourceRange(-1, -1); - } - return expr; -} - -cel_StringView cel_IdentExpr_Name(CEL_NONNULL(const cel_IdentExpr*) expr) { - CEL_ASSERT_NOT_NULL(expr); - - return expr->name; -} - -void cel_IdentExpr_SetName(CEL_NONNULL(cel_IdentExpr*) expr, - cel_StringView name) { - CEL_ASSERT_NOT_NULL(expr); - - expr->name = name; -} - -CEL_NULLABLE(cel_ConstExpr*) -cel_ConstExpr_New(CEL_NONNULL(cel_Ast*) ast) { - CEL_ASSERT_NOT_NULL(ast); - - CEL_NULLABLE(cel_ConstExpr*) - expr = (CEL_NULLABLE(cel_ConstExpr*))cel_Arena_Malloc( - ast->arena, sizeof(cel_ConstExpr), cel_nullptr); - if (expr != cel_nullptr) { - memset(expr, 0, sizeof(*expr)); - expr->ast = ast; - expr->kind = cel_ExprKind_kConst; - expr->range = cel_SourceRange(-1, -1); - } - return expr; -} - -CEL_NONNULL(const cel_Constant*) -cel_ConstExpr_Value(CEL_NONNULL(const cel_ConstExpr*) expr) { - CEL_ASSERT_NOT_NULL(expr); - - return &expr->value; -} - -CEL_NONNULL(cel_Constant*) -cel_ConstExpr_MutableValue(CEL_NONNULL(cel_ConstExpr*) expr) { - CEL_ASSERT_NOT_NULL(expr); - - return &expr->value; -} - -CEL_NULLABLE(cel_SelectExpr*) -cel_SelectExpr_New(CEL_NONNULL(cel_Ast*) ast) { - CEL_ASSERT_NOT_NULL(ast); - - CEL_NULLABLE(cel_SelectExpr*) - expr = (CEL_NULLABLE(cel_SelectExpr*))cel_Arena_Malloc( - ast->arena, sizeof(cel_SelectExpr), cel_nullptr); - if (expr != cel_nullptr) { - memset(expr, 0, sizeof(*expr)); - expr->ast = ast; - expr->kind = cel_ExprKind_kSelect; - expr->range = cel_SourceRange(-1, -1); - } - return expr; -} - -CEL_NULLABLE(cel_Expr*) -cel_SelectExpr_Operand(CEL_NONNULL(const cel_SelectExpr*) expr) { - CEL_ASSERT_NOT_NULL(expr); - - return _cel_Expr_Child(cel_Expr_UpCast(expr), expr->operand); -} - -CEL_NULLABLE(cel_Expr*) -cel_SelectExpr_SetOperand(CEL_NONNULL(cel_SelectExpr*) expr, - CEL_NULLABLE(cel_Expr*) operand) { - CEL_ASSERT_NOT_NULL(expr); - - return _cel_Expr_SetChild(cel_Expr_UpCast(expr), &expr->operand, operand); -} - -CEL_NULLABLE(cel_Expr*) -cel_SelectExpr_ReleaseOperand(CEL_NONNULL(cel_SelectExpr*) expr) { - CEL_ASSERT_NOT_NULL(expr); - - return _cel_Expr_ReleaseChild(cel_Expr_UpCast(expr), &expr->operand); -} - -cel_StringView cel_SelectExpr_Field(CEL_NONNULL(const cel_SelectExpr*) expr) { - CEL_ASSERT_NOT_NULL(expr); - - return expr->field; -} - -void cel_SelectExpr_SetField(CEL_NONNULL(cel_SelectExpr*) expr, - cel_StringView field) { - CEL_ASSERT_NOT_NULL(expr); - - expr->field = field; -} - -bool cel_SelectExpr_TestOnly(CEL_NONNULL(const cel_SelectExpr*) expr) { - CEL_ASSERT_NOT_NULL(expr); - - return expr->test_only; -} - -void cel_SelectExpr_SetTestOnly(CEL_NONNULL(cel_SelectExpr*) expr, - bool test_only) { - CEL_ASSERT_NOT_NULL(expr); - - expr->test_only = test_only; -} - -CEL_NULLABLE(cel_CallArgExpr*) -cel_CallArgExpr_New(CEL_NONNULL(cel_Ast*) ast) { - CEL_ASSERT_NOT_NULL(ast); - - CEL_NULLABLE(cel_CallArgExpr*) - expr = (CEL_NULLABLE(cel_CallArgExpr*))cel_Arena_Malloc( - ast->arena, sizeof(cel_CallArgExpr), cel_nullptr); - if (expr != cel_nullptr) { - memset(expr, 0, sizeof(*expr)); - expr->ast = ast; - expr->kind = cel_ExprKind_kCallArg; - expr->range = cel_SourceRange(-1, -1); - expr->index = -1; - } - return expr; -} - -CEL_NULLABLE(cel_CallExpr*) -cel_CallArgExpr_Parent(CEL_NONNULL(const cel_CallArgExpr*) expr) { - CEL_NULLABLE(cel_Expr*) parent = cel_Expr_Parent(cel_Expr_UpCast(expr)); - return parent != cel_nullptr ? cel_CallExpr_DownCast(parent) : cel_nullptr; -} - -ptrdiff_t cel_CallArgExpr_Index(CEL_NONNULL(const cel_CallArgExpr*) expr) { - CEL_ASSERT_NOT_NULL(expr); - - return expr->index; -} - -CEL_NULLABLE(cel_Expr*) -cel_CallArgExpr_Value(CEL_NONNULL(const cel_CallArgExpr*) expr) { - CEL_ASSERT_NOT_NULL(expr); - - return _cel_Expr_Child(cel_Expr_UpCast(expr), expr->value); -} - -CEL_NULLABLE(cel_Expr*) -cel_CallArgExpr_SetValue(CEL_NONNULL(cel_CallArgExpr*) expr, - CEL_NULLABLE(cel_Expr*) value) { - CEL_ASSERT_NOT_NULL(expr); - - return _cel_Expr_SetChild(cel_Expr_UpCast(expr), &expr->value, value); -} - -CEL_NULLABLE(cel_Expr*) -cel_CallArgExpr_ReleaseValue(CEL_NONNULL(cel_CallArgExpr*) expr) { - CEL_ASSERT_NOT_NULL(expr); - - return _cel_Expr_ReleaseChild(cel_Expr_UpCast(expr), &expr->value); -} - -CEL_NULLABLE(cel_CallExpr*) -cel_CallExpr_New(CEL_NONNULL(cel_Ast*) ast) { - CEL_ASSERT_NOT_NULL(ast); - - CEL_NULLABLE(cel_CallExpr*) - expr = (CEL_NULLABLE(cel_CallExpr*))cel_Arena_Malloc( - ast->arena, sizeof(cel_CallExpr), cel_nullptr); - if (expr != cel_nullptr) { - memset(expr, 0, sizeof(*expr)); - expr->ast = ast; - expr->kind = cel_ExprKind_kCall; - expr->range = cel_SourceRange(-1, -1); - } - return expr; -} - -CEL_NULLABLE(cel_Expr*) -cel_CallExpr_Target(CEL_NONNULL(const cel_CallExpr*) expr) { - CEL_ASSERT_NOT_NULL(expr); - - return _cel_Expr_Child(cel_Expr_UpCast(expr), expr->target); -} - -CEL_NULLABLE(cel_Expr*) -cel_CallExpr_SetTarget(CEL_NONNULL(cel_CallExpr*) expr, - CEL_NULLABLE(cel_Expr*) target) { - CEL_ASSERT_NOT_NULL(expr); - - return _cel_Expr_SetChild(cel_Expr_UpCast(expr), &expr->target, target); -} - -CEL_NULLABLE(cel_Expr*) -cel_CallExpr_ReleaseTarget(CEL_NONNULL(cel_CallExpr*) expr) { - CEL_ASSERT_NOT_NULL(expr); - - return _cel_Expr_ReleaseChild(cel_Expr_UpCast(expr), &expr->target); -} - -cel_StringView cel_CallExpr_Function(CEL_NONNULL(const cel_CallExpr*) expr) { - CEL_ASSERT_NOT_NULL(expr); - - return expr->function; -} - -void cel_CallExpr_SetFunction(CEL_NONNULL(cel_CallExpr*) expr, - cel_StringView function) { - CEL_ASSERT_NOT_NULL(expr); - - expr->function = function; -} - -void cel_CallExpr_AppendArg(CEL_NONNULL(cel_CallExpr*) expr, - CEL_NONNULL(cel_CallArgExpr*) arg) { - CEL_ASSERT_NOT_NULL(expr); - - _cel_Expr_LinkChild(cel_Expr_UpCast(expr), &expr->args_head, &expr->args_tail, - &expr->args, cel_nullptr, (_cel_ExprLink*)arg); -} - -void cel_CallExpr_PrependArg(CEL_NONNULL(cel_CallExpr*) expr, - CEL_NONNULL(cel_CallArgExpr*) arg) { - CEL_ASSERT_NOT_NULL(expr); - - _cel_Expr_LinkChild(cel_Expr_UpCast(expr), &expr->args_head, &expr->args_tail, - &expr->args, expr->args_head, (_cel_ExprLink*)arg); -} - -void cel_CallExpr_InsertArg(CEL_NONNULL(cel_CallExpr*) expr, - CEL_NULLABLE(cel_CallArgExpr*) before, - CEL_NONNULL(cel_CallArgExpr*) arg) { - CEL_ASSERT_NOT_NULL(expr); - - _cel_Expr_LinkChild(cel_Expr_UpCast(expr), &expr->args_head, &expr->args_tail, - &expr->args, (_cel_ExprLink*)before, (_cel_ExprLink*)arg); -} - -CEL_NONNULL(cel_CallArgExpr*) -cel_CallExpr_ReleaseArg(CEL_NONNULL(cel_CallExpr*) expr, - CEL_NONNULL(cel_CallArgExpr*) arg) { - CEL_ASSERT_NOT_NULL(expr); - - _cel_Expr_UnlinkChild(cel_Expr_UpCast(expr), &expr->args_head, - &expr->args_tail, &expr->args, (_cel_ExprLink*)arg); - return arg; -} - -CEL_NONNULL(cel_CallArgExpr*) -cel_CallExpr_Arg(CEL_NONNULL(const cel_CallExpr*) expr, size_t index) { - CEL_ASSERT_NOT_NULL(expr); - CEL_ASSERT_LT(index, expr->args); - - CEL_NULLABLE(_cel_ExprLink*) arg = expr->args_head; - for (; index > 0; --index) { - CEL_ASSERT_NOT_NULL(arg); - arg = arg->right; - } - CEL_ASSERT_NOT_NULL(arg); - CEL_ASSERT(arg->parent == cel_Expr_UpCast(expr)); - return (cel_CallArgExpr*)arg; -} - -size_t cel_CallExpr_Args(CEL_NONNULL(const cel_CallExpr*) expr, - CEL_NULLABLE(cel_CallArgExpr*) * cel_nullable head, - CEL_NULLABLE(cel_CallArgExpr*) * cel_nullable tail) { - CEL_ASSERT_NOT_NULL(expr); - - if (head != cel_nullptr) { - *head = (cel_CallArgExpr*)expr->args_head; - } - if (tail != cel_nullptr) { - *tail = (cel_CallArgExpr*)expr->args_tail; - } - return expr->args; -} - -CEL_NULLABLE(cel_CallArgExpr*) -cel_CallExpr_PrevArg(CEL_NULLABLE(const cel_CallArgExpr*) arg) { - if (arg != cel_nullptr) { - arg = (cel_CallArgExpr*)arg->left; - } - return (cel_CallArgExpr*)arg; -} - -CEL_NULLABLE(cel_CallArgExpr*) -cel_CallExpr_NextArg(CEL_NULLABLE(const cel_CallArgExpr*) arg) { - if (arg != cel_nullptr) { - arg = (cel_CallArgExpr*)arg->right; - } - return (cel_CallArgExpr*)arg; -} - -CEL_NULLABLE(cel_UnaryExpr*) -cel_UnaryExpr_New(CEL_NONNULL(cel_Ast*) ast) { - CEL_ASSERT_NOT_NULL(ast); - - CEL_NULLABLE(cel_UnaryExpr*) - expr = (CEL_NULLABLE(cel_UnaryExpr*))cel_Arena_Malloc( - ast->arena, sizeof(cel_UnaryExpr), cel_nullptr); - if (expr != cel_nullptr) { - memset(expr, 0, sizeof(*expr)); - expr->ast = ast; - expr->kind = cel_ExprKind_kUnary; - expr->range = cel_SourceRange(-1, -1); - } - return expr; -} - -cel_UnaryOp cel_UnaryExpr_Op(CEL_NONNULL(const cel_UnaryExpr*) expr) { - CEL_ASSERT_NOT_NULL(expr); - - return expr->op; -} - -void cel_UnaryExpr_SetOp(CEL_NONNULL(cel_UnaryExpr*) expr, cel_UnaryOp op) { - CEL_ASSERT_NOT_NULL(expr); - - expr->op = op; -} - -CEL_NULLABLE(cel_Expr*) -cel_UnaryExpr_Arg(CEL_NONNULL(const cel_UnaryExpr*) expr) { - CEL_ASSERT_NOT_NULL(expr); - - return _cel_Expr_Child(cel_Expr_UpCast(expr), expr->args[0]); -} - -CEL_NULLABLE(cel_Expr*) -cel_UnaryExpr_SetArg(CEL_NONNULL(cel_UnaryExpr*) expr, - CEL_NULLABLE(cel_Expr*) arg) { - CEL_ASSERT_NOT_NULL(expr); - - return _cel_Expr_SetChild(cel_Expr_UpCast(expr), &expr->args[0], arg); -} - -CEL_NULLABLE(cel_Expr*) -cel_UnaryExpr_ReleaseArg(CEL_NONNULL(cel_UnaryExpr*) expr) { - CEL_ASSERT_NOT_NULL(expr); - - return _cel_Expr_ReleaseChild(cel_Expr_UpCast(expr), &expr->args[0]); -} - -CEL_NULLABLE(cel_BinaryExpr*) -cel_BinaryExpr_New(CEL_NONNULL(cel_Ast*) ast) { - CEL_ASSERT_NOT_NULL(ast); - - CEL_NULLABLE(cel_BinaryExpr*) - expr = (CEL_NULLABLE(cel_BinaryExpr*))cel_Arena_Malloc( - ast->arena, sizeof(cel_BinaryExpr), cel_nullptr); - if (expr != cel_nullptr) { - memset(expr, 0, sizeof(*expr)); - expr->ast = ast; - expr->kind = cel_ExprKind_kBinary; - expr->range = cel_SourceRange(-1, -1); - } - return expr; -} - -cel_BinaryOp cel_BinaryExpr_Op(CEL_NONNULL(const cel_BinaryExpr*) expr) { - CEL_ASSERT_NOT_NULL(expr); - - return expr->op; -} - -void cel_BinaryExpr_SetOp(CEL_NONNULL(cel_BinaryExpr*) expr, cel_BinaryOp op) { - CEL_ASSERT_NOT_NULL(expr); - - expr->op = op; -} - -CEL_NULLABLE(cel_Expr*) -cel_BinaryExpr_Left(CEL_NONNULL(const cel_BinaryExpr*) expr) { - CEL_ASSERT_NOT_NULL(expr); - - return _cel_Expr_Child(cel_Expr_UpCast(expr), expr->args[0]); -} - -CEL_NULLABLE(cel_Expr*) -cel_BinaryExpr_SetLeft(CEL_NONNULL(cel_BinaryExpr*) expr, - CEL_NULLABLE(cel_Expr*) left) { - CEL_ASSERT_NOT_NULL(expr); - - return _cel_Expr_SetChild(cel_Expr_UpCast(expr), &expr->args[0], left); -} - -CEL_NULLABLE(cel_Expr*) -cel_BinaryExpr_ReleaseLeft(CEL_NONNULL(cel_BinaryExpr*) expr) { - CEL_ASSERT_NOT_NULL(expr); - - return _cel_Expr_ReleaseChild(cel_Expr_UpCast(expr), &expr->args[0]); -} - -CEL_NULLABLE(cel_Expr*) -cel_BinaryExpr_Right(CEL_NONNULL(const cel_BinaryExpr*) expr) { - CEL_ASSERT_NOT_NULL(expr); - - return _cel_Expr_Child(cel_Expr_UpCast(expr), expr->args[1]); -} - -CEL_NULLABLE(cel_Expr*) -cel_BinaryExpr_SetRight(CEL_NONNULL(cel_BinaryExpr*) expr, - CEL_NULLABLE(cel_Expr*) right) { - CEL_ASSERT_NOT_NULL(expr); - - return _cel_Expr_SetChild(cel_Expr_UpCast(expr), &expr->args[1], right); -} - -CEL_NULLABLE(cel_Expr*) -cel_BinaryExpr_ReleaseRight(CEL_NONNULL(cel_BinaryExpr*) expr) { - CEL_ASSERT_NOT_NULL(expr); - - return _cel_Expr_ReleaseChild(cel_Expr_UpCast(expr), &expr->args[1]); -} - -CEL_NULLABLE(cel_TernaryExpr*) -cel_TernaryExpr_New(CEL_NONNULL(cel_Ast*) ast) { - CEL_ASSERT_NOT_NULL(ast); - - CEL_NULLABLE(cel_TernaryExpr*) - expr = (CEL_NULLABLE(cel_TernaryExpr*))cel_Arena_Malloc( - ast->arena, sizeof(cel_TernaryExpr), cel_nullptr); - if (expr != cel_nullptr) { - memset(expr, 0, sizeof(*expr)); - expr->ast = ast; - expr->kind = cel_ExprKind_kTernary; - expr->range = cel_SourceRange(-1, -1); - } - return expr; -} - -cel_TernaryOp cel_TernaryExpr_Op(CEL_NONNULL(const cel_TernaryExpr*) expr) { - CEL_ASSERT_NOT_NULL(expr); - - return expr->op; -} - -void cel_TernaryExpr_SetOp(CEL_NONNULL(cel_TernaryExpr*) expr, - cel_TernaryOp op) { - CEL_ASSERT_NOT_NULL(expr); - - expr->op = op; -} - -CEL_NULLABLE(cel_Expr*) -cel_TernaryExpr_Condition(CEL_NONNULL(const cel_TernaryExpr*) expr) { - CEL_ASSERT_NOT_NULL(expr); - - return _cel_Expr_Child(cel_Expr_UpCast(expr), expr->args[0]); -} - -CEL_NULLABLE(cel_Expr*) -cel_TernaryExpr_SetCondition(CEL_NONNULL(cel_TernaryExpr*) expr, - CEL_NULLABLE(cel_Expr*) condition) { - CEL_ASSERT_NOT_NULL(expr); - - return _cel_Expr_SetChild(cel_Expr_UpCast(expr), &expr->args[0], condition); -} - -CEL_NULLABLE(cel_Expr*) -cel_TernaryExpr_ReleaseCondition(CEL_NONNULL(cel_TernaryExpr*) expr) { - CEL_ASSERT_NOT_NULL(expr); - - return _cel_Expr_ReleaseChild(cel_Expr_UpCast(expr), &expr->args[0]); -} - -CEL_NULLABLE(cel_Expr*) -cel_TernaryExpr_IfTrue(CEL_NONNULL(const cel_TernaryExpr*) expr) { - CEL_ASSERT_NOT_NULL(expr); - - return _cel_Expr_Child(cel_Expr_UpCast(expr), expr->args[1]); -} - -CEL_NULLABLE(cel_Expr*) -cel_TernaryExpr_SetIfTrue(CEL_NONNULL(cel_TernaryExpr*) expr, - CEL_NULLABLE(cel_Expr*) if_true) { - CEL_ASSERT_NOT_NULL(expr); - - return _cel_Expr_SetChild(cel_Expr_UpCast(expr), &expr->args[1], if_true); -} - -CEL_NULLABLE(cel_Expr*) -cel_TernaryExpr_ReleaseIfTrue(CEL_NONNULL(cel_TernaryExpr*) expr) { - CEL_ASSERT_NOT_NULL(expr); - - return _cel_Expr_ReleaseChild(cel_Expr_UpCast(expr), &expr->args[1]); -} - -CEL_NULLABLE(cel_Expr*) -cel_TernaryExpr_IfFalse(CEL_NONNULL(const cel_TernaryExpr*) expr) { - CEL_ASSERT_NOT_NULL(expr); - - return _cel_Expr_Child(cel_Expr_UpCast(expr), expr->args[2]); -} - -CEL_NULLABLE(cel_Expr*) -cel_TernaryExpr_SetIfFalse(CEL_NONNULL(cel_TernaryExpr*) expr, - CEL_NULLABLE(cel_Expr*) if_false) { - CEL_ASSERT_NOT_NULL(expr); - - return _cel_Expr_SetChild(cel_Expr_UpCast(expr), &expr->args[2], if_false); -} - -CEL_NULLABLE(cel_Expr*) -cel_TernaryExpr_ReleaseIfFalse(CEL_NONNULL(cel_TernaryExpr*) expr) { - CEL_ASSERT_NOT_NULL(expr); - - return _cel_Expr_ReleaseChild(cel_Expr_UpCast(expr), &expr->args[2]); -} - -CEL_NULLABLE(cel_ListElementExpr*) -cel_ListElementExpr_New(CEL_NONNULL(cel_Ast*) ast) { - CEL_ASSERT_NOT_NULL(ast); - - CEL_NULLABLE(cel_ListElementExpr*) - expr = (CEL_NULLABLE(cel_ListElementExpr*))cel_Arena_Malloc( - ast->arena, sizeof(cel_ListElementExpr), cel_nullptr); - if (expr != cel_nullptr) { - memset(expr, 0, sizeof(*expr)); - expr->ast = ast; - expr->kind = cel_ExprKind_kListElement; - expr->range = cel_SourceRange(-1, -1); - expr->index = -1; - } - return expr; -} - -CEL_NULLABLE(cel_ListExpr*) -cel_ListElementExpr_Parent(CEL_NONNULL(const cel_ListElementExpr*) expr) { - CEL_NULLABLE(cel_Expr*) parent = cel_Expr_Parent(cel_Expr_UpCast(expr)); - return parent != cel_nullptr ? cel_ListExpr_DownCast(parent) : cel_nullptr; -} - -ptrdiff_t cel_ListElementExpr_Index(CEL_NONNULL(const cel_ListElementExpr*) - expr) { - CEL_ASSERT_NOT_NULL(expr); - - return expr->index; -} - -CEL_NULLABLE(cel_Expr*) -cel_ListElementExpr_Value(CEL_NONNULL(const cel_ListElementExpr*) expr) { - CEL_ASSERT_NOT_NULL(expr); - - return _cel_Expr_Child(cel_Expr_UpCast(expr), expr->value); -} - -CEL_NULLABLE(cel_Expr*) -cel_ListElementExpr_SetValue(CEL_NONNULL(cel_ListElementExpr*) expr, - CEL_NULLABLE(cel_Expr*) value) { - CEL_ASSERT_NOT_NULL(expr); - - return _cel_Expr_SetChild(cel_Expr_UpCast(expr), &expr->value, value); -} - -CEL_NULLABLE(cel_Expr*) -cel_ListElementExpr_ReleaseValue(CEL_NONNULL(cel_ListElementExpr*) expr) { - CEL_ASSERT_NOT_NULL(expr); - - return _cel_Expr_ReleaseChild(cel_Expr_UpCast(expr), &expr->value); -} - -bool cel_ListElementExpr_Optional(CEL_NONNULL(const cel_ListElementExpr*) - expr) { - CEL_ASSERT_NOT_NULL(expr); - - return expr->optional; -} - -void cel_ListElementExpr_SetOptional(CEL_NONNULL(cel_ListElementExpr*) expr, - bool optional) { - CEL_ASSERT_NOT_NULL(expr); - - expr->optional = optional; -} - -CEL_NULLABLE(cel_ListExpr*) -cel_ListExpr_New(CEL_NONNULL(cel_Ast*) ast) { - CEL_ASSERT_NOT_NULL(ast); - - CEL_NULLABLE(cel_ListExpr*) - expr = (CEL_NULLABLE(cel_ListExpr*))cel_Arena_Malloc( - ast->arena, sizeof(cel_ListExpr), cel_nullptr); - if (expr != cel_nullptr) { - memset(expr, 0, sizeof(*expr)); - expr->ast = ast; - expr->kind = cel_ExprKind_kList; - expr->range = cel_SourceRange(-1, -1); - } - return expr; -} - -void cel_ListExpr_AppendElement(CEL_NONNULL(cel_ListExpr*) expr, - CEL_NONNULL(cel_ListElementExpr*) element) { - CEL_ASSERT_NOT_NULL(expr); - - _cel_Expr_LinkChild(cel_Expr_UpCast(expr), &expr->elems_head, - &expr->elems_tail, &expr->elems, cel_nullptr, - (_cel_ExprLink*)element); -} - -void cel_ListExpr_PrependElement(CEL_NONNULL(cel_ListExpr*) expr, - CEL_NONNULL(cel_ListElementExpr*) element) { - CEL_ASSERT_NOT_NULL(expr); - - _cel_Expr_LinkChild(cel_Expr_UpCast(expr), &expr->elems_head, - &expr->elems_tail, &expr->elems, expr->elems_head, - (_cel_ExprLink*)element); -} - -void cel_ListExpr_InsertElement(CEL_NONNULL(cel_ListExpr*) expr, - CEL_NULLABLE(cel_ListElementExpr*) before, - CEL_NONNULL(cel_ListElementExpr*) element) { - CEL_ASSERT_NOT_NULL(expr); - - _cel_Expr_LinkChild(cel_Expr_UpCast(expr), &expr->elems_head, - &expr->elems_tail, &expr->elems, (_cel_ExprLink*)before, - (_cel_ExprLink*)element); -} - -CEL_NONNULL(cel_ListElementExpr*) -cel_ListExpr_ReleaseElement(CEL_NONNULL(cel_ListExpr*) expr, - CEL_NONNULL(cel_ListElementExpr*) element) { - CEL_ASSERT_NOT_NULL(expr); - - _cel_Expr_UnlinkChild(cel_Expr_UpCast(expr), &expr->elems_head, - &expr->elems_tail, &expr->elems, - (_cel_ExprLink*)element); - return element; -} - -CEL_NONNULL(cel_ListElementExpr*) -cel_ListExpr_Element(CEL_NONNULL(const cel_ListExpr*) expr, size_t index) { - CEL_ASSERT_NOT_NULL(expr); - CEL_ASSERT_LT(index, expr->elems); - - CEL_NULLABLE(_cel_ExprLink*) element = expr->elems_head; - for (; index > 0; --index) { - CEL_ASSERT_NOT_NULL(element); - element = element->right; - } - CEL_ASSERT_NOT_NULL(element); - CEL_ASSERT(element->parent == cel_Expr_UpCast(expr)); - return (cel_ListElementExpr*)element; -} - -size_t cel_ListExpr_Elements(CEL_NONNULL(const cel_ListExpr*) expr, - CEL_NULLABLE(cel_ListElementExpr*) * - cel_nullable head, - CEL_NULLABLE(cel_ListElementExpr*) * - cel_nullable tail) { - CEL_ASSERT_NOT_NULL(expr); - - if (head != cel_nullptr) { - *head = (cel_ListElementExpr*)expr->elems_head; - } - if (tail != cel_nullptr) { - *tail = (cel_ListElementExpr*)expr->elems_tail; - } - return expr->elems; -} - -CEL_NULLABLE(cel_ListElementExpr*) -cel_ListExpr_PrevElement(CEL_NULLABLE(const cel_ListElementExpr*) element) { - if (element != cel_nullptr) { - element = (cel_ListElementExpr*)element->left; - } - return (CEL_NULLABLE(cel_ListElementExpr*))element; -} - -CEL_NULLABLE(cel_ListElementExpr*) -cel_ListExpr_NextElement(CEL_NULLABLE(const cel_ListElementExpr*) element) { - if (element != cel_nullptr) { - element = (cel_ListElementExpr*)element->right; - } - return (CEL_NULLABLE(cel_ListElementExpr*))element; -} - -CEL_NULLABLE(cel_MapEntryExpr*) -cel_MapEntryExpr_New(CEL_NONNULL(cel_Ast*) ast) { - CEL_ASSERT_NOT_NULL(ast); - - CEL_NULLABLE(cel_MapEntryExpr*) - expr = (CEL_NULLABLE(cel_MapEntryExpr*))cel_Arena_Malloc( - ast->arena, sizeof(cel_MapEntryExpr), cel_nullptr); - if (expr != cel_nullptr) { - memset(expr, 0, sizeof(*expr)); - expr->ast = ast; - expr->kind = cel_ExprKind_kMapEntry; - expr->range = cel_SourceRange(-1, -1); - expr->index = -1; - } - return expr; -} - -CEL_NULLABLE(cel_MapExpr*) -cel_MapEntryExpr_Parent(CEL_NONNULL(const cel_MapEntryExpr*) expr) { - CEL_NULLABLE(cel_Expr*) parent = cel_Expr_Parent(cel_Expr_UpCast(expr)); - return parent != cel_nullptr ? cel_MapExpr_DownCast(parent) : cel_nullptr; -} - -ptrdiff_t cel_MapEntryExpr_Index(CEL_NONNULL(const cel_MapEntryExpr*) expr) { - CEL_ASSERT_NOT_NULL(expr); - - return expr->index; -} - -CEL_NULLABLE(cel_Expr*) -cel_MapEntryExpr_Key(CEL_NONNULL(const cel_MapEntryExpr*) expr) { - CEL_ASSERT_NOT_NULL(expr); - - return _cel_Expr_Child(cel_Expr_UpCast(expr), expr->key); -} - -CEL_NULLABLE(cel_Expr*) -cel_MapEntryExpr_SetKey(CEL_NONNULL(cel_MapEntryExpr*) expr, - CEL_NULLABLE(cel_Expr*) key) { - CEL_ASSERT_NOT_NULL(expr); - - return _cel_Expr_SetChild(cel_Expr_UpCast(expr), &expr->key, key); -} - -CEL_NULLABLE(cel_Expr*) -cel_MapEntryExpr_ReleaseKey(CEL_NONNULL(cel_MapEntryExpr*) expr) { - CEL_ASSERT_NOT_NULL(expr); - - return _cel_Expr_ReleaseChild(cel_Expr_UpCast(expr), &expr->key); -} - -CEL_NULLABLE(cel_Expr*) -cel_MapEntryExpr_Value(CEL_NONNULL(const cel_MapEntryExpr*) expr) { - CEL_ASSERT_NOT_NULL(expr); - - return _cel_Expr_Child(cel_Expr_UpCast(expr), expr->value); -} - -CEL_NULLABLE(cel_Expr*) -cel_MapEntryExpr_SetValue(CEL_NONNULL(cel_MapEntryExpr*) expr, - CEL_NULLABLE(cel_Expr*) value) { - CEL_ASSERT_NOT_NULL(expr); - - return _cel_Expr_SetChild(cel_Expr_UpCast(expr), &expr->value, value); -} - -CEL_NULLABLE(cel_Expr*) -cel_MapEntryExpr_ReleaseValue(CEL_NONNULL(cel_MapEntryExpr*) expr) { - CEL_ASSERT_NOT_NULL(expr); - - return _cel_Expr_ReleaseChild(cel_Expr_UpCast(expr), &expr->value); -} - -bool cel_MapEntryExpr_Optional(CEL_NONNULL(const cel_MapEntryExpr*) expr) { - CEL_ASSERT_NOT_NULL(expr); - - return expr->optional; -} - -void cel_MapEntryExpr_SetOptional(CEL_NONNULL(cel_MapEntryExpr*) expr, - bool optional) { - CEL_ASSERT_NOT_NULL(expr); - - expr->optional = optional; -} - -CEL_NULLABLE(cel_MapExpr*) -cel_MapExpr_New(CEL_NONNULL(cel_Ast*) ast) { - CEL_ASSERT_NOT_NULL(ast); - - CEL_NULLABLE(cel_MapExpr*) - expr = (CEL_NULLABLE(cel_MapExpr*))cel_Arena_Malloc( - ast->arena, sizeof(cel_MapExpr), cel_nullptr); - if (expr != cel_nullptr) { - memset(expr, 0, sizeof(*expr)); - expr->ast = ast; - expr->kind = cel_ExprKind_kMap; - expr->range = cel_SourceRange(-1, -1); - } - return expr; -} - -void cel_MapExpr_AppendEntry(CEL_NONNULL(cel_MapExpr*) expr, - CEL_NONNULL(cel_MapEntryExpr*) entry) { - CEL_ASSERT_NOT_NULL(expr); - - _cel_Expr_LinkChild(cel_Expr_UpCast(expr), &expr->ents_head, &expr->ents_tail, - &expr->ents, cel_nullptr, (_cel_ExprLink*)entry); -} - -void cel_MapExpr_PrependEntry(CEL_NONNULL(cel_MapExpr*) expr, - CEL_NONNULL(cel_MapEntryExpr*) entry) { - CEL_ASSERT_NOT_NULL(expr); - - _cel_Expr_LinkChild(cel_Expr_UpCast(expr), &expr->ents_head, &expr->ents_tail, - &expr->ents, expr->ents_head, (_cel_ExprLink*)entry); -} - -void cel_MapExpr_InsertEntry(CEL_NONNULL(cel_MapExpr*) expr, - CEL_NULLABLE(cel_MapEntryExpr*) before, - CEL_NONNULL(cel_MapEntryExpr*) entry) { - CEL_ASSERT_NOT_NULL(expr); - - _cel_Expr_LinkChild(cel_Expr_UpCast(expr), &expr->ents_head, &expr->ents_tail, - &expr->ents, (_cel_ExprLink*)before, - (_cel_ExprLink*)entry); -} - -CEL_NONNULL(cel_MapEntryExpr*) -cel_MapExpr_ReleaseEntry(CEL_NONNULL(cel_MapExpr*) expr, - CEL_NONNULL(cel_MapEntryExpr*) entry) { - CEL_ASSERT_NOT_NULL(expr); - - _cel_Expr_UnlinkChild(cel_Expr_UpCast(expr), &expr->ents_head, - &expr->ents_tail, &expr->ents, (_cel_ExprLink*)entry); - return entry; -} - -CEL_NONNULL(cel_MapEntryExpr*) -cel_MapExpr_Entry(CEL_NONNULL(const cel_MapExpr*) expr, size_t index) { - CEL_ASSERT_NOT_NULL(expr); - CEL_ASSERT_LT(index, expr->ents); - - CEL_NULLABLE(_cel_ExprLink*) element = expr->ents_head; - for (; index > 0; --index) { - CEL_ASSERT_NOT_NULL(element); - element = element->right; - } - CEL_ASSERT_NOT_NULL(element); - CEL_ASSERT(element->parent == cel_Expr_UpCast(expr)); - return (cel_MapEntryExpr*)element; -} - -size_t cel_MapExpr_Entries(CEL_NONNULL(const cel_MapExpr*) expr, - CEL_NULLABLE(cel_MapEntryExpr*) * cel_nullable head, - CEL_NULLABLE(cel_MapEntryExpr*) * - cel_nullable tail) { - CEL_ASSERT_NOT_NULL(expr); - - if (head != cel_nullptr) { - *head = (cel_MapEntryExpr*)expr->ents_head; - } - if (tail != cel_nullptr) { - *tail = (cel_MapEntryExpr*)expr->ents_tail; - } - return expr->ents; -} - -CEL_NULLABLE(cel_MapEntryExpr*) -cel_MapExpr_PrevEntry(CEL_NULLABLE(const cel_MapEntryExpr*) entry) { - if (entry != cel_nullptr) { - entry = (cel_MapEntryExpr*)entry->left; - } - return (CEL_NULLABLE(cel_MapEntryExpr*))entry; -} - -CEL_NULLABLE(cel_MapEntryExpr*) -cel_MapExpr_NextEntry(CEL_NULLABLE(const cel_MapEntryExpr*) entry) { - if (entry != cel_nullptr) { - entry = (cel_MapEntryExpr*)entry->right; - } - return (CEL_NULLABLE(cel_MapEntryExpr*))entry; -} - -CEL_NULLABLE(cel_StructFieldExpr*) -cel_StructFieldExpr_New(CEL_NONNULL(cel_Ast*) ast) { - CEL_ASSERT_NOT_NULL(ast); - - CEL_NULLABLE(cel_StructFieldExpr*) - expr = (CEL_NULLABLE(cel_StructFieldExpr*))cel_Arena_Malloc( - ast->arena, sizeof(cel_StructFieldExpr), cel_nullptr); - if (expr != cel_nullptr) { - memset(expr, 0, sizeof(*expr)); - expr->ast = ast; - expr->kind = cel_ExprKind_kStructField; - expr->range = cel_SourceRange(-1, -1); - expr->index = -1; - } - return expr; -} - -CEL_NULLABLE(cel_StructExpr*) -cel_StructFieldExpr_Parent(CEL_NONNULL(const cel_StructFieldExpr*) expr) { - CEL_NULLABLE(cel_Expr*) parent = cel_Expr_Parent(cel_Expr_UpCast(expr)); - return parent != cel_nullptr ? cel_StructExpr_DownCast(parent) : cel_nullptr; -} - -ptrdiff_t cel_StructFieldExpr_Index(CEL_NONNULL(const cel_StructFieldExpr*) - expr) { - CEL_ASSERT_NOT_NULL(expr); - - return expr->index; -} - -cel_StringView cel_StructFieldExpr_Name(CEL_NONNULL(const cel_StructFieldExpr*) - expr) { - CEL_ASSERT_NOT_NULL(expr); - - return expr->name; -} - -void cel_StructFieldExpr_SetName(CEL_NONNULL(cel_StructFieldExpr*) expr, - cel_StringView name) { - CEL_ASSERT_NOT_NULL(expr); - - expr->name = name; -} - -CEL_NULLABLE(cel_Expr*) -cel_StructFieldExpr_Value(CEL_NONNULL(const cel_StructFieldExpr*) expr) { - CEL_ASSERT_NOT_NULL(expr); - - return _cel_Expr_Child(cel_Expr_UpCast(expr), expr->value); -} - -CEL_NULLABLE(cel_Expr*) -cel_StructFieldExpr_SetValue(CEL_NONNULL(cel_StructFieldExpr*) expr, - CEL_NULLABLE(cel_Expr*) value) { - CEL_ASSERT_NOT_NULL(expr); - - return _cel_Expr_SetChild(cel_Expr_UpCast(expr), &expr->value, value); -} - -CEL_NULLABLE(cel_Expr*) -cel_StructFieldExpr_ReleaseValue(CEL_NONNULL(cel_StructFieldExpr*) expr) { - CEL_ASSERT_NOT_NULL(expr); - - return _cel_Expr_ReleaseChild(cel_Expr_UpCast(expr), &expr->value); -} - -bool cel_StructFieldExpr_Optional(CEL_NONNULL(const cel_StructFieldExpr*) - expr) { - CEL_ASSERT_NOT_NULL(expr); - - return expr->optional; -} - -void cel_StructFieldExpr_SetOptional(CEL_NONNULL(cel_StructFieldExpr*) expr, - bool optional) { - CEL_ASSERT_NOT_NULL(expr); - - expr->optional = optional; -} - -CEL_NULLABLE(cel_StructExpr*) -cel_StructExpr_New(CEL_NONNULL(cel_Ast*) ast) { - CEL_ASSERT_NOT_NULL(ast); - - CEL_NULLABLE(cel_StructExpr*) - expr = (CEL_NULLABLE(cel_StructExpr*))cel_Arena_Malloc( - ast->arena, sizeof(cel_StructExpr), cel_nullptr); - if (expr != cel_nullptr) { - memset(expr, 0, sizeof(*expr)); - expr->ast = ast; - expr->kind = cel_ExprKind_kStruct; - expr->range = cel_SourceRange(-1, -1); - } - return expr; -} - -cel_StringView cel_StructExpr_Name(CEL_NONNULL(const cel_StructExpr*) expr) { - CEL_ASSERT_NOT_NULL(expr); - - return expr->name; -} - -void cel_StructExpr_SetName(CEL_NONNULL(cel_StructExpr*) expr, - cel_StringView name) { - CEL_ASSERT_NOT_NULL(expr); - - expr->name = name; -} - -void cel_StructExpr_AppendField(CEL_NONNULL(cel_StructExpr*) expr, - CEL_NONNULL(cel_StructFieldExpr*) field) { - CEL_ASSERT_NOT_NULL(expr); - - _cel_Expr_LinkChild(cel_Expr_UpCast(expr), &expr->flds_head, &expr->flds_tail, - &expr->flds, cel_nullptr, (_cel_ExprLink*)field); -} - -void cel_StructExpr_PrependField(CEL_NONNULL(cel_StructExpr*) expr, - CEL_NONNULL(cel_StructFieldExpr*) field) { - CEL_ASSERT_NOT_NULL(expr); - - _cel_Expr_LinkChild(cel_Expr_UpCast(expr), &expr->flds_head, &expr->flds_tail, - &expr->flds, expr->flds_head, (_cel_ExprLink*)field); -} - -void cel_StructExpr_InsertField(CEL_NONNULL(cel_StructExpr*) expr, - CEL_NULLABLE(cel_StructFieldExpr*) before, - CEL_NONNULL(cel_StructFieldExpr*) field) { - CEL_ASSERT_NOT_NULL(expr); - - _cel_Expr_LinkChild(cel_Expr_UpCast(expr), &expr->flds_head, &expr->flds_tail, - &expr->flds, (_cel_ExprLink*)before, - (_cel_ExprLink*)field); -} - -CEL_NONNULL(cel_StructFieldExpr*) -cel_StructExpr_ReleaseField(CEL_NONNULL(cel_StructExpr*) expr, - CEL_NONNULL(cel_StructFieldExpr*) field) { - CEL_ASSERT_NOT_NULL(expr); - - _cel_Expr_UnlinkChild(cel_Expr_UpCast(expr), &expr->flds_head, - &expr->flds_tail, &expr->flds, (_cel_ExprLink*)field); - return field; -} - -CEL_NONNULL(cel_StructFieldExpr*) -cel_StructExpr_Field(CEL_NONNULL(const cel_StructExpr*) expr, size_t index) { - CEL_ASSERT_NOT_NULL(expr); - CEL_ASSERT_LT(index, expr->flds); - - CEL_NULLABLE(_cel_ExprLink*) element = expr->flds_head; - for (; index > 0; --index) { - CEL_ASSERT_NOT_NULL(element); - element = element->right; - } - CEL_ASSERT_NOT_NULL(element); - CEL_ASSERT(element->parent == cel_Expr_UpCast(expr)); - return (cel_StructFieldExpr*)element; -} - -size_t cel_StructExpr_Fields(CEL_NONNULL(const cel_StructExpr*) expr, - CEL_NULLABLE(cel_StructFieldExpr*) * - cel_nullable head, - CEL_NULLABLE(cel_StructFieldExpr*) * - cel_nullable tail) { - CEL_ASSERT_NOT_NULL(expr); - - if (head != cel_nullptr) { - *head = (cel_StructFieldExpr*)expr->flds_head; - } - if (tail != cel_nullptr) { - *tail = (cel_StructFieldExpr*)expr->flds_tail; - } - return expr->flds; -} - -CEL_NULLABLE(cel_StructFieldExpr*) -cel_StructExpr_PrevField(CEL_NULLABLE(const cel_StructFieldExpr*) field) { - if (field != cel_nullptr) { - field = (cel_StructFieldExpr*)field->left; - } - return (CEL_NULLABLE(cel_StructFieldExpr*))field; -} - -CEL_NULLABLE(cel_StructFieldExpr*) -cel_StructExpr_NextField(CEL_NULLABLE(const cel_StructFieldExpr*) field) { - if (field != cel_nullptr) { - field = (cel_StructFieldExpr*)field->right; - } - return (CEL_NULLABLE(cel_StructFieldExpr*))field; -} - -CEL_NULLABLE(cel_ComprehensionExpr*) -cel_ComprehensionExpr_New(CEL_NONNULL(cel_Ast*) ast) { - CEL_ASSERT_NOT_NULL(ast); - - CEL_NULLABLE(cel_ComprehensionExpr*) - expr = (CEL_NULLABLE(cel_ComprehensionExpr*))cel_Arena_Malloc( - ast->arena, sizeof(cel_ComprehensionExpr), cel_nullptr); - if (expr != cel_nullptr) { - memset(expr, 0, sizeof(*expr)); - expr->ast = ast; - expr->kind = cel_ExprKind_kComprehension; - expr->range = cel_SourceRange(-1, -1); - } - return expr; -} - -cel_StringView cel_ComprehensionExpr_IterVar( - CEL_NONNULL(const cel_ComprehensionExpr*) expr) { - CEL_ASSERT_NOT_NULL(expr); - - return expr->iter_var; -} - -void cel_ComprehensionExpr_SetIterVar(CEL_NONNULL(cel_ComprehensionExpr*) expr, - cel_StringView iter_var) { - CEL_ASSERT_NOT_NULL(expr); - - expr->iter_var = iter_var; -} - -cel_StringView cel_ComprehensionExpr_IterVar2( - CEL_NONNULL(const cel_ComprehensionExpr*) expr) { - CEL_ASSERT_NOT_NULL(expr); - - return expr->iter_var2; -} - -void cel_ComprehensionExpr_SetIterVar2(CEL_NONNULL(cel_ComprehensionExpr*) expr, - cel_StringView iter_var2) { - CEL_ASSERT_NOT_NULL(expr); - - expr->iter_var2 = iter_var2; -} - -CEL_NULLABLE(cel_Expr*) -cel_ComprehensionExpr_IterRange(CEL_NONNULL(const cel_ComprehensionExpr*) - expr) { - CEL_ASSERT_NOT_NULL(expr); - - return _cel_Expr_Child(cel_Expr_UpCast(expr), expr->iter_range); -} - -CEL_NULLABLE(cel_Expr*) -cel_ComprehensionExpr_SetIterRange(CEL_NONNULL(cel_ComprehensionExpr*) expr, - CEL_NULLABLE(cel_Expr*) iter_range) { - CEL_ASSERT_NOT_NULL(expr); - - return _cel_Expr_SetChild(cel_Expr_UpCast(expr), &expr->iter_range, - iter_range); -} - -CEL_NULLABLE(cel_Expr*) -cel_ComprehensionExpr_ReleaseIterRange(CEL_NONNULL(cel_ComprehensionExpr*) - expr) { - CEL_ASSERT_NOT_NULL(expr); - - return _cel_Expr_ReleaseChild(cel_Expr_UpCast(expr), &expr->iter_range); -} - -cel_StringView cel_ComprehensionExpr_AccuVar( - CEL_NONNULL(const cel_ComprehensionExpr*) expr) { - CEL_ASSERT_NOT_NULL(expr); - - return expr->accu_var; -} - -void cel_ComprehensionExpr_SetAccuVar(CEL_NONNULL(cel_ComprehensionExpr*) expr, - cel_StringView accu_var) { - CEL_ASSERT_NOT_NULL(expr); - - expr->accu_var = accu_var; -} - -CEL_NULLABLE(cel_Expr*) -cel_ComprehensionExpr_AccuInit(CEL_NONNULL(const cel_ComprehensionExpr*) expr) { - CEL_ASSERT_NOT_NULL(expr); - - return _cel_Expr_Child(cel_Expr_UpCast(expr), expr->accu_init); -} - -CEL_NULLABLE(cel_Expr*) -cel_ComprehensionExpr_SetAccuInit(CEL_NONNULL(cel_ComprehensionExpr*) expr, - CEL_NULLABLE(cel_Expr*) accu_init) { - CEL_ASSERT_NOT_NULL(expr); - - return _cel_Expr_SetChild(cel_Expr_UpCast(expr), &expr->accu_init, accu_init); -} - -CEL_NULLABLE(cel_Expr*) -cel_ComprehensionExpr_ReleaseAccuInit(CEL_NONNULL(cel_ComprehensionExpr*) - expr) { - CEL_ASSERT_NOT_NULL(expr); - - return _cel_Expr_ReleaseChild(cel_Expr_UpCast(expr), &expr->accu_init); -} - -CEL_NULLABLE(cel_Expr*) -cel_ComprehensionExpr_LoopCondition(CEL_NONNULL(const cel_ComprehensionExpr*) - expr) { - CEL_ASSERT_NOT_NULL(expr); - - return _cel_Expr_Child(cel_Expr_UpCast(expr), expr->loop_condition); -} - -CEL_NULLABLE(cel_Expr*) -cel_ComprehensionExpr_SetLoopCondition(CEL_NONNULL(cel_ComprehensionExpr*) expr, - CEL_NULLABLE(cel_Expr*) loop_condition) { - CEL_ASSERT_NOT_NULL(expr); - - return _cel_Expr_SetChild(cel_Expr_UpCast(expr), &expr->loop_condition, - loop_condition); -} - -CEL_NULLABLE(cel_Expr*) -cel_ComprehensionExpr_ReleaseLoopCondition(CEL_NONNULL(cel_ComprehensionExpr*) - expr) { - CEL_ASSERT_NOT_NULL(expr); - - return _cel_Expr_ReleaseChild(cel_Expr_UpCast(expr), &expr->loop_condition); -} - -CEL_NULLABLE(cel_Expr*) -cel_ComprehensionExpr_LoopStep(CEL_NONNULL(const cel_ComprehensionExpr*) expr) { - CEL_ASSERT_NOT_NULL(expr); - - return _cel_Expr_Child(cel_Expr_UpCast(expr), expr->loop_step); -} - -CEL_NULLABLE(cel_Expr*) -cel_ComprehensionExpr_SetLoopStep(CEL_NONNULL(cel_ComprehensionExpr*) expr, - CEL_NULLABLE(cel_Expr*) loop_step) { - CEL_ASSERT_NOT_NULL(expr); - - return _cel_Expr_SetChild(cel_Expr_UpCast(expr), &expr->loop_step, loop_step); -} - -CEL_NULLABLE(cel_Expr*) -cel_ComprehensionExpr_ReleaseLoopStep(CEL_NONNULL(cel_ComprehensionExpr*) - expr) { - CEL_ASSERT_NOT_NULL(expr); - - return _cel_Expr_ReleaseChild(cel_Expr_UpCast(expr), &expr->loop_step); -} - -CEL_NULLABLE(cel_Expr*) -cel_ComprehensionExpr_Result(CEL_NONNULL(const cel_ComprehensionExpr*) expr) { - CEL_ASSERT_NOT_NULL(expr); - - return _cel_Expr_Child(cel_Expr_UpCast(expr), expr->result); -} - -CEL_NULLABLE(cel_Expr*) -cel_ComprehensionExpr_SetResult(CEL_NONNULL(cel_ComprehensionExpr*) expr, - CEL_NULLABLE(cel_Expr*) result) { - CEL_ASSERT_NOT_NULL(expr); - - return _cel_Expr_SetChild(cel_Expr_UpCast(expr), &expr->result, result); -} - -CEL_NULLABLE(cel_Expr*) -cel_ComprehensionExpr_ReleaseResult(CEL_NONNULL(cel_ComprehensionExpr*) expr) { - CEL_ASSERT_NOT_NULL(expr); - - return _cel_Expr_ReleaseChild(cel_Expr_UpCast(expr), &expr->result); -} diff --git a/cel-c/ast_proto.c b/cel-c/ast_proto.c deleted file mode 100644 index f9cb3b1..0000000 --- a/cel-c/ast_proto.c +++ /dev/null @@ -1,667 +0,0 @@ -// Copyright 2025 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "cel-c/ast_proto.h" - -#include -#include -#include -#include - -#include "cel/expr/checked.upb.h" -#include "cel/expr/syntax.upb.h" -#include "cel-c/arena.h" -#include "cel-c/assert.h" -#include "cel-c/ast.h" -#include "cel-c/config.h" -#include "cel-c/constant_proto.h" -#include "cel-c/operators.h" -#include "cel-c/ref.h" -#include "cel-c/ref_proto.h" -#include "cel-c/status.h" -#include "cel-c/string_view.h" -#include "cel-c/type.h" -#include "cel-c/type_proto.h" -#include "cel-c/src/malloc.h" -#include "cel-c/src/setjmp.h" - -typedef struct { - CEL_NONNULL(cel_Ast*) ast; - CEL_NONNULL(cel_Arena*) arena; - CEL_NONNULL(cel_Status*) status; - CEL_NONNULL(const cel_expr_CheckedExpr*) checked_expr; - CEL_NULLABLE(const cel_expr_SourceInfo*) source_info; - _cel_jmp_buf jmp; -} _cel_AstFromProtoState; - -static int64_t _cel_AstFromProto_CheckId(CEL_NONNULL(_cel_AstFromProtoState*) - state, - cel_ExprId id) { - if (CEL_UNLIKELY(id < 0)) { - cel_InvalidArgumentStatusF(state->status, - "cel: expected google.api.expr.Expr.id to be " - "greater than or equal to 0: %" PRId64, - id); - _cel_longjmp(state->jmp); - } - return id; -} - -static cel_StringView _cel_AstFromProto_StrDup( - CEL_NONNULL(_cel_AstFromProtoState*) state, cel_StringView in) { - cel_StringView out; - if (CEL_UNLIKELY(!cel_Arena_StrDup(state->arena, &out, in))) { - cel_OutOfMemoryStatus(state->status); - _cel_longjmp(state->jmp); - } - return out; -} - -static void _cel_AstFromProto_UpdatePosition( - CEL_NONNULL(_cel_AstFromProtoState*) state, CEL_NONNULL(cel_Expr*) expr) { - if (state->source_info != cel_nullptr) { - int64_t id = cel_Expr_Id(expr); - if (id != 0) { - int32_t position; - if (cel_expr_SourceInfo_positions_get(state->source_info, id, - &position)) { - if (CEL_UNLIKELY(position < -1)) { - cel_InvalidArgumentStatusF( - state->status, - "cel: expected " - "google.api.expr.SourceInfo.positions[%" PRId64 - "] " - "to be greater than or equal to -1: %" PRId32, - id, position); - _cel_longjmp(state->jmp); - } - cel_Expr_SetSourcePosition(expr, position); - } - } - } -} - -static void _cel_AstFromProto_SetType(CEL_NONNULL(_cel_AstFromProtoState*) - state, - CEL_NONNULL(cel_Expr*) expr) { - int64_t id = cel_Expr_Id(expr); - if (id != 0) { - const cel_expr_Type* in_type; - if (cel_expr_CheckedExpr_type_map_get( - state->checked_expr, id, (cel_expr_Type**)&in_type)) { - const cel_Type* type = - cel_Type_FromProto(in_type, state->arena, state->status); - if (CEL_UNLIKELY(type == cel_nullptr)) { - _cel_longjmp(state->jmp); - } - cel_Expr_SetType(expr, type); - } - } -} - -static void _cel_AstFromProto_SetRef(CEL_NONNULL(_cel_AstFromProtoState*) state, - CEL_NONNULL(cel_Expr*) expr) { - int64_t id = cel_Expr_Id(expr); - if (id != 0) { - const cel_expr_Reference* in_ref; - if (cel_expr_CheckedExpr_reference_map_get( - state->checked_expr, id, (cel_expr_Reference**)&in_ref)) { - const cel_Ref* ref = - cel_Ref_FromProto(in_ref, state->arena, state->status); - if (CEL_UNLIKELY(ref == cel_nullptr)) { - _cel_longjmp(state->jmp); - } - cel_Expr_SetRef(expr, ref); - } - } -} - -static CEL_NONNULL(cel_Expr*) - _cel_AstFromProto_Expr(CEL_NONNULL(_cel_AstFromProtoState*) state, - CEL_NONNULL(const cel_expr_Expr*) in); - -static CEL_NONNULL(cel_Expr*) - _cel_AstFromProto_UnspecifiedExpr(CEL_NONNULL(_cel_AstFromProtoState*) - state, - int64_t id) { - _cel_AstFromProto_CheckId(state, id); - CEL_NULLABLE(cel_UnspecifiedExpr*) expr = cel_UnspecifiedExpr_New(state->ast); - if (CEL_UNLIKELY(expr == cel_nullptr)) { - cel_OutOfMemoryStatus(state->status); - _cel_longjmp(state->jmp); - } - cel_Expr_SetId(cel_Expr_UpCast(expr), id); - _cel_AstFromProto_UpdatePosition(state, cel_Expr_UpCast(expr)); - _cel_AstFromProto_SetType(state, cel_Expr_UpCast(expr)); - _cel_AstFromProto_SetRef(state, cel_Expr_UpCast(expr)); - return cel_Expr_UpCast(expr); -} - -static CEL_NONNULL(cel_Expr*) - _cel_AstFromProto_IdentExpr(CEL_NONNULL(_cel_AstFromProtoState*) state, - int64_t id, - CEL_NONNULL(const cel_expr_Expr_Ident*) - in) { - _cel_AstFromProto_CheckId(state, id); - CEL_NULLABLE(cel_IdentExpr*) expr = cel_IdentExpr_New(state->ast); - if (CEL_UNLIKELY(expr == cel_nullptr)) { - cel_OutOfMemoryStatus(state->status); - _cel_longjmp(state->jmp); - } - cel_Expr_SetId(cel_Expr_UpCast(expr), id); - _cel_AstFromProto_UpdatePosition(state, cel_Expr_UpCast(expr)); - _cel_AstFromProto_SetType(state, cel_Expr_UpCast(expr)); - _cel_AstFromProto_SetRef(state, cel_Expr_UpCast(expr)); - cel_IdentExpr_SetName(expr, _cel_AstFromProto_StrDup( - state, cel_expr_Expr_Ident_name(in))); - return cel_Expr_UpCast(expr); -} - -static CEL_NONNULL(cel_Expr*) - _cel_AstFromProto_ConstExpr(CEL_NONNULL(_cel_AstFromProtoState*) state, - int64_t id, - CEL_NONNULL(const cel_expr_Constant*) - in) { - _cel_AstFromProto_CheckId(state, id); - CEL_NULLABLE(cel_ConstExpr*) expr = cel_ConstExpr_New(state->ast); - if (CEL_UNLIKELY(expr == cel_nullptr)) { - cel_OutOfMemoryStatus(state->status); - _cel_longjmp(state->jmp); - } - cel_Expr_SetId(cel_Expr_UpCast(expr), id); - _cel_AstFromProto_UpdatePosition(state, cel_Expr_UpCast(expr)); - _cel_AstFromProto_SetType(state, cel_Expr_UpCast(expr)); - _cel_AstFromProto_SetRef(state, cel_Expr_UpCast(expr)); - if (CEL_UNLIKELY(!cel_Constant_FromProto(cel_ConstExpr_MutableValue(expr), in, - state->arena, state->status))) { - _cel_longjmp(state->jmp); - } - return cel_Expr_UpCast(expr); -} - -static CEL_NONNULL(cel_Expr*) - _cel_AstFromProto_SelectExpr(CEL_NONNULL(_cel_AstFromProtoState*) state, - int64_t id, - CEL_NONNULL(const cel_expr_Expr_Select*) - in) { - _cel_AstFromProto_CheckId(state, id); - CEL_NULLABLE(cel_SelectExpr*) expr = cel_SelectExpr_New(state->ast); - if (CEL_UNLIKELY(expr == cel_nullptr)) { - cel_OutOfMemoryStatus(state->status); - _cel_longjmp(state->jmp); - } - cel_Expr_SetId(cel_Expr_UpCast(expr), id); - _cel_AstFromProto_UpdatePosition(state, cel_Expr_UpCast(expr)); - _cel_AstFromProto_SetType(state, cel_Expr_UpCast(expr)); - _cel_AstFromProto_SetRef(state, cel_Expr_UpCast(expr)); - if (cel_expr_Expr_Select_has_operand(in)) { - cel_SelectExpr_SetOperand( - expr, - _cel_AstFromProto_Expr(state, cel_expr_Expr_Select_operand(in))); - } - cel_SelectExpr_SetField( - expr, - _cel_AstFromProto_StrDup(state, cel_expr_Expr_Select_field(in))); - cel_SelectExpr_SetTestOnly(expr, cel_expr_Expr_Select_test_only(in)); - return cel_Expr_UpCast(expr); -} - -static CEL_NONNULL(cel_Expr*) - _cel_AstFromProto_UnaryExpr(CEL_NONNULL(_cel_AstFromProtoState*) state, - int64_t id, cel_UnaryOp op, - CEL_NONNULL(const cel_expr_Expr*) arg) { - _cel_AstFromProto_CheckId(state, id); - CEL_NULLABLE(cel_UnaryExpr*) expr = cel_UnaryExpr_New(state->ast); - if (CEL_UNLIKELY(expr == cel_nullptr)) { - cel_OutOfMemoryStatus(state->status); - _cel_longjmp(state->jmp); - } - cel_Expr_SetId(cel_Expr_UpCast(expr), id); - _cel_AstFromProto_UpdatePosition(state, cel_Expr_UpCast(expr)); - _cel_AstFromProto_SetType(state, cel_Expr_UpCast(expr)); - _cel_AstFromProto_SetRef(state, cel_Expr_UpCast(expr)); - cel_UnaryExpr_SetOp(expr, op); - cel_UnaryExpr_SetArg(expr, _cel_AstFromProto_Expr(state, arg)); - return cel_Expr_UpCast(expr); -} - -static CEL_NONNULL(cel_Expr*) - _cel_AstFromProto_BinaryExpr(CEL_NONNULL(_cel_AstFromProtoState*) state, - int64_t id, cel_BinaryOp op, - CEL_NONNULL(const cel_expr_Expr*) left, - CEL_NONNULL(const cel_expr_Expr*) - right) { - _cel_AstFromProto_CheckId(state, id); - CEL_NULLABLE(cel_BinaryExpr*) expr = cel_BinaryExpr_New(state->ast); - if (CEL_UNLIKELY(expr == cel_nullptr)) { - cel_OutOfMemoryStatus(state->status); - _cel_longjmp(state->jmp); - } - cel_Expr_SetId(cel_Expr_UpCast(expr), id); - _cel_AstFromProto_UpdatePosition(state, cel_Expr_UpCast(expr)); - _cel_AstFromProto_SetType(state, cel_Expr_UpCast(expr)); - _cel_AstFromProto_SetRef(state, cel_Expr_UpCast(expr)); - cel_BinaryExpr_SetOp(expr, op); - cel_BinaryExpr_SetLeft(expr, _cel_AstFromProto_Expr(state, left)); - cel_BinaryExpr_SetRight(expr, _cel_AstFromProto_Expr(state, right)); - return cel_Expr_UpCast(expr); -} - -static CEL_NONNULL(cel_Expr*) _cel_AstFromProto_TernaryExpr( - CEL_NONNULL(_cel_AstFromProtoState*) state, int64_t id, cel_TernaryOp op, - CEL_NONNULL(const cel_expr_Expr*) condition, - CEL_NONNULL(const cel_expr_Expr*) if_true, - CEL_NONNULL(const cel_expr_Expr*) if_false) { - _cel_AstFromProto_CheckId(state, id); - CEL_NULLABLE(cel_TernaryExpr*) expr = cel_TernaryExpr_New(state->ast); - if (CEL_UNLIKELY(expr == cel_nullptr)) { - cel_OutOfMemoryStatus(state->status); - _cel_longjmp(state->jmp); - } - cel_Expr_SetId(cel_Expr_UpCast(expr), id); - _cel_AstFromProto_UpdatePosition(state, cel_Expr_UpCast(expr)); - _cel_AstFromProto_SetType(state, cel_Expr_UpCast(expr)); - _cel_AstFromProto_SetRef(state, cel_Expr_UpCast(expr)); - cel_TernaryExpr_SetOp(expr, op); - cel_TernaryExpr_SetCondition(expr, _cel_AstFromProto_Expr(state, condition)); - cel_TernaryExpr_SetIfTrue(expr, _cel_AstFromProto_Expr(state, if_true)); - cel_TernaryExpr_SetIfFalse(expr, _cel_AstFromProto_Expr(state, if_false)); - return cel_Expr_UpCast(expr); -} - -static CEL_NONNULL(cel_Expr*) - _cel_AstFromProto_CallExpr(CEL_NONNULL(_cel_AstFromProtoState*) state, - int64_t id, - CEL_NONNULL(const cel_expr_Expr_Call*) - in) { - size_t in_args_len = 0; - const cel_expr_Expr* const* in_args = - cel_expr_Expr_Call_args(in, &in_args_len); - cel_StringView function = cel_expr_Expr_Call_function(in); - if (!cel_StringView_Empty(function) && - !cel_expr_Expr_Call_has_target(in)) { - switch (in_args_len) { - case 1: { - cel_UnaryOp op; - if (cel_UnaryOp_FromString(function, &op)) { - return _cel_AstFromProto_UnaryExpr(state, id, op, in_args[0]); - } - } break; - case 2: { - cel_BinaryOp op; - if (cel_BinaryOp_FromString(function, &op)) { - return _cel_AstFromProto_BinaryExpr(state, id, op, in_args[0], - in_args[1]); - } - } break; - case 3: { - cel_TernaryOp op; - if (cel_TernaryOp_FromString(function, &op)) { - return _cel_AstFromProto_TernaryExpr(state, id, op, in_args[0], - in_args[1], in_args[2]); - } - } break; - default: - break; - } - } - _cel_AstFromProto_CheckId(state, id); - CEL_NULLABLE(cel_CallExpr*) expr = cel_CallExpr_New(state->ast); - if (CEL_UNLIKELY(expr == cel_nullptr)) { - cel_OutOfMemoryStatus(state->status); - _cel_longjmp(state->jmp); - } - cel_Expr_SetId(cel_Expr_UpCast(expr), id); - _cel_AstFromProto_UpdatePosition(state, cel_Expr_UpCast(expr)); - _cel_AstFromProto_SetType(state, cel_Expr_UpCast(expr)); - _cel_AstFromProto_SetRef(state, cel_Expr_UpCast(expr)); - if (cel_expr_Expr_Call_has_target(in)) { - cel_CallExpr_SetTarget( - expr, - _cel_AstFromProto_Expr(state, cel_expr_Expr_Call_target(in))); - } - cel_CallExpr_SetFunction(expr, _cel_AstFromProto_StrDup(state, function)); - for (size_t i = 0; i < in_args_len; ++i) { - CEL_NULLABLE(cel_CallArgExpr*) - arg = cel_CallArgExpr_New(state->ast); - if (CEL_UNLIKELY(arg == cel_nullptr)) { - cel_OutOfMemoryStatus(state->status); - _cel_longjmp(state->jmp); - } - CEL_NONNULL(cel_Expr*) - arg_value = _cel_AstFromProto_Expr(state, in_args[i]); - cel_Expr_SetSourceRange(cel_Expr_UpCast(arg), - cel_Expr_SourceRange(arg_value)); - cel_CallArgExpr_SetValue(arg, arg_value); - cel_CallExpr_AppendArg(expr, arg); - } - return cel_Expr_UpCast(expr); -} - -static CEL_NONNULL(cel_Expr*) _cel_AstFromProto_ListExpr( - CEL_NONNULL(_cel_AstFromProtoState*) state, int64_t id, - CEL_NONNULL(const cel_expr_Expr_CreateList*) in) { - _cel_AstFromProto_CheckId(state, id); - CEL_NULLABLE(cel_ListExpr*) expr = cel_ListExpr_New(state->ast); - if (CEL_UNLIKELY(expr == cel_nullptr)) { - cel_OutOfMemoryStatus(state->status); - _cel_longjmp(state->jmp); - } - cel_Expr_SetId(cel_Expr_UpCast(expr), id); - _cel_AstFromProto_UpdatePosition(state, cel_Expr_UpCast(expr)); - _cel_AstFromProto_SetType(state, cel_Expr_UpCast(expr)); - _cel_AstFromProto_SetRef(state, cel_Expr_UpCast(expr)); - size_t in_opt_indices_len = 0; - const int32_t* in_opt_indices = - cel_expr_Expr_CreateList_optional_indices(in, &in_opt_indices_len); - size_t in_elems_len = 0; - const cel_expr_Expr* const* in_elems = - cel_expr_Expr_CreateList_elements(in, &in_elems_len); - for (size_t i = 0; i < in_elems_len; ++i) { - CEL_NULLABLE(cel_ListElementExpr*) - elem = cel_ListElementExpr_New(state->ast); - if (CEL_UNLIKELY(elem == cel_nullptr)) { - cel_OutOfMemoryStatus(state->status); - _cel_longjmp(state->jmp); - } - CEL_NONNULL(cel_Expr*) - elem_value = _cel_AstFromProto_Expr(state, in_elems[i]); - cel_Expr_SetSourceRange(cel_Expr_UpCast(elem), - cel_Expr_SourceRange(elem_value)); - cel_ListElementExpr_SetValue(elem, elem_value); - bool optional = false; - for (size_t j = 0; j < in_opt_indices_len; ++j) { - int32_t in_opt_index = in_opt_indices[j]; - if (in_opt_index < 0) { - // Just skip for now. In future we should error. - continue; - } - if (((uint32_t)in_opt_index) == i) { - optional = true; - break; - } - } - cel_ListElementExpr_SetOptional(elem, optional); - cel_ListExpr_AppendElement(expr, elem); - } - return cel_Expr_UpCast(expr); -} - -static CEL_NONNULL(cel_Expr*) _cel_AstFromProto_MapExpr( - CEL_NONNULL(_cel_AstFromProtoState*) state, int64_t id, - CEL_NONNULL(const cel_expr_Expr_CreateStruct*) in) { - _cel_AstFromProto_CheckId(state, id); - CEL_NULLABLE(cel_MapExpr*) expr = cel_MapExpr_New(state->ast); - if (CEL_UNLIKELY(expr == cel_nullptr)) { - cel_OutOfMemoryStatus(state->status); - _cel_longjmp(state->jmp); - } - cel_Expr_SetId(cel_Expr_UpCast(expr), id); - _cel_AstFromProto_UpdatePosition(state, cel_Expr_UpCast(expr)); - _cel_AstFromProto_SetType(state, cel_Expr_UpCast(expr)); - _cel_AstFromProto_SetRef(state, cel_Expr_UpCast(expr)); - size_t in_ents_len = 0; - const cel_expr_Expr_CreateStruct_Entry* const* in_ents = - cel_expr_Expr_CreateStruct_entries(in, &in_ents_len); - for (size_t i = 0; i < in_ents_len; ++i) { - const cel_expr_Expr_CreateStruct_Entry* in_ent = in_ents[i]; - const cel_expr_Expr_CreateStruct_Entry_key_kind_oneofcases key_kind = - cel_expr_Expr_CreateStruct_Entry_key_kind_case(in_ent); - if (key_kind != cel_expr_Expr_CreateStruct_Entry_key_kind_map_key) { - cel_InvalidArgumentStatusF( - state->status, - "cel: expected google.api.expr.Expr.CreateStruct.Entry.key_kind to " - "be map_key: %d", - key_kind); - _cel_longjmp(state->jmp); - } - CEL_NONNULL(cel_MapEntryExpr*) ent = cel_MapEntryExpr_New(state->ast); - if (CEL_UNLIKELY(ent == cel_nullptr)) { - cel_OutOfMemoryStatus(state->status); - _cel_longjmp(state->jmp); - } - cel_Expr_SetId( - cel_Expr_UpCast(ent), - _cel_AstFromProto_CheckId( - state, cel_expr_Expr_CreateStruct_Entry_id(in_ent))); - _cel_AstFromProto_UpdatePosition(state, cel_Expr_UpCast(ent)); - _cel_AstFromProto_SetType(state, cel_Expr_UpCast(ent)); - _cel_AstFromProto_SetRef(state, cel_Expr_UpCast(ent)); - cel_MapEntryExpr_SetKey( - ent, - _cel_AstFromProto_Expr( - state, cel_expr_Expr_CreateStruct_Entry_map_key(in_ent))); - if (cel_expr_Expr_CreateStruct_Entry_has_value(in_ent)) { - cel_MapEntryExpr_SetValue( - ent, - _cel_AstFromProto_Expr( - state, cel_expr_Expr_CreateStruct_Entry_value(in_ent))); - } - cel_MapEntryExpr_SetOptional( - ent, cel_expr_Expr_CreateStruct_Entry_optional_entry(in_ent)); - cel_MapExpr_AppendEntry(expr, ent); - } - return cel_Expr_UpCast(expr); -} - -static CEL_NONNULL(cel_Expr*) _cel_AstFromProto_StructExpr( - CEL_NONNULL(_cel_AstFromProtoState*) state, int64_t id, - CEL_NONNULL(const cel_expr_Expr_CreateStruct*) in) { - _cel_AstFromProto_CheckId(state, id); - CEL_NULLABLE(cel_StructExpr*) expr = cel_StructExpr_New(state->ast); - if (CEL_UNLIKELY(expr == cel_nullptr)) { - cel_OutOfMemoryStatus(state->status); - _cel_longjmp(state->jmp); - } - cel_Expr_SetId(cel_Expr_UpCast(expr), id); - _cel_AstFromProto_UpdatePosition(state, cel_Expr_UpCast(expr)); - _cel_AstFromProto_SetType(state, cel_Expr_UpCast(expr)); - _cel_AstFromProto_SetRef(state, cel_Expr_UpCast(expr)); - cel_StructExpr_SetName( - expr, _cel_AstFromProto_StrDup( - state, cel_expr_Expr_CreateStruct_message_name(in))); - size_t in_flds_len = 0; - const cel_expr_Expr_CreateStruct_Entry* const* in_flds = - cel_expr_Expr_CreateStruct_entries(in, &in_flds_len); - for (size_t i = 0; i < in_flds_len; ++i) { - const cel_expr_Expr_CreateStruct_Entry* in_fld = in_flds[i]; - const cel_expr_Expr_CreateStruct_Entry_key_kind_oneofcases key_kind = - cel_expr_Expr_CreateStruct_Entry_key_kind_case(in_fld); - if (key_kind != - cel_expr_Expr_CreateStruct_Entry_key_kind_field_key) { - cel_InvalidArgumentStatusF( - state->status, - "cel: expected google.api.expr.Expr.CreateStruct.Entry.key_kind to " - "be field_key: %d", - key_kind); - _cel_longjmp(state->jmp); - } - CEL_NONNULL(cel_StructFieldExpr*) fld = cel_StructFieldExpr_New(state->ast); - if (CEL_UNLIKELY(fld == cel_nullptr)) { - cel_OutOfMemoryStatus(state->status); - _cel_longjmp(state->jmp); - } - cel_Expr_SetId( - cel_Expr_UpCast(fld), - _cel_AstFromProto_CheckId( - state, cel_expr_Expr_CreateStruct_Entry_id(in_fld))); - _cel_AstFromProto_UpdatePosition(state, cel_Expr_UpCast(fld)); - _cel_AstFromProto_SetType(state, cel_Expr_UpCast(fld)); - _cel_AstFromProto_SetRef(state, cel_Expr_UpCast(fld)); - cel_StructFieldExpr_SetName( - fld, - _cel_AstFromProto_StrDup( - state, cel_expr_Expr_CreateStruct_Entry_field_key(in_fld))); - if (cel_expr_Expr_CreateStruct_Entry_has_value(in_fld)) { - cel_StructFieldExpr_SetValue( - fld, - _cel_AstFromProto_Expr( - state, cel_expr_Expr_CreateStruct_Entry_value(in_fld))); - } - cel_StructFieldExpr_SetOptional( - fld, cel_expr_Expr_CreateStruct_Entry_optional_entry(in_fld)); - cel_StructExpr_AppendField(expr, fld); - } - return cel_Expr_UpCast(expr); -} - -static CEL_NONNULL(cel_Expr*) _cel_AstFromProto_ComprehensionExpr( - CEL_NONNULL(_cel_AstFromProtoState*) state, int64_t id, - CEL_NONNULL(const cel_expr_Expr_Comprehension*) in) { - _cel_AstFromProto_CheckId(state, id); - CEL_NULLABLE(cel_ComprehensionExpr*) - expr = cel_ComprehensionExpr_New(state->ast); - if (CEL_UNLIKELY(expr == cel_nullptr)) { - cel_OutOfMemoryStatus(state->status); - _cel_longjmp(state->jmp); - } - cel_Expr_SetId(cel_Expr_UpCast(expr), id); - _cel_AstFromProto_UpdatePosition(state, cel_Expr_UpCast(expr)); - _cel_AstFromProto_SetType(state, cel_Expr_UpCast(expr)); - _cel_AstFromProto_SetRef(state, cel_Expr_UpCast(expr)); - cel_ComprehensionExpr_SetIterVar( - expr, _cel_AstFromProto_StrDup( - state, cel_expr_Expr_Comprehension_iter_var(in))); - cel_ComprehensionExpr_SetIterVar2( - expr, _cel_AstFromProto_StrDup( - state, cel_expr_Expr_Comprehension_iter_var2(in))); - cel_ComprehensionExpr_SetAccuVar( - expr, _cel_AstFromProto_StrDup( - state, cel_expr_Expr_Comprehension_accu_var(in))); - if (cel_expr_Expr_Comprehension_has_iter_range(in)) { - cel_ComprehensionExpr_SetIterRange( - expr, _cel_AstFromProto_Expr( - state, cel_expr_Expr_Comprehension_iter_range(in))); - } - if (cel_expr_Expr_Comprehension_has_accu_init(in)) { - cel_ComprehensionExpr_SetAccuInit( - expr, _cel_AstFromProto_Expr( - state, cel_expr_Expr_Comprehension_accu_init(in))); - } - if (cel_expr_Expr_Comprehension_has_loop_condition(in)) { - cel_ComprehensionExpr_SetLoopCondition( - expr, - _cel_AstFromProto_Expr( - state, cel_expr_Expr_Comprehension_loop_condition(in))); - } - if (cel_expr_Expr_Comprehension_has_loop_step(in)) { - cel_ComprehensionExpr_SetLoopStep( - expr, _cel_AstFromProto_Expr( - state, cel_expr_Expr_Comprehension_loop_step(in))); - } - if (cel_expr_Expr_Comprehension_has_result(in)) { - cel_ComprehensionExpr_SetResult( - expr, _cel_AstFromProto_Expr( - state, cel_expr_Expr_Comprehension_result(in))); - } - return cel_Expr_UpCast(expr); -} - -static CEL_NONNULL(cel_Expr*) - _cel_AstFromProto_Expr(CEL_NONNULL(_cel_AstFromProtoState*) state, - CEL_NONNULL(const cel_expr_Expr*) in) { - cel_expr_Expr_expr_kind_oneofcases kind = - cel_expr_Expr_expr_kind_case(in); - switch (kind) { - case cel_expr_Expr_expr_kind_NOT_SET: - return _cel_AstFromProto_UnspecifiedExpr(state, - cel_expr_Expr_id(in)); - case cel_expr_Expr_expr_kind_ident_expr: - return _cel_AstFromProto_IdentExpr(state, cel_expr_Expr_id(in), - cel_expr_Expr_ident_expr(in)); - case cel_expr_Expr_expr_kind_const_expr: - return _cel_AstFromProto_ConstExpr(state, cel_expr_Expr_id(in), - cel_expr_Expr_const_expr(in)); - case cel_expr_Expr_expr_kind_select_expr: - return _cel_AstFromProto_SelectExpr(state, cel_expr_Expr_id(in), - cel_expr_Expr_select_expr(in)); - case cel_expr_Expr_expr_kind_call_expr: - return _cel_AstFromProto_CallExpr(state, cel_expr_Expr_id(in), - cel_expr_Expr_call_expr(in)); - case cel_expr_Expr_expr_kind_list_expr: - return _cel_AstFromProto_ListExpr(state, cel_expr_Expr_id(in), - cel_expr_Expr_list_expr(in)); - case cel_expr_Expr_expr_kind_struct_expr: { - CEL_NONNULL(const cel_expr_Expr_CreateStruct*) - struct_expr = cel_expr_Expr_struct_expr(in); - if (cel_StringView_Empty( - cel_expr_Expr_CreateStruct_message_name(struct_expr))) { - return _cel_AstFromProto_MapExpr(state, cel_expr_Expr_id(in), - struct_expr); - } - return _cel_AstFromProto_StructExpr(state, cel_expr_Expr_id(in), - struct_expr); - } - case cel_expr_Expr_expr_kind_comprehension_expr: - return _cel_AstFromProto_ComprehensionExpr( - state, cel_expr_Expr_id(in), - cel_expr_Expr_comprehension_expr(in)); - default: - cel_InvalidArgumentStatusF( - state->status, "cel: unexpected google.api.expr.Expr kind: %d", kind); - _cel_longjmp(state->jmp); - } -} - -CEL_NULLABLE(cel_Ast*) -cel_Ast_FromProto(CEL_NONNULL(const cel_expr_CheckedExpr*) in, - CEL_NONNULL(cel_Arena*) arena, - CEL_NONNULL(cel_Status*) status) { - CEL_ASSERT_NOT_NULL(in); - CEL_ASSERT_NOT_NULL(arena); - CEL_ASSERT_NOT_NULL(status); - - if (CEL_UNLIKELY(!cel_Status_Ok(status))) { - return cel_nullptr; - } - CEL_NULLABLE(_cel_AstFromProtoState*) - volatile state = (CEL_NULLABLE(_cel_AstFromProtoState*))_cel_Malloc( - sizeof(_cel_AstFromProtoState), cel_nullptr); - if (CEL_UNLIKELY(state == cel_nullptr)) { - cel_OutOfMemoryStatus(status); - return cel_nullptr; - } - CEL_NULLABLE(cel_Ast*) ast = cel_Ast_New(arena); - if (CEL_UNLIKELY(ast == cel_nullptr)) { - _cel_FreeSized(state, sizeof(_cel_AstFromProtoState)); - cel_OutOfMemoryStatus(status); - return cel_nullptr; - } - state->ast = ast; - state->arena = arena; - state->status = status; - state->checked_expr = in; - state->source_info = cel_nullptr; - - if (_cel_setjmp(state->jmp)) { - // ERROR - CEL_ASSERT(!cel_Status_Ok(state->status)); - cel_Ast_Delete(state->ast); - _cel_FreeSized(state, sizeof(_cel_AstFromProtoState)); - return cel_nullptr; - } else { - if (cel_expr_CheckedExpr_has_expr(in)) { - if (cel_expr_CheckedExpr_has_source_info(in)) { - state->source_info = cel_expr_CheckedExpr_source_info(in); - } - cel_Ast_SetExpr( - state->ast, - _cel_AstFromProto_Expr(state, cel_expr_CheckedExpr_expr(in))); - } - // OK - CEL_ASSERT(cel_Status_Ok(state->status)); - _cel_FreeSized(state, sizeof(_cel_AstFromProtoState)); - return ast; - } -} diff --git a/cel-c/ast_proto_v1alpha1.c b/cel-c/ast_proto_v1alpha1.c deleted file mode 100644 index f9658c3..0000000 --- a/cel-c/ast_proto_v1alpha1.c +++ /dev/null @@ -1,698 +0,0 @@ -// Copyright 2025 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "cel-c/ast_proto_v1alpha1.h" - -#include -#include -#include -#include - -#include "google/api/expr/v1alpha1/checked.upb.h" -#include "google/api/expr/v1alpha1/syntax.upb.h" -#include "cel-c/arena.h" -#include "cel-c/assert.h" -#include "cel-c/ast.h" -#include "cel-c/config.h" -#include "cel-c/constant_proto_v1alpha1.h" -#include "cel-c/operators.h" -#include "cel-c/ref.h" -#include "cel-c/ref_proto_v1alpha1.h" -#include "cel-c/status.h" -#include "cel-c/string_view.h" -#include "cel-c/type.h" -#include "cel-c/type_proto_v1alpha1.h" -#include "cel-c/src/malloc.h" -#include "cel-c/src/setjmp.h" - -typedef struct { - CEL_NONNULL(cel_Ast*) ast; - CEL_NONNULL(cel_Arena*) arena; - CEL_NONNULL(cel_Status*) status; - CEL_NONNULL(const google_api_expr_v1alpha1_CheckedExpr*) checked_expr; - CEL_NULLABLE(const google_api_expr_v1alpha1_SourceInfo*) source_info; - _cel_jmp_buf jmp; -} _cel_AstFromProtoV1Alpha1State; - -static int64_t _cel_AstFromProtoV1Alpha1_CheckId( - CEL_NONNULL(_cel_AstFromProtoV1Alpha1State*) state, cel_ExprId id) { - if (CEL_UNLIKELY(id < 0)) { - cel_InvalidArgumentStatusF(state->status, - "cel: expected google.api.expr.v1alpha1.Expr.id " - "to be greater than or equal to 0: %" PRId64, - id); - _cel_longjmp(state->jmp); - } - return id; -} - -static cel_StringView _cel_AstFromProtoV1Alpha1_StrDup( - CEL_NONNULL(_cel_AstFromProtoV1Alpha1State*) state, cel_StringView in) { - cel_StringView out; - if (CEL_UNLIKELY(!cel_Arena_StrDup(state->arena, &out, in))) { - cel_OutOfMemoryStatus(state->status); - _cel_longjmp(state->jmp); - } - return out; -} - -static void _cel_AstFromProtoV1Alpha1_UpdatePosition( - CEL_NONNULL(_cel_AstFromProtoV1Alpha1State*) state, - CEL_NONNULL(cel_Expr*) expr) { - if (state->source_info != cel_nullptr) { - int64_t id = cel_Expr_Id(expr); - if (id != 0) { - int32_t position; - if (google_api_expr_v1alpha1_SourceInfo_positions_get(state->source_info, - id, &position)) { - if (CEL_UNLIKELY(position < -1)) { - cel_InvalidArgumentStatusF( - state->status, - "cel: expected " - "google.api.expr.v1alpha1.SourceInfo.positions[%" PRId64 - "] " - "to be greater than or equal to -1: %" PRId32, - id, position); - _cel_longjmp(state->jmp); - } - cel_Expr_SetSourcePosition(expr, position); - } - } - } -} - -static void _cel_AstFromProtoV1Alpha1_SetType( - CEL_NONNULL(_cel_AstFromProtoV1Alpha1State*) state, - CEL_NONNULL(cel_Expr*) expr) { - int64_t id = cel_Expr_Id(expr); - if (id != 0) { - const google_api_expr_v1alpha1_Type* in_type; - if (google_api_expr_v1alpha1_CheckedExpr_type_map_get( - state->checked_expr, id, - (google_api_expr_v1alpha1_Type**)&in_type)) { - const cel_Type* type = - cel_Type_FromProtoV1Alpha1(in_type, state->arena, state->status); - if (CEL_UNLIKELY(type == cel_nullptr)) { - _cel_longjmp(state->jmp); - } - cel_Expr_SetType(expr, type); - } - } -} - -static void _cel_AstFromProtoV1Alpha1_SetRef( - CEL_NONNULL(_cel_AstFromProtoV1Alpha1State*) state, - CEL_NONNULL(cel_Expr*) expr) { - int64_t id = cel_Expr_Id(expr); - if (id != 0) { - const google_api_expr_v1alpha1_Reference* in_ref; - if (google_api_expr_v1alpha1_CheckedExpr_reference_map_get( - state->checked_expr, id, - (google_api_expr_v1alpha1_Reference**)&in_ref)) { - const cel_Ref* ref = - cel_Ref_FromProtoV1Alpha1(in_ref, state->arena, state->status); - if (CEL_UNLIKELY(ref == cel_nullptr)) { - _cel_longjmp(state->jmp); - } - cel_Expr_SetRef(expr, ref); - } - } -} - -static CEL_NONNULL(cel_Expr*) _cel_AstFromProtoV1Alpha1_Expr( - CEL_NONNULL(_cel_AstFromProtoV1Alpha1State*) state, - CEL_NONNULL(const google_api_expr_v1alpha1_Expr*) in); - -static CEL_NONNULL(cel_Expr*) _cel_AstFromProtoV1Alpha1_UnspecifiedExpr( - CEL_NONNULL(_cel_AstFromProtoV1Alpha1State*) state, int64_t id) { - _cel_AstFromProtoV1Alpha1_CheckId(state, id); - CEL_NULLABLE(cel_UnspecifiedExpr*) expr = cel_UnspecifiedExpr_New(state->ast); - if (CEL_UNLIKELY(expr == cel_nullptr)) { - cel_OutOfMemoryStatus(state->status); - _cel_longjmp(state->jmp); - } - cel_Expr_SetId(cel_Expr_UpCast(expr), id); - _cel_AstFromProtoV1Alpha1_UpdatePosition(state, cel_Expr_UpCast(expr)); - _cel_AstFromProtoV1Alpha1_SetType(state, cel_Expr_UpCast(expr)); - _cel_AstFromProtoV1Alpha1_SetRef(state, cel_Expr_UpCast(expr)); - return cel_Expr_UpCast(expr); -} - -static CEL_NONNULL(cel_Expr*) _cel_AstFromProtoV1Alpha1_IdentExpr( - CEL_NONNULL(_cel_AstFromProtoV1Alpha1State*) state, int64_t id, - CEL_NONNULL(const google_api_expr_v1alpha1_Expr_Ident*) in) { - _cel_AstFromProtoV1Alpha1_CheckId(state, id); - CEL_NULLABLE(cel_IdentExpr*) expr = cel_IdentExpr_New(state->ast); - if (CEL_UNLIKELY(expr == cel_nullptr)) { - cel_OutOfMemoryStatus(state->status); - _cel_longjmp(state->jmp); - } - cel_Expr_SetId(cel_Expr_UpCast(expr), id); - _cel_AstFromProtoV1Alpha1_UpdatePosition(state, cel_Expr_UpCast(expr)); - _cel_AstFromProtoV1Alpha1_SetType(state, cel_Expr_UpCast(expr)); - _cel_AstFromProtoV1Alpha1_SetRef(state, cel_Expr_UpCast(expr)); - cel_IdentExpr_SetName( - expr, _cel_AstFromProtoV1Alpha1_StrDup( - state, google_api_expr_v1alpha1_Expr_Ident_name(in))); - return cel_Expr_UpCast(expr); -} - -static CEL_NONNULL(cel_Expr*) _cel_AstFromProtoV1Alpha1_ConstExpr( - CEL_NONNULL(_cel_AstFromProtoV1Alpha1State*) state, int64_t id, - CEL_NONNULL(const google_api_expr_v1alpha1_Constant*) in) { - _cel_AstFromProtoV1Alpha1_CheckId(state, id); - CEL_NULLABLE(cel_ConstExpr*) expr = cel_ConstExpr_New(state->ast); - if (CEL_UNLIKELY(expr == cel_nullptr)) { - cel_OutOfMemoryStatus(state->status); - _cel_longjmp(state->jmp); - } - cel_Expr_SetId(cel_Expr_UpCast(expr), id); - _cel_AstFromProtoV1Alpha1_UpdatePosition(state, cel_Expr_UpCast(expr)); - _cel_AstFromProtoV1Alpha1_SetType(state, cel_Expr_UpCast(expr)); - _cel_AstFromProtoV1Alpha1_SetRef(state, cel_Expr_UpCast(expr)); - if (CEL_UNLIKELY(!cel_Constant_FromProtoV1Alpha1( - cel_ConstExpr_MutableValue(expr), in, state->arena, state->status))) { - _cel_longjmp(state->jmp); - } - return cel_Expr_UpCast(expr); -} - -static CEL_NONNULL(cel_Expr*) _cel_AstFromProtoV1Alpha1_SelectExpr( - CEL_NONNULL(_cel_AstFromProtoV1Alpha1State*) state, int64_t id, - CEL_NONNULL(const google_api_expr_v1alpha1_Expr_Select*) in) { - _cel_AstFromProtoV1Alpha1_CheckId(state, id); - CEL_NULLABLE(cel_SelectExpr*) expr = cel_SelectExpr_New(state->ast); - if (CEL_UNLIKELY(expr == cel_nullptr)) { - cel_OutOfMemoryStatus(state->status); - _cel_longjmp(state->jmp); - } - cel_Expr_SetId(cel_Expr_UpCast(expr), id); - _cel_AstFromProtoV1Alpha1_UpdatePosition(state, cel_Expr_UpCast(expr)); - _cel_AstFromProtoV1Alpha1_SetType(state, cel_Expr_UpCast(expr)); - _cel_AstFromProtoV1Alpha1_SetRef(state, cel_Expr_UpCast(expr)); - if (google_api_expr_v1alpha1_Expr_Select_has_operand(in)) { - cel_SelectExpr_SetOperand( - expr, _cel_AstFromProtoV1Alpha1_Expr( - state, google_api_expr_v1alpha1_Expr_Select_operand(in))); - } - cel_SelectExpr_SetField( - expr, _cel_AstFromProtoV1Alpha1_StrDup( - state, google_api_expr_v1alpha1_Expr_Select_field(in))); - cel_SelectExpr_SetTestOnly( - expr, google_api_expr_v1alpha1_Expr_Select_test_only(in)); - return cel_Expr_UpCast(expr); -} - -static CEL_NONNULL(cel_Expr*) _cel_AstFromProtoV1Alpha1_UnaryExpr( - CEL_NONNULL(_cel_AstFromProtoV1Alpha1State*) state, int64_t id, - cel_UnaryOp op, CEL_NONNULL(const google_api_expr_v1alpha1_Expr*) arg) { - _cel_AstFromProtoV1Alpha1_CheckId(state, id); - CEL_NULLABLE(cel_UnaryExpr*) expr = cel_UnaryExpr_New(state->ast); - if (CEL_UNLIKELY(expr == cel_nullptr)) { - cel_OutOfMemoryStatus(state->status); - _cel_longjmp(state->jmp); - } - cel_Expr_SetId(cel_Expr_UpCast(expr), id); - _cel_AstFromProtoV1Alpha1_UpdatePosition(state, cel_Expr_UpCast(expr)); - _cel_AstFromProtoV1Alpha1_SetType(state, cel_Expr_UpCast(expr)); - _cel_AstFromProtoV1Alpha1_SetRef(state, cel_Expr_UpCast(expr)); - cel_UnaryExpr_SetOp(expr, op); - cel_UnaryExpr_SetArg(expr, _cel_AstFromProtoV1Alpha1_Expr(state, arg)); - return cel_Expr_UpCast(expr); -} - -static CEL_NONNULL(cel_Expr*) _cel_AstFromProtoV1Alpha1_BinaryExpr( - CEL_NONNULL(_cel_AstFromProtoV1Alpha1State*) state, int64_t id, - cel_BinaryOp op, CEL_NONNULL(const google_api_expr_v1alpha1_Expr*) left, - CEL_NONNULL(const google_api_expr_v1alpha1_Expr*) right) { - _cel_AstFromProtoV1Alpha1_CheckId(state, id); - CEL_NULLABLE(cel_BinaryExpr*) expr = cel_BinaryExpr_New(state->ast); - if (CEL_UNLIKELY(expr == cel_nullptr)) { - cel_OutOfMemoryStatus(state->status); - _cel_longjmp(state->jmp); - } - cel_Expr_SetId(cel_Expr_UpCast(expr), id); - _cel_AstFromProtoV1Alpha1_UpdatePosition(state, cel_Expr_UpCast(expr)); - _cel_AstFromProtoV1Alpha1_SetType(state, cel_Expr_UpCast(expr)); - _cel_AstFromProtoV1Alpha1_SetRef(state, cel_Expr_UpCast(expr)); - cel_BinaryExpr_SetOp(expr, op); - cel_BinaryExpr_SetLeft(expr, _cel_AstFromProtoV1Alpha1_Expr(state, left)); - cel_BinaryExpr_SetRight(expr, _cel_AstFromProtoV1Alpha1_Expr(state, right)); - return cel_Expr_UpCast(expr); -} - -static CEL_NONNULL(cel_Expr*) _cel_AstFromProtoV1Alpha1_TernaryExpr( - CEL_NONNULL(_cel_AstFromProtoV1Alpha1State*) state, int64_t id, - cel_TernaryOp op, - CEL_NONNULL(const google_api_expr_v1alpha1_Expr*) condition, - CEL_NONNULL(const google_api_expr_v1alpha1_Expr*) if_true, - CEL_NONNULL(const google_api_expr_v1alpha1_Expr*) if_false) { - _cel_AstFromProtoV1Alpha1_CheckId(state, id); - CEL_NULLABLE(cel_TernaryExpr*) expr = cel_TernaryExpr_New(state->ast); - if (CEL_UNLIKELY(expr == cel_nullptr)) { - cel_OutOfMemoryStatus(state->status); - _cel_longjmp(state->jmp); - } - cel_Expr_SetId(cel_Expr_UpCast(expr), id); - _cel_AstFromProtoV1Alpha1_UpdatePosition(state, cel_Expr_UpCast(expr)); - _cel_AstFromProtoV1Alpha1_SetType(state, cel_Expr_UpCast(expr)); - _cel_AstFromProtoV1Alpha1_SetRef(state, cel_Expr_UpCast(expr)); - cel_TernaryExpr_SetOp(expr, op); - cel_TernaryExpr_SetCondition( - expr, _cel_AstFromProtoV1Alpha1_Expr(state, condition)); - cel_TernaryExpr_SetIfTrue(expr, - _cel_AstFromProtoV1Alpha1_Expr(state, if_true)); - cel_TernaryExpr_SetIfFalse(expr, - _cel_AstFromProtoV1Alpha1_Expr(state, if_false)); - return cel_Expr_UpCast(expr); -} - -static CEL_NONNULL(cel_Expr*) _cel_AstFromProtoV1Alpha1_CallExpr( - CEL_NONNULL(_cel_AstFromProtoV1Alpha1State*) state, int64_t id, - CEL_NONNULL(const google_api_expr_v1alpha1_Expr_Call*) in) { - size_t in_args_len = 0; - const google_api_expr_v1alpha1_Expr* const* in_args = - google_api_expr_v1alpha1_Expr_Call_args(in, &in_args_len); - cel_StringView function = google_api_expr_v1alpha1_Expr_Call_function(in); - if (!cel_StringView_Empty(function) && - !google_api_expr_v1alpha1_Expr_Call_has_target(in)) { - switch (in_args_len) { - case 1: { - cel_UnaryOp op; - if (cel_UnaryOp_FromString(function, &op)) { - return _cel_AstFromProtoV1Alpha1_UnaryExpr(state, id, op, in_args[0]); - } - } break; - case 2: { - cel_BinaryOp op; - if (cel_BinaryOp_FromString(function, &op)) { - return _cel_AstFromProtoV1Alpha1_BinaryExpr(state, id, op, in_args[0], - in_args[1]); - } - } break; - case 3: { - cel_TernaryOp op; - if (cel_TernaryOp_FromString(function, &op)) { - return _cel_AstFromProtoV1Alpha1_TernaryExpr( - state, id, op, in_args[0], in_args[1], in_args[2]); - } - } break; - default: - break; - } - } - _cel_AstFromProtoV1Alpha1_CheckId(state, id); - CEL_NULLABLE(cel_CallExpr*) expr = cel_CallExpr_New(state->ast); - if (CEL_UNLIKELY(expr == cel_nullptr)) { - cel_OutOfMemoryStatus(state->status); - _cel_longjmp(state->jmp); - } - cel_Expr_SetId(cel_Expr_UpCast(expr), id); - _cel_AstFromProtoV1Alpha1_UpdatePosition(state, cel_Expr_UpCast(expr)); - _cel_AstFromProtoV1Alpha1_SetType(state, cel_Expr_UpCast(expr)); - _cel_AstFromProtoV1Alpha1_SetRef(state, cel_Expr_UpCast(expr)); - if (google_api_expr_v1alpha1_Expr_Call_has_target(in)) { - cel_CallExpr_SetTarget( - expr, _cel_AstFromProtoV1Alpha1_Expr( - state, google_api_expr_v1alpha1_Expr_Call_target(in))); - } - cel_CallExpr_SetFunction(expr, - _cel_AstFromProtoV1Alpha1_StrDup(state, function)); - for (size_t i = 0; i < in_args_len; ++i) { - CEL_NULLABLE(cel_CallArgExpr*) - arg = cel_CallArgExpr_New(state->ast); - if (CEL_UNLIKELY(arg == cel_nullptr)) { - cel_OutOfMemoryStatus(state->status); - _cel_longjmp(state->jmp); - } - CEL_NONNULL(cel_Expr*) - arg_value = _cel_AstFromProtoV1Alpha1_Expr(state, in_args[i]); - cel_Expr_SetSourceRange(cel_Expr_UpCast(arg), - cel_Expr_SourceRange(arg_value)); - cel_CallArgExpr_SetValue(arg, arg_value); - cel_CallExpr_AppendArg(expr, arg); - } - return cel_Expr_UpCast(expr); -} - -static CEL_NONNULL(cel_Expr*) _cel_AstFromProtoV1Alpha1_ListExpr( - CEL_NONNULL(_cel_AstFromProtoV1Alpha1State*) state, int64_t id, - CEL_NONNULL(const google_api_expr_v1alpha1_Expr_CreateList*) in) { - _cel_AstFromProtoV1Alpha1_CheckId(state, id); - CEL_NULLABLE(cel_ListExpr*) expr = cel_ListExpr_New(state->ast); - if (CEL_UNLIKELY(expr == cel_nullptr)) { - cel_OutOfMemoryStatus(state->status); - _cel_longjmp(state->jmp); - } - cel_Expr_SetId(cel_Expr_UpCast(expr), id); - _cel_AstFromProtoV1Alpha1_UpdatePosition(state, cel_Expr_UpCast(expr)); - _cel_AstFromProtoV1Alpha1_SetType(state, cel_Expr_UpCast(expr)); - _cel_AstFromProtoV1Alpha1_SetRef(state, cel_Expr_UpCast(expr)); - size_t in_opt_indices_len = 0; - const int32_t* in_opt_indices = - google_api_expr_v1alpha1_Expr_CreateList_optional_indices( - in, &in_opt_indices_len); - size_t in_elems_len = 0; - const google_api_expr_v1alpha1_Expr* const* in_elems = - google_api_expr_v1alpha1_Expr_CreateList_elements(in, &in_elems_len); - for (size_t i = 0; i < in_elems_len; ++i) { - CEL_NULLABLE(cel_ListElementExpr*) - elem = cel_ListElementExpr_New(state->ast); - if (CEL_UNLIKELY(elem == cel_nullptr)) { - cel_OutOfMemoryStatus(state->status); - _cel_longjmp(state->jmp); - } - CEL_NONNULL(cel_Expr*) - elem_value = _cel_AstFromProtoV1Alpha1_Expr(state, in_elems[i]); - cel_Expr_SetSourceRange(cel_Expr_UpCast(elem), - cel_Expr_SourceRange(elem_value)); - cel_ListElementExpr_SetValue(elem, elem_value); - bool optional = false; - for (size_t j = 0; j < in_opt_indices_len; ++j) { - int32_t in_opt_index = in_opt_indices[j]; - if (in_opt_index < 0) { - // Just skip for now. In future we should error. - continue; - } - if (((uint32_t)in_opt_index) == i) { - optional = true; - break; - } - } - cel_ListElementExpr_SetOptional(elem, optional); - cel_ListExpr_AppendElement(expr, elem); - } - return cel_Expr_UpCast(expr); -} - -static CEL_NONNULL(cel_Expr*) _cel_AstFromProtoV1Alpha1_MapExpr( - CEL_NONNULL(_cel_AstFromProtoV1Alpha1State*) state, int64_t id, - CEL_NONNULL(const google_api_expr_v1alpha1_Expr_CreateStruct*) in) { - _cel_AstFromProtoV1Alpha1_CheckId(state, id); - CEL_NULLABLE(cel_MapExpr*) expr = cel_MapExpr_New(state->ast); - if (CEL_UNLIKELY(expr == cel_nullptr)) { - cel_OutOfMemoryStatus(state->status); - _cel_longjmp(state->jmp); - } - cel_Expr_SetId(cel_Expr_UpCast(expr), id); - _cel_AstFromProtoV1Alpha1_UpdatePosition(state, cel_Expr_UpCast(expr)); - _cel_AstFromProtoV1Alpha1_SetType(state, cel_Expr_UpCast(expr)); - _cel_AstFromProtoV1Alpha1_SetRef(state, cel_Expr_UpCast(expr)); - size_t in_ents_len = 0; - const google_api_expr_v1alpha1_Expr_CreateStruct_Entry* const* in_ents = - google_api_expr_v1alpha1_Expr_CreateStruct_entries(in, &in_ents_len); - for (size_t i = 0; i < in_ents_len; ++i) { - const google_api_expr_v1alpha1_Expr_CreateStruct_Entry* in_ent = in_ents[i]; - const google_api_expr_v1alpha1_Expr_CreateStruct_Entry_key_kind_oneofcases - key_kind = - google_api_expr_v1alpha1_Expr_CreateStruct_Entry_key_kind_case( - in_ent); - if (key_kind != - google_api_expr_v1alpha1_Expr_CreateStruct_Entry_key_kind_map_key) { - cel_InvalidArgumentStatusF( - state->status, - "cel: expected " - "google.api.expr.v1alpha1.Expr.CreateStruct.Entry.key_kind to " - "be map_key: %d", - key_kind); - _cel_longjmp(state->jmp); - } - CEL_NONNULL(cel_MapEntryExpr*) ent = cel_MapEntryExpr_New(state->ast); - if (CEL_UNLIKELY(ent == cel_nullptr)) { - cel_OutOfMemoryStatus(state->status); - _cel_longjmp(state->jmp); - } - cel_Expr_SetId( - cel_Expr_UpCast(ent), - _cel_AstFromProtoV1Alpha1_CheckId( - state, - google_api_expr_v1alpha1_Expr_CreateStruct_Entry_id(in_ent))); - _cel_AstFromProtoV1Alpha1_UpdatePosition(state, cel_Expr_UpCast(ent)); - _cel_AstFromProtoV1Alpha1_SetType(state, cel_Expr_UpCast(ent)); - _cel_AstFromProtoV1Alpha1_SetRef(state, cel_Expr_UpCast(ent)); - cel_MapEntryExpr_SetKey( - ent, - _cel_AstFromProtoV1Alpha1_Expr( - state, - google_api_expr_v1alpha1_Expr_CreateStruct_Entry_map_key(in_ent))); - if (google_api_expr_v1alpha1_Expr_CreateStruct_Entry_has_value(in_ent)) { - cel_MapEntryExpr_SetValue( - ent, - _cel_AstFromProtoV1Alpha1_Expr( - state, - google_api_expr_v1alpha1_Expr_CreateStruct_Entry_value(in_ent))); - } - cel_MapEntryExpr_SetOptional( - ent, google_api_expr_v1alpha1_Expr_CreateStruct_Entry_optional_entry( - in_ent)); - cel_MapExpr_AppendEntry(expr, ent); - } - return cel_Expr_UpCast(expr); -} - -static CEL_NONNULL(cel_Expr*) _cel_AstFromProtoV1Alpha1_StructExpr( - CEL_NONNULL(_cel_AstFromProtoV1Alpha1State*) state, int64_t id, - CEL_NONNULL(const google_api_expr_v1alpha1_Expr_CreateStruct*) in) { - _cel_AstFromProtoV1Alpha1_CheckId(state, id); - CEL_NULLABLE(cel_StructExpr*) expr = cel_StructExpr_New(state->ast); - if (CEL_UNLIKELY(expr == cel_nullptr)) { - cel_OutOfMemoryStatus(state->status); - _cel_longjmp(state->jmp); - } - cel_Expr_SetId(cel_Expr_UpCast(expr), id); - _cel_AstFromProtoV1Alpha1_UpdatePosition(state, cel_Expr_UpCast(expr)); - _cel_AstFromProtoV1Alpha1_SetType(state, cel_Expr_UpCast(expr)); - _cel_AstFromProtoV1Alpha1_SetRef(state, cel_Expr_UpCast(expr)); - cel_StructExpr_SetName( - expr, - _cel_AstFromProtoV1Alpha1_StrDup( - state, google_api_expr_v1alpha1_Expr_CreateStruct_message_name(in))); - size_t in_flds_len = 0; - const google_api_expr_v1alpha1_Expr_CreateStruct_Entry* const* in_flds = - google_api_expr_v1alpha1_Expr_CreateStruct_entries(in, &in_flds_len); - for (size_t i = 0; i < in_flds_len; ++i) { - const google_api_expr_v1alpha1_Expr_CreateStruct_Entry* in_fld = in_flds[i]; - const google_api_expr_v1alpha1_Expr_CreateStruct_Entry_key_kind_oneofcases - key_kind = - google_api_expr_v1alpha1_Expr_CreateStruct_Entry_key_kind_case( - in_fld); - if (key_kind != - google_api_expr_v1alpha1_Expr_CreateStruct_Entry_key_kind_field_key) { - cel_InvalidArgumentStatusF( - state->status, - "cel: expected " - "google.api.expr.v1alpha1.Expr.CreateStruct.Entry.key_kind to " - "be field_key: %d", - key_kind); - _cel_longjmp(state->jmp); - } - CEL_NONNULL(cel_StructFieldExpr*) fld = cel_StructFieldExpr_New(state->ast); - if (CEL_UNLIKELY(fld == cel_nullptr)) { - cel_OutOfMemoryStatus(state->status); - _cel_longjmp(state->jmp); - } - cel_Expr_SetId( - cel_Expr_UpCast(fld), - _cel_AstFromProtoV1Alpha1_CheckId( - state, - google_api_expr_v1alpha1_Expr_CreateStruct_Entry_id(in_fld))); - _cel_AstFromProtoV1Alpha1_UpdatePosition(state, cel_Expr_UpCast(fld)); - _cel_AstFromProtoV1Alpha1_SetType(state, cel_Expr_UpCast(fld)); - _cel_AstFromProtoV1Alpha1_SetRef(state, cel_Expr_UpCast(fld)); - cel_StructFieldExpr_SetName( - fld, - _cel_AstFromProtoV1Alpha1_StrDup( - state, google_api_expr_v1alpha1_Expr_CreateStruct_Entry_field_key( - in_fld))); - if (google_api_expr_v1alpha1_Expr_CreateStruct_Entry_has_value(in_fld)) { - cel_StructFieldExpr_SetValue( - fld, - _cel_AstFromProtoV1Alpha1_Expr( - state, - google_api_expr_v1alpha1_Expr_CreateStruct_Entry_value(in_fld))); - } - cel_StructFieldExpr_SetOptional( - fld, google_api_expr_v1alpha1_Expr_CreateStruct_Entry_optional_entry( - in_fld)); - cel_StructExpr_AppendField(expr, fld); - } - return cel_Expr_UpCast(expr); -} - -static CEL_NONNULL(cel_Expr*) _cel_AstFromProtoV1Alpha1_ComprehensionExpr( - CEL_NONNULL(_cel_AstFromProtoV1Alpha1State*) state, int64_t id, - CEL_NONNULL(const google_api_expr_v1alpha1_Expr_Comprehension*) in) { - _cel_AstFromProtoV1Alpha1_CheckId(state, id); - CEL_NULLABLE(cel_ComprehensionExpr*) - expr = cel_ComprehensionExpr_New(state->ast); - if (CEL_UNLIKELY(expr == cel_nullptr)) { - cel_OutOfMemoryStatus(state->status); - _cel_longjmp(state->jmp); - } - cel_Expr_SetId(cel_Expr_UpCast(expr), id); - _cel_AstFromProtoV1Alpha1_UpdatePosition(state, cel_Expr_UpCast(expr)); - _cel_AstFromProtoV1Alpha1_SetType(state, cel_Expr_UpCast(expr)); - _cel_AstFromProtoV1Alpha1_SetRef(state, cel_Expr_UpCast(expr)); - cel_ComprehensionExpr_SetIterVar( - expr, - _cel_AstFromProtoV1Alpha1_StrDup( - state, google_api_expr_v1alpha1_Expr_Comprehension_iter_var(in))); - cel_ComprehensionExpr_SetIterVar2( - expr, - _cel_AstFromProtoV1Alpha1_StrDup( - state, google_api_expr_v1alpha1_Expr_Comprehension_iter_var2(in))); - cel_ComprehensionExpr_SetAccuVar( - expr, - _cel_AstFromProtoV1Alpha1_StrDup( - state, google_api_expr_v1alpha1_Expr_Comprehension_accu_var(in))); - if (google_api_expr_v1alpha1_Expr_Comprehension_has_iter_range(in)) { - cel_ComprehensionExpr_SetIterRange( - expr, - _cel_AstFromProtoV1Alpha1_Expr( - state, google_api_expr_v1alpha1_Expr_Comprehension_iter_range(in))); - } - if (google_api_expr_v1alpha1_Expr_Comprehension_has_accu_init(in)) { - cel_ComprehensionExpr_SetAccuInit( - expr, - _cel_AstFromProtoV1Alpha1_Expr( - state, google_api_expr_v1alpha1_Expr_Comprehension_accu_init(in))); - } - if (google_api_expr_v1alpha1_Expr_Comprehension_has_loop_condition(in)) { - cel_ComprehensionExpr_SetLoopCondition( - expr, - _cel_AstFromProtoV1Alpha1_Expr( - state, - google_api_expr_v1alpha1_Expr_Comprehension_loop_condition(in))); - } - if (google_api_expr_v1alpha1_Expr_Comprehension_has_loop_step(in)) { - cel_ComprehensionExpr_SetLoopStep( - expr, - _cel_AstFromProtoV1Alpha1_Expr( - state, google_api_expr_v1alpha1_Expr_Comprehension_loop_step(in))); - } - if (google_api_expr_v1alpha1_Expr_Comprehension_has_result(in)) { - cel_ComprehensionExpr_SetResult( - expr, - _cel_AstFromProtoV1Alpha1_Expr( - state, google_api_expr_v1alpha1_Expr_Comprehension_result(in))); - } - return cel_Expr_UpCast(expr); -} - -static CEL_NONNULL(cel_Expr*) _cel_AstFromProtoV1Alpha1_Expr( - CEL_NONNULL(_cel_AstFromProtoV1Alpha1State*) state, - CEL_NONNULL(const google_api_expr_v1alpha1_Expr*) in) { - google_api_expr_v1alpha1_Expr_expr_kind_oneofcases kind = - google_api_expr_v1alpha1_Expr_expr_kind_case(in); - switch (kind) { - case google_api_expr_v1alpha1_Expr_expr_kind_NOT_SET: - return _cel_AstFromProtoV1Alpha1_UnspecifiedExpr( - state, google_api_expr_v1alpha1_Expr_id(in)); - case google_api_expr_v1alpha1_Expr_expr_kind_ident_expr: - return _cel_AstFromProtoV1Alpha1_IdentExpr( - state, google_api_expr_v1alpha1_Expr_id(in), - google_api_expr_v1alpha1_Expr_ident_expr(in)); - case google_api_expr_v1alpha1_Expr_expr_kind_const_expr: - return _cel_AstFromProtoV1Alpha1_ConstExpr( - state, google_api_expr_v1alpha1_Expr_id(in), - google_api_expr_v1alpha1_Expr_const_expr(in)); - case google_api_expr_v1alpha1_Expr_expr_kind_select_expr: - return _cel_AstFromProtoV1Alpha1_SelectExpr( - state, google_api_expr_v1alpha1_Expr_id(in), - google_api_expr_v1alpha1_Expr_select_expr(in)); - case google_api_expr_v1alpha1_Expr_expr_kind_call_expr: - return _cel_AstFromProtoV1Alpha1_CallExpr( - state, google_api_expr_v1alpha1_Expr_id(in), - google_api_expr_v1alpha1_Expr_call_expr(in)); - case google_api_expr_v1alpha1_Expr_expr_kind_list_expr: - return _cel_AstFromProtoV1Alpha1_ListExpr( - state, google_api_expr_v1alpha1_Expr_id(in), - google_api_expr_v1alpha1_Expr_list_expr(in)); - case google_api_expr_v1alpha1_Expr_expr_kind_struct_expr: { - CEL_NONNULL(const google_api_expr_v1alpha1_Expr_CreateStruct*) - struct_expr = google_api_expr_v1alpha1_Expr_struct_expr(in); - if (cel_StringView_Empty( - google_api_expr_v1alpha1_Expr_CreateStruct_message_name( - struct_expr))) { - return _cel_AstFromProtoV1Alpha1_MapExpr( - state, google_api_expr_v1alpha1_Expr_id(in), struct_expr); - } - return _cel_AstFromProtoV1Alpha1_StructExpr( - state, google_api_expr_v1alpha1_Expr_id(in), struct_expr); - } - case google_api_expr_v1alpha1_Expr_expr_kind_comprehension_expr: - return _cel_AstFromProtoV1Alpha1_ComprehensionExpr( - state, google_api_expr_v1alpha1_Expr_id(in), - google_api_expr_v1alpha1_Expr_comprehension_expr(in)); - default: - cel_InvalidArgumentStatusF( - state->status, - "cel: unexpected google.api.expr.v1alpha1.Expr kind: %d", kind); - _cel_longjmp(state->jmp); - } -} - -CEL_NULLABLE(cel_Ast*) -cel_Ast_FromProtoV1Alpha1( - CEL_NONNULL(const google_api_expr_v1alpha1_CheckedExpr*) in, - CEL_NONNULL(cel_Arena*) arena, CEL_NONNULL(cel_Status*) status) { - CEL_ASSERT_NOT_NULL(in); - CEL_ASSERT_NOT_NULL(arena); - CEL_ASSERT_NOT_NULL(status); - - if (CEL_UNLIKELY(!cel_Status_Ok(status))) { - return cel_nullptr; - } - CEL_NULLABLE(_cel_AstFromProtoV1Alpha1State*) - volatile state = (CEL_NULLABLE(_cel_AstFromProtoV1Alpha1State*))_cel_Malloc( - sizeof(_cel_AstFromProtoV1Alpha1State), cel_nullptr); - if (CEL_UNLIKELY(state == cel_nullptr)) { - cel_OutOfMemoryStatus(status); - return cel_nullptr; - } - CEL_NULLABLE(cel_Ast*) ast = cel_Ast_New(arena); - if (CEL_UNLIKELY(ast == cel_nullptr)) { - _cel_FreeSized(state, sizeof(_cel_AstFromProtoV1Alpha1State)); - cel_OutOfMemoryStatus(status); - return cel_nullptr; - } - state->ast = ast; - state->arena = arena; - state->status = status; - state->checked_expr = in; - state->source_info = cel_nullptr; - - if (_cel_setjmp(state->jmp)) { - // ERROR - CEL_ASSERT(!cel_Status_Ok(state->status)); - cel_Ast_Delete(state->ast); - _cel_FreeSized(state, sizeof(_cel_AstFromProtoV1Alpha1State)); - return cel_nullptr; - } else { - if (google_api_expr_v1alpha1_CheckedExpr_has_expr(in)) { - if (google_api_expr_v1alpha1_CheckedExpr_has_source_info(in)) { - state->source_info = - google_api_expr_v1alpha1_CheckedExpr_source_info(in); - } - cel_Ast_SetExpr( - state->ast, - _cel_AstFromProtoV1Alpha1_Expr( - state, google_api_expr_v1alpha1_CheckedExpr_expr(in))); - } - // OK - CEL_ASSERT(cel_Status_Ok(state->status)); - _cel_FreeSized(state, sizeof(_cel_AstFromProtoV1Alpha1State)); - return ast; - } -} diff --git a/cel-c/ast_traverse.c b/cel-c/ast_traverse.c deleted file mode 100644 index b9bdb88..0000000 --- a/cel-c/ast_traverse.c +++ /dev/null @@ -1,1426 +0,0 @@ -// Copyright 2025 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "cel-c/ast_traverse.h" - -#include -#include -#include - -#include "cel-c/alloc.h" -#include "cel-c/assert.h" -#include "cel-c/ast.h" -#include "cel-c/ast_visitor.h" -#include "cel-c/config.h" -#include "cel-c/status.h" -#include "cel-c/string_view.h" -#include "cel-c/src/deque.h" -#include "cel-c/src/malloc.h" - -typedef enum CEL_ATTRIBUTE_CLOSED_ENUM { - _cel_AstVisitorControl_kStop = 0, - _cel_AstVisitorControl_kContinue, -} _cel_AstVisitorControl; - -typedef enum CEL_ATTRIBUTE_CLOSED_ENUM { - _cel_AstTraverserStep_kStepIn = 0, - _cel_AstTraverserStep_kStepOver, - _cel_AstTraverserStep_kStepOut, -} _cel_AstTraverserStep; - -#define _cel_AstVisitor_Invoke(visitor, member, ...) \ - ((((visitor)->vtable->member) != cel_nullptr) \ - ? ((*(visitor)->vtable->member)((visitor), ##__VA_ARGS__), \ - _cel_AstVisitorControl_kStop) \ - : _cel_AstVisitorControl_kContinue) - -#define _cel_AstVisitor_HasVisit(visitor, visit) \ - (((visitor)->vtable->PreVisit##visit) != cel_nullptr || \ - ((visitor)->vtable->PostVisit##visit) != cel_nullptr) - -typedef enum CEL_ATTRIBUTE_CLOSED_ENUM { - _cel_AstTraverserRecordKind_kExpr = 1, - _cel_AstTraverserRecordKind_kSelectOperand, - _cel_AstTraverserRecordKind_kCallTarget, - _cel_AstTraverserRecordKind_kCallArgValue, - _cel_AstTraverserRecordKind_kListElementValue, - _cel_AstTraverserRecordKind_kMapEntryKey, - _cel_AstTraverserRecordKind_kMapEntryValue, - _cel_AstTraverserRecordKind_kStructFieldValue, - _cel_AstTraverserRecordKind_kComprehensionIterRange, - _cel_AstTraverserRecordKind_kComprehensionAccuInit, - _cel_AstTraverserRecordKind_kComprehensionLoopCondition, - _cel_AstTraverserRecordKind_kComprehensionLoopStep, - _cel_AstTraverserRecordKind_kComprehensionResult, - _cel_AstTraverserRecordKind_kUnaryArg, - _cel_AstTraverserRecordKind_kBinaryLeft, - _cel_AstTraverserRecordKind_kBinaryRight, - _cel_AstTraverserRecordKind_kTernaryCondition, - _cel_AstTraverserRecordKind_kTernaryIfTrue, - _cel_AstTraverserRecordKind_kTernaryIfFalse, -} _cel_AstTraverserRecordKind; - -typedef struct { - CEL_NONNULL(const cel_Expr*) expr; - bool previsited; - bool pushed_deps; - bool postvisited; - bool previsited_expr; - bool postvisited_expr; -} _cel_AstTraverserRecordData; - -typedef struct { - _cel_AstTraverserRecordData data; - _cel_AstTraverserRecordKind kind; -} _cel_AstTraverserRecord; - -struct cel_AstTraverser { - _cel_Deque(_cel_AstTraverserRecord) records; - CEL_NONNULL(cel_AstVisitor*) visitor; - _cel_AstTraverserStep step; - bool stepped; - // Is the visitor interested in any {Pre,Post}VisitSelectExpr{...} callbacks? - bool select_operand_callbacks; - // Is the visitor interested in any {Pre,Post}VisitUnaryExpr{...} callbacks? - bool unary_arg_callbacks; - // Is the visitor interested in any {Pre,Post}VisitBinaryExpr{...} callbacks? - bool binary_left_callbacks; - bool binary_right_callbacks; - // Is the visitor interested in any {Pre,Post}VisitTernaryExpr{...} callbacks? - bool ternary_condition_callbacks; - bool ternary_if_true_callbacks; - bool ternary_if_false_callbacks; - // Is the visitor interested in any {Pre,Post}VisitCallExpr{...} callbacks? - bool call_target_callbacks; - // Is the visitor interested in any {Pre,Post}VisitCallArgExpr{...} callbacks? - bool call_arg_value_callbacks; - // Is the visitor interested in any {Pre,Post}VisitListElementExpr{...} - // callbacks? - bool list_element_value_callbacks; - // Is the visitor interested in any {Pre,Post}VisitMapEntryExpr{...} - // callbacks? - bool map_entry_key_callbacks; - bool map_entry_value_callbacks; - // Is the visitor interested in any {Pre,Post}VisitStructFieldExpr{...} - // callbacks? - bool struct_field_value_callbacks; - // Is the visitor interested in any {Pre,Post}VisitComprehensionExpr{...} - // callbacks? - bool comprehension_iter_range_callbacks; - bool comprehension_accu_init_callbacks; - bool comprehension_loop_condition_callbacks; - bool comprehension_loop_step_callbacks; - bool comprehension_result_callbacks; -}; - -CEL_ATTRIBUTE_NODISCARD -static CEL_NULLABLE(_cel_AstTraverserRecord*) - _cel_AstTraverser_Push(CEL_NONNULL(cel_AstTraverser*) traverser, - CEL_NULLABLE(cel_Status*) status) { - _cel_AstTraverserRecord* record = - _cel_Deque_PushBack(&traverser->records, cel_DefaultAllocator); - if (CEL_UNLIKELY(record == cel_nullptr)) { - if (status != cel_nullptr) { - cel_OutOfMemoryStatus(status); - } - return cel_nullptr; - } - memset(record, 0, sizeof(*record)); - return record; -} - -CEL_ATTRIBUTE_NODISCARD -static bool _cel_AstTraverser_PushExpr(CEL_NONNULL(cel_AstTraverser*) traverser, - CEL_NONNULL(const cel_Expr*) expr, - CEL_NULLABLE(cel_Status*) status) { - _cel_AstTraverserRecord* record = _cel_AstTraverser_Push(traverser, status); - if (CEL_UNLIKELY(record == cel_nullptr)) { - return false; - } - record->data.expr = expr; - record->kind = _cel_AstTraverserRecordKind_kExpr; - return true; -} - -CEL_ATTRIBUTE_NODISCARD -static CEL_NULLABLE(_cel_AstTraverserRecord*) - _cel_AstTraverser_Peek(CEL_NONNULL(cel_AstTraverser*) traverser) { - if (_cel_Deque_Empty(&traverser->records)) { - return cel_nullptr; - } - return _cel_Deque_MutablePeekBack(&traverser->records); -} - -static void _cel_AstTraverser_Pop(CEL_NONNULL(cel_AstTraverser*) traverser) { - _cel_Deque_PopBack(&traverser->records, cel_DefaultAllocator); -} - -CEL_ATTRIBUTE_NODISCARD -static _cel_AstVisitorControl _cel_AstTraverserRecord_PreVisit( - CEL_NONNULL(_cel_AstTraverserRecord*) record, - CEL_NONNULL(cel_AstTraverser*) traverser, CEL_NONNULL(cel_Status*) status) { - if (CEL_UNLIKELY(!cel_Status_Ok(status))) { - return _cel_AstVisitorControl_kStop; - } - cel_AstVisitor* visitor = traverser->visitor; - CEL_NONNULL(const cel_Expr*) expr = record->data.expr; - const _cel_AstTraverserRecordKind record_kind = record->kind; - switch (record_kind) { - case _cel_AstTraverserRecordKind_kExpr: { - _cel_AstVisitorControl control = _cel_AstVisitorControl_kContinue; - if (!record->data.previsited_expr) { - control = _cel_AstVisitor_Invoke(visitor, PreVisitExpr, expr); - record->data.previsited_expr = true; - if (traverser->stepped) { - CEL_ASSERT_EQ(control, _cel_AstVisitorControl_kStop); - switch (traverser->step) { - case _cel_AstTraverserStep_kStepIn: - break; - case _cel_AstTraverserStep_kStepOver: - record->data.previsited = true; - record->data.pushed_deps = true; - record->data.postvisited = true; - break; - case _cel_AstTraverserStep_kStepOut: - record->data.previsited = true; - record->data.pushed_deps = true; - record->data.postvisited = true; - record->data.postvisited_expr = true; - break; - default: - CEL_UNREACHABLE(); - } - } - } - if (control != _cel_AstVisitorControl_kContinue) { - return control; - } - if (record->data.previsited) { - return _cel_AstVisitorControl_kContinue; - } - record->data.previsited = true; - switch (cel_Expr_Kind(expr)) { - case cel_ExprKind_kUnspecified: - control = _cel_AstVisitor_Invoke(visitor, VisitUnspecifiedExpr, - cel_UnspecifiedExpr_DownCast(expr)); - break; - case cel_ExprKind_kIdent: - control = _cel_AstVisitor_Invoke(visitor, VisitIdentExpr, - cel_IdentExpr_DownCast(expr)); - break; - case cel_ExprKind_kConst: - control = _cel_AstVisitor_Invoke(visitor, VisitConstExpr, - cel_ConstExpr_DownCast(expr)); - break; - case cel_ExprKind_kSelect: - control = _cel_AstVisitor_Invoke(visitor, PreVisitSelectExpr, - cel_SelectExpr_DownCast(expr)); - break; - case cel_ExprKind_kCallArg: - control = _cel_AstVisitor_Invoke(visitor, PreVisitCallArgExpr, - cel_CallArgExpr_DownCast(expr)); - break; - case cel_ExprKind_kCall: - control = _cel_AstVisitor_Invoke(visitor, PreVisitCallExpr, - cel_CallExpr_DownCast(expr)); - break; - case cel_ExprKind_kListElement: - control = _cel_AstVisitor_Invoke(visitor, PreVisitListElementExpr, - cel_ListElementExpr_DownCast(expr)); - break; - case cel_ExprKind_kList: - control = _cel_AstVisitor_Invoke(visitor, PreVisitListExpr, - cel_ListExpr_DownCast(expr)); - break; - case cel_ExprKind_kMapEntry: - control = _cel_AstVisitor_Invoke(visitor, PreVisitMapEntryExpr, - cel_MapEntryExpr_DownCast(expr)); - break; - case cel_ExprKind_kMap: - control = _cel_AstVisitor_Invoke(visitor, PreVisitMapExpr, - cel_MapExpr_DownCast(expr)); - break; - case cel_ExprKind_kStructField: - control = _cel_AstVisitor_Invoke(visitor, PreVisitStructFieldExpr, - cel_StructFieldExpr_DownCast(expr)); - break; - case cel_ExprKind_kStruct: - control = _cel_AstVisitor_Invoke(visitor, PreVisitStructExpr, - cel_StructExpr_DownCast(expr)); - break; - case cel_ExprKind_kComprehension: - control = - _cel_AstVisitor_Invoke(visitor, PreVisitComprehensionExpr, - cel_ComprehensionExpr_DownCast(expr)); - break; - case cel_ExprKind_kUnary: - control = _cel_AstVisitor_Invoke(visitor, PreVisitUnaryExpr, - cel_UnaryExpr_DownCast(expr)); - break; - case cel_ExprKind_kBinary: - control = _cel_AstVisitor_Invoke(visitor, PreVisitBinaryExpr, - cel_BinaryExpr_DownCast(expr)); - break; - case cel_ExprKind_kTernary: - control = _cel_AstVisitor_Invoke(visitor, PreVisitTernaryExpr, - cel_TernaryExpr_DownCast(expr)); - break; - default: - cel_InternalStatus(status, - cel_StringView_From("unexpected AST node kind")); - control = _cel_AstVisitorControl_kStop; - break; - } - if (traverser->stepped) { - CEL_ASSERT_EQ(control, _cel_AstVisitorControl_kStop); - switch (traverser->step) { - case _cel_AstTraverserStep_kStepIn: - break; - case _cel_AstTraverserStep_kStepOver: - record->data.pushed_deps = true; - break; - case _cel_AstTraverserStep_kStepOut: - record->data.pushed_deps = true; - record->data.postvisited = true; - break; - default: - CEL_UNREACHABLE(); - } - } - return control; - } - default: - record->data.previsited = record->data.previsited_expr = true; - break; - } - _cel_AstVisitorControl control = _cel_AstVisitorControl_kContinue; - switch (record_kind) { - case _cel_AstTraverserRecordKind_kSelectOperand: { - control = - _cel_AstVisitor_Invoke(visitor, PreVisitSelectExprOperand, expr); - break; - } - case _cel_AstTraverserRecordKind_kCallTarget: { - control = _cel_AstVisitor_Invoke(visitor, PreVisitCallExprTarget, expr); - break; - } - case _cel_AstTraverserRecordKind_kCallArgValue: { - control = _cel_AstVisitor_Invoke(visitor, PreVisitCallArgExprValue, expr); - break; - } - case _cel_AstTraverserRecordKind_kListElementValue: { - control = - _cel_AstVisitor_Invoke(visitor, PreVisitListElementExprValue, expr); - break; - } - case _cel_AstTraverserRecordKind_kMapEntryKey: { - control = _cel_AstVisitor_Invoke(visitor, PreVisitMapEntryExprKey, expr); - break; - } - case _cel_AstTraverserRecordKind_kMapEntryValue: { - control = - _cel_AstVisitor_Invoke(visitor, PreVisitMapEntryExprValue, expr); - break; - } - case _cel_AstTraverserRecordKind_kStructFieldValue: { - control = - _cel_AstVisitor_Invoke(visitor, PreVisitStructFieldExprValue, expr); - break; - } - case _cel_AstTraverserRecordKind_kComprehensionIterRange: { - control = _cel_AstVisitor_Invoke( - visitor, PreVisitComprehensionExprIterRange, expr); - break; - } - case _cel_AstTraverserRecordKind_kComprehensionAccuInit: { - control = _cel_AstVisitor_Invoke(visitor, - PreVisitComprehensionExprAccuInit, expr); - break; - } - case _cel_AstTraverserRecordKind_kComprehensionLoopCondition: { - control = _cel_AstVisitor_Invoke( - visitor, PreVisitComprehensionExprLoopCondition, expr); - break; - } - case _cel_AstTraverserRecordKind_kComprehensionLoopStep: { - control = _cel_AstVisitor_Invoke(visitor, - PreVisitComprehensionExprLoopStep, expr); - break; - } - case _cel_AstTraverserRecordKind_kComprehensionResult: { - control = _cel_AstVisitor_Invoke(visitor, PreVisitComprehensionExprResult, - expr); - break; - } - case _cel_AstTraverserRecordKind_kUnaryArg: { - control = _cel_AstVisitor_Invoke(visitor, PreVisitUnaryExprArg, expr); - break; - } - case _cel_AstTraverserRecordKind_kBinaryLeft: { - control = _cel_AstVisitor_Invoke(visitor, PreVisitBinaryExprLeft, expr); - break; - } - case _cel_AstTraverserRecordKind_kBinaryRight: { - control = _cel_AstVisitor_Invoke(visitor, PreVisitBinaryExprRight, expr); - break; - } - case _cel_AstTraverserRecordKind_kTernaryCondition: { - control = - _cel_AstVisitor_Invoke(visitor, PreVisitTernaryExprCondition, expr); - break; - } - case _cel_AstTraverserRecordKind_kTernaryIfTrue: { - control = - _cel_AstVisitor_Invoke(visitor, PreVisitTernaryExprIfTrue, expr); - break; - } - case _cel_AstTraverserRecordKind_kTernaryIfFalse: { - control = - _cel_AstVisitor_Invoke(visitor, PreVisitTernaryExprIfFalse, expr); - break; - } - default: - CEL_UNREACHABLE(); - } - if (traverser->stepped) { - CEL_ASSERT_EQ(control, _cel_AstVisitorControl_kStop); - switch (traverser->step) { - case _cel_AstTraverserStep_kStepIn: - break; - case _cel_AstTraverserStep_kStepOver: - record->data.pushed_deps = true; - break; - case _cel_AstTraverserStep_kStepOut: - record->data.pushed_deps = true; - record->data.postvisited = true; - record->data.postvisited_expr = true; - break; - default: - CEL_UNREACHABLE(); - } - } - return control; -} - -CEL_ATTRIBUTE_NODISCARD -static _cel_AstVisitorControl _cel_AstTraverserRecord_PostVisit( - CEL_NONNULL(_cel_AstTraverserRecord*) record, - CEL_NONNULL(cel_AstTraverser*) traverser, CEL_NONNULL(cel_Status*) status) { - if (CEL_UNLIKELY(!cel_Status_Ok(status))) { - return _cel_AstVisitorControl_kStop; - } - cel_AstVisitor* visitor = traverser->visitor; - CEL_NONNULL(const cel_Expr*) expr = record->data.expr; - const _cel_AstTraverserRecordKind record_kind = record->kind; - switch (record_kind) { - case _cel_AstTraverserRecordKind_kExpr: { - _cel_AstVisitorControl control = _cel_AstVisitorControl_kContinue; - if (!record->data.postvisited) { - record->data.postvisited = true; - switch (cel_Expr_Kind(expr)) { - case cel_ExprKind_kUnspecified: - CEL_ATTRIBUTE_FALLTHROUGH; - case cel_ExprKind_kIdent: - CEL_ATTRIBUTE_FALLTHROUGH; - case cel_ExprKind_kConst: - break; - case cel_ExprKind_kSelect: - control = _cel_AstVisitor_Invoke(visitor, PostVisitSelectExpr, - cel_SelectExpr_DownCast(expr)); - break; - case cel_ExprKind_kCallArg: - control = _cel_AstVisitor_Invoke(visitor, PostVisitCallArgExpr, - cel_CallArgExpr_DownCast(expr)); - break; - case cel_ExprKind_kCall: - control = _cel_AstVisitor_Invoke(visitor, PostVisitCallExpr, - cel_CallExpr_DownCast(expr)); - break; - case cel_ExprKind_kListElement: - control = - _cel_AstVisitor_Invoke(visitor, PostVisitListElementExpr, - cel_ListElementExpr_DownCast(expr)); - break; - case cel_ExprKind_kList: - control = _cel_AstVisitor_Invoke(visitor, PostVisitListExpr, - cel_ListExpr_DownCast(expr)); - break; - case cel_ExprKind_kMapEntry: - control = _cel_AstVisitor_Invoke(visitor, PostVisitMapEntryExpr, - cel_MapEntryExpr_DownCast(expr)); - break; - case cel_ExprKind_kMap: - control = _cel_AstVisitor_Invoke(visitor, PostVisitMapExpr, - cel_MapExpr_DownCast(expr)); - break; - case cel_ExprKind_kStructField: - control = - _cel_AstVisitor_Invoke(visitor, PostVisitStructFieldExpr, - cel_StructFieldExpr_DownCast(expr)); - break; - case cel_ExprKind_kStruct: - control = _cel_AstVisitor_Invoke(visitor, PostVisitStructExpr, - cel_StructExpr_DownCast(expr)); - break; - case cel_ExprKind_kComprehension: - control = - _cel_AstVisitor_Invoke(visitor, PostVisitComprehensionExpr, - cel_ComprehensionExpr_DownCast(expr)); - break; - case cel_ExprKind_kUnary: - control = _cel_AstVisitor_Invoke(visitor, PostVisitUnaryExpr, - cel_UnaryExpr_DownCast(expr)); - break; - case cel_ExprKind_kBinary: - control = _cel_AstVisitor_Invoke(visitor, PostVisitBinaryExpr, - cel_BinaryExpr_DownCast(expr)); - break; - case cel_ExprKind_kTernary: - control = _cel_AstVisitor_Invoke(visitor, PostVisitTernaryExpr, - cel_TernaryExpr_DownCast(expr)); - break; - default: - record->data.postvisited = false; - cel_InternalStatus(status, - cel_StringView_From("unexpected AST node kind")); - control = _cel_AstVisitorControl_kStop; - break; - } - } - if (control != _cel_AstVisitorControl_kContinue) { - return control; - } - if (record->data.postvisited_expr) { - return _cel_AstVisitorControl_kContinue; - } - record->data.postvisited_expr = true; - return _cel_AstVisitor_Invoke(visitor, PostVisitExpr, expr); - } - default: - if (record->data.postvisited || record->data.postvisited_expr) { - record->data.postvisited = record->data.postvisited_expr = true; - return _cel_AstVisitorControl_kContinue; - } - record->data.postvisited = record->data.postvisited_expr = true; - break; - } - _cel_AstVisitorControl control = _cel_AstVisitorControl_kContinue; - switch (record_kind) { - case _cel_AstTraverserRecordKind_kSelectOperand: { - control = - _cel_AstVisitor_Invoke(visitor, PostVisitSelectExprOperand, expr); - break; - } - case _cel_AstTraverserRecordKind_kCallTarget: { - control = _cel_AstVisitor_Invoke(visitor, PostVisitCallExprTarget, expr); - break; - } - case _cel_AstTraverserRecordKind_kCallArgValue: { - control = - _cel_AstVisitor_Invoke(visitor, PostVisitCallArgExprValue, expr); - break; - } - case _cel_AstTraverserRecordKind_kListElementValue: { - control = - _cel_AstVisitor_Invoke(visitor, PostVisitListElementExprValue, expr); - break; - } - case _cel_AstTraverserRecordKind_kMapEntryKey: { - control = _cel_AstVisitor_Invoke(visitor, PostVisitMapEntryExprKey, expr); - break; - } - case _cel_AstTraverserRecordKind_kMapEntryValue: { - control = - _cel_AstVisitor_Invoke(visitor, PostVisitMapEntryExprValue, expr); - break; - } - case _cel_AstTraverserRecordKind_kStructFieldValue: { - control = - _cel_AstVisitor_Invoke(visitor, PostVisitStructFieldExprValue, expr); - break; - } - case _cel_AstTraverserRecordKind_kComprehensionIterRange: { - control = _cel_AstVisitor_Invoke( - visitor, PostVisitComprehensionExprIterRange, expr); - break; - } - case _cel_AstTraverserRecordKind_kComprehensionAccuInit: { - control = _cel_AstVisitor_Invoke( - visitor, PostVisitComprehensionExprAccuInit, expr); - break; - } - case _cel_AstTraverserRecordKind_kComprehensionLoopCondition: { - control = _cel_AstVisitor_Invoke( - visitor, PostVisitComprehensionExprLoopCondition, expr); - break; - } - case _cel_AstTraverserRecordKind_kComprehensionLoopStep: { - control = _cel_AstVisitor_Invoke( - visitor, PostVisitComprehensionExprLoopStep, expr); - break; - } - case _cel_AstTraverserRecordKind_kComprehensionResult: { - control = _cel_AstVisitor_Invoke(visitor, - PostVisitComprehensionExprResult, expr); - break; - } - case _cel_AstTraverserRecordKind_kUnaryArg: { - control = _cel_AstVisitor_Invoke(visitor, PostVisitUnaryExprArg, expr); - break; - } - case _cel_AstTraverserRecordKind_kBinaryLeft: { - control = _cel_AstVisitor_Invoke(visitor, PostVisitBinaryExprLeft, expr); - break; - } - case _cel_AstTraverserRecordKind_kBinaryRight: { - control = _cel_AstVisitor_Invoke(visitor, PostVisitBinaryExprRight, expr); - break; - } - case _cel_AstTraverserRecordKind_kTernaryCondition: { - control = - _cel_AstVisitor_Invoke(visitor, PostVisitTernaryExprCondition, expr); - break; - } - case _cel_AstTraverserRecordKind_kTernaryIfFalse: { - control = - _cel_AstVisitor_Invoke(visitor, PostVisitTernaryExprIfFalse, expr); - break; - } - case _cel_AstTraverserRecordKind_kTernaryIfTrue: { - control = - _cel_AstVisitor_Invoke(visitor, PostVisitTernaryExprIfTrue, expr); - break; - } - default: - CEL_UNREACHABLE(); - } - if (traverser->stepped) { - CEL_ASSERT_EQ(control, _cel_AstVisitorControl_kStop); - switch (traverser->step) { - case _cel_AstTraverserStep_kStepIn: - break; - case _cel_AstTraverserStep_kStepOver: - CEL_ATTRIBUTE_FALLTHROUGH; - case _cel_AstTraverserStep_kStepOut: - record->data.postvisited = true; - record->data.postvisited_expr = true; - break; - default: - CEL_UNREACHABLE(); - } - } - return control; -} - -CEL_ATTRIBUTE_NODISCARD -static bool _cel_AstTraverser_PushSelectOperand(CEL_NONNULL(cel_AstTraverser*) - traverser, - CEL_NONNULL(const cel_Expr*) - select_operand, - CEL_NONNULL(cel_Status*) - status) { - _cel_AstTraverserRecord* record = _cel_AstTraverser_Push(traverser, status); - if (CEL_UNLIKELY(record == cel_nullptr)) { - return false; - } - record->data.expr = select_operand; - record->kind = traverser->select_operand_callbacks - ? _cel_AstTraverserRecordKind_kSelectOperand - : _cel_AstTraverserRecordKind_kExpr; - return true; -} - -CEL_ATTRIBUTE_NODISCARD -static bool _cel_AstTraverser_PushCallTarget(CEL_NONNULL(cel_AstTraverser*) - traverser, - CEL_NONNULL(const cel_Expr*) - call_target, - CEL_NONNULL(cel_Status*) status) { - _cel_AstTraverserRecord* record = _cel_AstTraverser_Push(traverser, status); - if (CEL_UNLIKELY(record == cel_nullptr)) { - return false; - } - record->data.expr = call_target; - record->kind = traverser->call_target_callbacks - ? _cel_AstTraverserRecordKind_kCallTarget - : _cel_AstTraverserRecordKind_kExpr; - return true; -} - -CEL_ATTRIBUTE_NODISCARD -static bool _cel_AstTraverser_PushCallArgValue(CEL_NONNULL(cel_AstTraverser*) - traverser, - CEL_NONNULL(const cel_Expr*) - call_arg_value, - CEL_NONNULL(cel_Status*) - status) { - _cel_AstTraverserRecord* record = _cel_AstTraverser_Push(traverser, status); - if (CEL_UNLIKELY(record == cel_nullptr)) { - return false; - } - record->data.expr = call_arg_value; - record->kind = traverser->call_arg_value_callbacks - ? _cel_AstTraverserRecordKind_kCallArgValue - : _cel_AstTraverserRecordKind_kExpr; - return true; -} - -CEL_ATTRIBUTE_NODISCARD -static bool _cel_AstTraverser_PushListElementValue( - CEL_NONNULL(cel_AstTraverser*) traverser, - CEL_NONNULL(const cel_Expr*) list_element_value, - CEL_NONNULL(cel_Status*) status) { - _cel_AstTraverserRecord* record = _cel_AstTraverser_Push(traverser, status); - if (CEL_UNLIKELY(record == cel_nullptr)) { - return false; - } - record->data.expr = list_element_value; - record->kind = traverser->list_element_value_callbacks - ? _cel_AstTraverserRecordKind_kListElementValue - : _cel_AstTraverserRecordKind_kExpr; - return true; -} - -CEL_ATTRIBUTE_NODISCARD -static bool _cel_AstTraverser_PushMapEntryKey(CEL_NONNULL(cel_AstTraverser*) - traverser, - CEL_NONNULL(const cel_Expr*) - map_entry_key, - CEL_NONNULL(cel_Status*) status) { - _cel_AstTraverserRecord* record = _cel_AstTraverser_Push(traverser, status); - if (CEL_UNLIKELY(record == cel_nullptr)) { - return false; - } - record->data.expr = map_entry_key; - record->kind = traverser->map_entry_key_callbacks - ? _cel_AstTraverserRecordKind_kMapEntryKey - : _cel_AstTraverserRecordKind_kExpr; - return true; -} - -CEL_ATTRIBUTE_NODISCARD -static bool _cel_AstTraverser_PushMapEntryValue(CEL_NONNULL(cel_AstTraverser*) - traverser, - CEL_NONNULL(const cel_Expr*) - map_entry_value, - CEL_NONNULL(cel_Status*) - status) { - _cel_AstTraverserRecord* record = _cel_AstTraverser_Push(traverser, status); - if (CEL_UNLIKELY(record == cel_nullptr)) { - return false; - } - record->data.expr = map_entry_value; - record->kind = traverser->map_entry_value_callbacks - ? _cel_AstTraverserRecordKind_kMapEntryValue - : _cel_AstTraverserRecordKind_kExpr; - return true; -} - -CEL_ATTRIBUTE_NODISCARD -static bool _cel_AstTraverser_PushStructFieldValue( - CEL_NONNULL(cel_AstTraverser*) traverser, - CEL_NONNULL(const cel_Expr*) struct_field_value, - CEL_NONNULL(cel_Status*) status) { - _cel_AstTraverserRecord* record = _cel_AstTraverser_Push(traverser, status); - if (CEL_UNLIKELY(record == cel_nullptr)) { - return false; - } - record->data.expr = struct_field_value; - record->kind = traverser->struct_field_value_callbacks - ? _cel_AstTraverserRecordKind_kStructFieldValue - : _cel_AstTraverserRecordKind_kExpr; - return true; -} - -CEL_ATTRIBUTE_NODISCARD -static bool _cel_AstTraverser_PushComprehensionIterRange( - CEL_NONNULL(cel_AstTraverser*) traverser, - CEL_NONNULL(const cel_Expr*) iter_range, CEL_NONNULL(cel_Status*) status) { - _cel_AstTraverserRecord* record = _cel_AstTraverser_Push(traverser, status); - if (CEL_UNLIKELY(record == cel_nullptr)) { - return false; - } - record->data.expr = iter_range; - record->kind = traverser->comprehension_iter_range_callbacks - ? _cel_AstTraverserRecordKind_kComprehensionIterRange - : _cel_AstTraverserRecordKind_kExpr; - return true; -} - -CEL_ATTRIBUTE_NODISCARD -static bool _cel_AstTraverser_PushComprehensionAccuInit( - CEL_NONNULL(cel_AstTraverser*) traverser, - CEL_NONNULL(const cel_Expr*) accu_init, CEL_NONNULL(cel_Status*) status) { - _cel_AstTraverserRecord* record = _cel_AstTraverser_Push(traverser, status); - if (CEL_UNLIKELY(record == cel_nullptr)) { - return false; - } - record->data.expr = accu_init; - record->kind = traverser->comprehension_accu_init_callbacks - ? _cel_AstTraverserRecordKind_kComprehensionAccuInit - : _cel_AstTraverserRecordKind_kExpr; - return true; -} - -CEL_ATTRIBUTE_NODISCARD -static bool _cel_AstTraverser_PushComprehensionLoopCondition( - CEL_NONNULL(cel_AstTraverser*) traverser, - CEL_NONNULL(const cel_Expr*) loop_condition, - CEL_NONNULL(cel_Status*) status) { - _cel_AstTraverserRecord* record = _cel_AstTraverser_Push(traverser, status); - if (CEL_UNLIKELY(record == cel_nullptr)) { - return false; - } - record->data.expr = loop_condition; - record->kind = traverser->comprehension_loop_condition_callbacks - ? _cel_AstTraverserRecordKind_kComprehensionLoopCondition - : _cel_AstTraverserRecordKind_kExpr; - return true; -} - -CEL_ATTRIBUTE_NODISCARD -static bool _cel_AstTraverser_PushComprehensionLoopStep( - CEL_NONNULL(cel_AstTraverser*) traverser, - CEL_NONNULL(const cel_Expr*) loop_step, CEL_NONNULL(cel_Status*) status) { - _cel_AstTraverserRecord* record = _cel_AstTraverser_Push(traverser, status); - if (CEL_UNLIKELY(record == cel_nullptr)) { - return false; - } - record->data.expr = loop_step; - record->kind = traverser->comprehension_loop_step_callbacks - ? _cel_AstTraverserRecordKind_kComprehensionLoopStep - : _cel_AstTraverserRecordKind_kExpr; - return true; -} - -CEL_ATTRIBUTE_NODISCARD -static bool _cel_AstTraverser_PushComprehensionResult( - CEL_NONNULL(cel_AstTraverser*) traverser, - CEL_NONNULL(const cel_Expr*) result, CEL_NONNULL(cel_Status*) status) { - _cel_AstTraverserRecord* record = _cel_AstTraverser_Push(traverser, status); - if (CEL_UNLIKELY(record == cel_nullptr)) { - return false; - } - record->data.expr = result; - record->kind = traverser->comprehension_result_callbacks - ? _cel_AstTraverserRecordKind_kComprehensionResult - : _cel_AstTraverserRecordKind_kExpr; - return true; -} - -CEL_ATTRIBUTE_NODISCARD -static bool _cel_AstTraverser_PushUnaryArg(CEL_NONNULL(cel_AstTraverser*) - traverser, - CEL_NONNULL(const cel_Expr*) result, - CEL_NONNULL(cel_Status*) status) { - _cel_AstTraverserRecord* record = _cel_AstTraverser_Push(traverser, status); - if (CEL_UNLIKELY(record == cel_nullptr)) { - return false; - } - record->data.expr = result; - record->kind = traverser->unary_arg_callbacks - ? _cel_AstTraverserRecordKind_kUnaryArg - : _cel_AstTraverserRecordKind_kExpr; - return true; -} - -CEL_ATTRIBUTE_NODISCARD -static bool _cel_AstTraverser_PushBinaryLeft(CEL_NONNULL(cel_AstTraverser*) - traverser, - CEL_NONNULL(const cel_Expr*) - result, - CEL_NONNULL(cel_Status*) status) { - _cel_AstTraverserRecord* record = _cel_AstTraverser_Push(traverser, status); - if (CEL_UNLIKELY(record == cel_nullptr)) { - return false; - } - record->data.expr = result; - record->kind = traverser->binary_left_callbacks - ? _cel_AstTraverserRecordKind_kBinaryLeft - : _cel_AstTraverserRecordKind_kExpr; - return true; -} - -CEL_ATTRIBUTE_NODISCARD -static bool _cel_AstTraverser_PushBinaryRight(CEL_NONNULL(cel_AstTraverser*) - traverser, - CEL_NONNULL(const cel_Expr*) - result, - CEL_NONNULL(cel_Status*) status) { - _cel_AstTraverserRecord* record = _cel_AstTraverser_Push(traverser, status); - if (CEL_UNLIKELY(record == cel_nullptr)) { - return false; - } - record->data.expr = result; - record->kind = traverser->binary_right_callbacks - ? _cel_AstTraverserRecordKind_kBinaryRight - : _cel_AstTraverserRecordKind_kExpr; - return true; -} - -CEL_ATTRIBUTE_NODISCARD -static bool _cel_AstTraverser_PushTernaryCondition( - CEL_NONNULL(cel_AstTraverser*) traverser, - CEL_NONNULL(const cel_Expr*) result, CEL_NONNULL(cel_Status*) status) { - _cel_AstTraverserRecord* record = _cel_AstTraverser_Push(traverser, status); - if (CEL_UNLIKELY(record == cel_nullptr)) { - return false; - } - record->data.expr = result; - record->kind = traverser->ternary_condition_callbacks - ? _cel_AstTraverserRecordKind_kTernaryCondition - : _cel_AstTraverserRecordKind_kExpr; - return true; -} - -CEL_ATTRIBUTE_NODISCARD -static bool _cel_AstTraverser_PushTernaryIfTrue( - CEL_NONNULL(cel_AstTraverser*) traverser, - CEL_NONNULL(const cel_Expr*) result, CEL_NONNULL(cel_Status*) status) { - _cel_AstTraverserRecord* record = _cel_AstTraverser_Push(traverser, status); - if (CEL_UNLIKELY(record == cel_nullptr)) { - return false; - } - record->data.expr = result; - record->kind = traverser->ternary_if_true_callbacks - ? _cel_AstTraverserRecordKind_kTernaryIfTrue - : _cel_AstTraverserRecordKind_kExpr; - return true; -} - -CEL_ATTRIBUTE_NODISCARD -static bool _cel_AstTraverser_PushTernaryIfFalse( - CEL_NONNULL(cel_AstTraverser*) traverser, - CEL_NONNULL(const cel_Expr*) result, CEL_NONNULL(cel_Status*) status) { - _cel_AstTraverserRecord* record = _cel_AstTraverser_Push(traverser, status); - if (CEL_UNLIKELY(record == cel_nullptr)) { - return false; - } - record->data.expr = result; - record->kind = traverser->ternary_if_false_callbacks - ? _cel_AstTraverserRecordKind_kTernaryIfFalse - : _cel_AstTraverserRecordKind_kExpr; - return true; -} - -CEL_ATTRIBUTE_NODISCARD -static bool _cel_AstTraverser_PushSelectDeps(CEL_NONNULL(cel_AstTraverser*) - traverser, - const cel_SelectExpr* select_expr, - CEL_NONNULL(cel_Status*) status) { - CEL_NULLABLE(cel_Expr*) operand = cel_SelectExpr_Operand(select_expr); - if (operand != cel_nullptr) { - if (!_cel_AstTraverser_PushSelectOperand(traverser, operand, status)) { - return false; - } - } - return true; -} - -CEL_ATTRIBUTE_NODISCARD -static bool _cel_AstTraverser_PushCallArgDeps( - CEL_NONNULL(cel_AstTraverser*) traverser, - const cel_CallArgExpr* call_arg_expr, CEL_NONNULL(cel_Status*) status) { - CEL_NULLABLE(cel_Expr*) value = cel_CallArgExpr_Value(call_arg_expr); - if (value != cel_nullptr) { - if (!_cel_AstTraverser_PushCallArgValue(traverser, value, status)) { - return false; - } - } - return true; -} - -CEL_ATTRIBUTE_NODISCARD -static bool _cel_AstTraverser_PushCallDeps(CEL_NONNULL(cel_AstTraverser*) - traverser, - const cel_CallExpr* call_expr, - CEL_NONNULL(cel_Status*) status) { - CEL_NULLABLE(cel_CallArgExpr*) arg; - size_t call_expr_args_size = - cel_CallExpr_Args(call_expr, /*head=*/cel_nullptr, &arg); - for (size_t i = call_expr_args_size; i > 0; --i) { - if (!_cel_AstTraverser_PushExpr(traverser, cel_Expr_UpCast(arg), status)) { - return false; - } - arg = cel_CallExpr_PrevArg(arg); - } - CEL_NULLABLE(cel_Expr*) target = cel_CallExpr_Target(call_expr); - if (target != cel_nullptr) { - if (!_cel_AstTraverser_PushCallTarget(traverser, target, status)) { - return false; - } - } - return true; -} - -CEL_ATTRIBUTE_NODISCARD -static bool _cel_AstTraverser_PushListElementDeps( - CEL_NONNULL(cel_AstTraverser*) traverser, - const cel_ListElementExpr* list_element_expr, - CEL_NONNULL(cel_Status*) status) { - CEL_NULLABLE(cel_Expr*) value = cel_ListElementExpr_Value(list_element_expr); - if (value != cel_nullptr) { - if (!_cel_AstTraverser_PushListElementValue(traverser, value, status)) { - return false; - } - } - return true; -} - -CEL_ATTRIBUTE_NODISCARD -static bool _cel_AstTraverser_PushListDeps(CEL_NONNULL(cel_AstTraverser*) - traverser, - const cel_ListExpr* list_expr, - CEL_NONNULL(cel_Status*) status) { - CEL_NULLABLE(cel_ListElementExpr*) elem; - size_t list_expr_elements_size = - cel_ListExpr_Elements(list_expr, /*head=*/cel_nullptr, &elem); - for (size_t i = list_expr_elements_size; i > 0; --i) { - if (!_cel_AstTraverser_PushExpr(traverser, cel_Expr_UpCast(elem), status)) { - return false; - } - elem = cel_ListExpr_PrevElement(elem); - } - return true; -} - -CEL_ATTRIBUTE_NODISCARD -static bool _cel_AstTraverser_PushMapEntryDeps( - CEL_NONNULL(cel_AstTraverser*) traverser, - const cel_MapEntryExpr* map_entry_expr, CEL_NONNULL(cel_Status*) status) { - CEL_NULLABLE(cel_Expr*) value = cel_MapEntryExpr_Value(map_entry_expr); - if (value != cel_nullptr) { - if (!_cel_AstTraverser_PushMapEntryValue(traverser, value, status)) { - return false; - } - } - CEL_NULLABLE(cel_Expr*) key = cel_MapEntryExpr_Key(map_entry_expr); - if (key != cel_nullptr) { - if (!_cel_AstTraverser_PushMapEntryKey(traverser, key, status)) { - return false; - } - } - return true; -} - -CEL_ATTRIBUTE_NODISCARD -static bool _cel_AstTraverser_PushMapDeps(CEL_NONNULL(cel_AstTraverser*) - traverser, - const cel_MapExpr* map_expr, - CEL_NONNULL(cel_Status*) status) { - CEL_NULLABLE(cel_MapEntryExpr*) ent; - size_t struct_expr_entries_size = - cel_MapExpr_Entries(map_expr, /*head=*/cel_nullptr, &ent); - for (size_t i = struct_expr_entries_size; i > 0; --i) { - if (!_cel_AstTraverser_PushExpr(traverser, cel_Expr_UpCast(ent), status)) { - return false; - } - ent = cel_MapExpr_PrevEntry(ent); - } - return true; -} - -CEL_ATTRIBUTE_NODISCARD -static bool _cel_AstTraverser_PushStructFieldDeps( - CEL_NONNULL(cel_AstTraverser*) traverser, - const cel_StructFieldExpr* struct_field_expr, - CEL_NONNULL(cel_Status*) status) { - CEL_NULLABLE(cel_Expr*) value = cel_StructFieldExpr_Value(struct_field_expr); - if (value != cel_nullptr) { - if (!_cel_AstTraverser_PushStructFieldValue(traverser, value, status)) { - return false; - } - } - return true; -} - -CEL_ATTRIBUTE_NODISCARD -static bool _cel_AstTraverser_PushStructDeps(CEL_NONNULL(cel_AstTraverser*) - traverser, - const cel_StructExpr* struct_expr, - CEL_NONNULL(cel_Status*) status) { - CEL_NULLABLE(cel_StructFieldExpr*) fld; - size_t struct_expr_entries_size = - cel_StructExpr_Fields(struct_expr, /*head=*/cel_nullptr, &fld); - for (size_t i = struct_expr_entries_size; i > 0; --i) { - if (!_cel_AstTraverser_PushExpr(traverser, cel_Expr_UpCast(fld), status)) { - return false; - } - fld = cel_StructExpr_PrevField(fld); - } - return true; -} - -CEL_ATTRIBUTE_NODISCARD -static bool _cel_AstTraverser_PushComprehensionDeps( - CEL_NONNULL(cel_AstTraverser*) traverser, - const cel_ComprehensionExpr* comprehension_expr, - CEL_NONNULL(cel_Status*) status) { - CEL_NULLABLE(cel_Expr*) - result = cel_ComprehensionExpr_Result(comprehension_expr); - if (result != cel_nullptr) { - if (!_cel_AstTraverser_PushComprehensionResult(traverser, result, status)) { - return false; - } - } - CEL_NULLABLE(cel_Expr*) - loop_step = cel_ComprehensionExpr_LoopStep(comprehension_expr); - if (loop_step != cel_nullptr) { - if (!_cel_AstTraverser_PushComprehensionLoopStep(traverser, loop_step, - status)) { - return false; - } - } - CEL_NULLABLE(cel_Expr*) - loop_condition = cel_ComprehensionExpr_LoopCondition(comprehension_expr); - if (loop_condition != cel_nullptr) { - if (!_cel_AstTraverser_PushComprehensionLoopCondition( - traverser, loop_condition, status)) { - return false; - } - } - CEL_NULLABLE(cel_Expr*) - accu_init = cel_ComprehensionExpr_AccuInit(comprehension_expr); - if (accu_init != cel_nullptr) { - if (!_cel_AstTraverser_PushComprehensionAccuInit(traverser, accu_init, - status)) { - return false; - } - } - CEL_NULLABLE(cel_Expr*) - iter_range = cel_ComprehensionExpr_IterRange(comprehension_expr); - if (iter_range != cel_nullptr) { - if (!_cel_AstTraverser_PushComprehensionIterRange(traverser, iter_range, - status)) { - return false; - } - } - return true; -} - -CEL_ATTRIBUTE_NODISCARD -static bool _cel_AstTraverser_PushUnaryDeps(CEL_NONNULL(cel_AstTraverser*) - traverser, - const cel_UnaryExpr* unary_expr, - CEL_NONNULL(cel_Status*) status) { - CEL_NULLABLE(cel_Expr*) arg = cel_UnaryExpr_Arg(unary_expr); - if (arg != cel_nullptr) { - if (!_cel_AstTraverser_PushUnaryArg(traverser, arg, status)) { - return false; - } - } - return true; -} - -CEL_ATTRIBUTE_NODISCARD -static bool _cel_AstTraverser_PushBinaryDeps(CEL_NONNULL(cel_AstTraverser*) - traverser, - const cel_BinaryExpr* binary_expr, - CEL_NONNULL(cel_Status*) status) { - CEL_NULLABLE(cel_Expr*) right = cel_BinaryExpr_Right(binary_expr); - if (right != cel_nullptr) { - if (!_cel_AstTraverser_PushBinaryRight(traverser, right, status)) { - return false; - } - } - CEL_NULLABLE(cel_Expr*) left = cel_BinaryExpr_Left(binary_expr); - if (left != cel_nullptr) { - if (!_cel_AstTraverser_PushBinaryLeft(traverser, left, status)) { - return false; - } - } - return true; -} - -CEL_ATTRIBUTE_NODISCARD -static bool _cel_AstTraverser_PushTernaryDeps( - CEL_NONNULL(cel_AstTraverser*) traverser, - const cel_TernaryExpr* ternary_expr, CEL_NONNULL(cel_Status*) status) { - CEL_NULLABLE(cel_Expr*) if_false = cel_TernaryExpr_IfFalse(ternary_expr); - if (if_false != cel_nullptr) { - if (!_cel_AstTraverser_PushTernaryIfFalse(traverser, if_false, status)) { - return false; - } - } - CEL_NULLABLE(cel_Expr*) if_true = cel_TernaryExpr_IfTrue(ternary_expr); - if (if_true != cel_nullptr) { - if (!_cel_AstTraverser_PushTernaryIfTrue(traverser, if_true, status)) { - return false; - } - } - CEL_NULLABLE(cel_Expr*) condition = cel_TernaryExpr_Condition(ternary_expr); - if (condition != cel_nullptr) { - if (!_cel_AstTraverser_PushTernaryCondition(traverser, condition, status)) { - return false; - } - } - return true; -} - -CEL_ATTRIBUTE_NODISCARD -static bool _cel_AstTraverser_PushDeps(CEL_NONNULL(cel_AstTraverser*) traverser, - CEL_NONNULL(_cel_AstTraverserRecord*) - record, - CEL_NONNULL(cel_Status*) status) { - CEL_NONNULL(const cel_Expr*) expr = record->data.expr; - switch (record->kind) { - case _cel_AstTraverserRecordKind_kExpr: { - switch (cel_Expr_Kind(expr)) { - case cel_ExprKind_kUnspecified: - break; - case cel_ExprKind_kIdent: - break; - case cel_ExprKind_kConst: - break; - case cel_ExprKind_kSelect: - return _cel_AstTraverser_PushSelectDeps( - traverser, cel_SelectExpr_DownCast(expr), status); - case cel_ExprKind_kCallArg: - return _cel_AstTraverser_PushCallArgDeps( - traverser, cel_CallArgExpr_DownCast(expr), status); - case cel_ExprKind_kCall: - return _cel_AstTraverser_PushCallDeps( - traverser, cel_CallExpr_DownCast(expr), status); - case cel_ExprKind_kListElement: - return _cel_AstTraverser_PushListElementDeps( - traverser, cel_ListElementExpr_DownCast(expr), status); - case cel_ExprKind_kList: - return _cel_AstTraverser_PushListDeps( - traverser, cel_ListExpr_DownCast(expr), status); - case cel_ExprKind_kMapEntry: - return _cel_AstTraverser_PushMapEntryDeps( - traverser, cel_MapEntryExpr_DownCast(expr), status); - case cel_ExprKind_kMap: - return _cel_AstTraverser_PushMapDeps( - traverser, cel_MapExpr_DownCast(expr), status); - case cel_ExprKind_kStructField: - return _cel_AstTraverser_PushStructFieldDeps( - traverser, cel_StructFieldExpr_DownCast(expr), status); - case cel_ExprKind_kStruct: - return _cel_AstTraverser_PushStructDeps( - traverser, cel_StructExpr_DownCast(expr), status); - case cel_ExprKind_kComprehension: - return _cel_AstTraverser_PushComprehensionDeps( - traverser, cel_ComprehensionExpr_DownCast(expr), status); - case cel_ExprKind_kUnary: - return _cel_AstTraverser_PushUnaryDeps( - traverser, cel_UnaryExpr_DownCast(expr), status); - case cel_ExprKind_kBinary: - return _cel_AstTraverser_PushBinaryDeps( - traverser, cel_BinaryExpr_DownCast(expr), status); - case cel_ExprKind_kTernary: - return _cel_AstTraverser_PushTernaryDeps( - traverser, cel_TernaryExpr_DownCast(expr), status); - default: - cel_InternalStatus(status, - cel_StringView_From("unexpected AST node kind")); - return false; - } - return true; - } - case _cel_AstTraverserRecordKind_kSelectOperand: - CEL_ATTRIBUTE_FALLTHROUGH; - case _cel_AstTraverserRecordKind_kCallTarget: - CEL_ATTRIBUTE_FALLTHROUGH; - case _cel_AstTraverserRecordKind_kCallArgValue: - CEL_ATTRIBUTE_FALLTHROUGH; - case _cel_AstTraverserRecordKind_kListElementValue: - CEL_ATTRIBUTE_FALLTHROUGH; - case _cel_AstTraverserRecordKind_kMapEntryKey: - CEL_ATTRIBUTE_FALLTHROUGH; - case _cel_AstTraverserRecordKind_kMapEntryValue: - CEL_ATTRIBUTE_FALLTHROUGH; - case _cel_AstTraverserRecordKind_kStructFieldValue: - CEL_ATTRIBUTE_FALLTHROUGH; - case _cel_AstTraverserRecordKind_kComprehensionIterRange: - CEL_ATTRIBUTE_FALLTHROUGH; - case _cel_AstTraverserRecordKind_kComprehensionAccuInit: - CEL_ATTRIBUTE_FALLTHROUGH; - case _cel_AstTraverserRecordKind_kComprehensionLoopCondition: - CEL_ATTRIBUTE_FALLTHROUGH; - case _cel_AstTraverserRecordKind_kComprehensionLoopStep: - CEL_ATTRIBUTE_FALLTHROUGH; - case _cel_AstTraverserRecordKind_kComprehensionResult: - CEL_ATTRIBUTE_FALLTHROUGH; - case _cel_AstTraverserRecordKind_kUnaryArg: - CEL_ATTRIBUTE_FALLTHROUGH; - case _cel_AstTraverserRecordKind_kBinaryLeft: - CEL_ATTRIBUTE_FALLTHROUGH; - case _cel_AstTraverserRecordKind_kBinaryRight: - CEL_ATTRIBUTE_FALLTHROUGH; - case _cel_AstTraverserRecordKind_kTernaryCondition: - CEL_ATTRIBUTE_FALLTHROUGH; - case _cel_AstTraverserRecordKind_kTernaryIfTrue: - CEL_ATTRIBUTE_FALLTHROUGH; - case _cel_AstTraverserRecordKind_kTernaryIfFalse: - return _cel_AstTraverser_PushExpr(traverser, expr, status); - default: - CEL_UNREACHABLE(); - } -} - -static void _cel_AstTraverser_Construct(CEL_NONNULL(cel_AstTraverser*) - traverser, - CEL_NONNULL(cel_AstVisitor*) visitor) { - memset(traverser, '\0', sizeof(*traverser)); - _cel_Deque_Construct(&traverser->records); - traverser->visitor = visitor; - traverser->step = _cel_AstTraverserStep_kStepIn; - traverser->stepped = false; - traverser->select_operand_callbacks = - _cel_AstVisitor_HasVisit(visitor, SelectExprOperand); - traverser->unary_arg_callbacks = - _cel_AstVisitor_HasVisit(visitor, UnaryExprArg); - traverser->binary_left_callbacks = - _cel_AstVisitor_HasVisit(visitor, BinaryExprLeft); - traverser->binary_right_callbacks = - _cel_AstVisitor_HasVisit(visitor, BinaryExprRight); - traverser->ternary_condition_callbacks = - _cel_AstVisitor_HasVisit(visitor, TernaryExprCondition); - traverser->ternary_if_true_callbacks = - _cel_AstVisitor_HasVisit(visitor, TernaryExprIfTrue); - traverser->ternary_if_false_callbacks = - _cel_AstVisitor_HasVisit(visitor, TernaryExprIfFalse); - traverser->call_target_callbacks = - _cel_AstVisitor_HasVisit(visitor, CallExprTarget); - traverser->call_arg_value_callbacks = - _cel_AstVisitor_HasVisit(visitor, CallArgExprValue); - traverser->list_element_value_callbacks = - _cel_AstVisitor_HasVisit(visitor, ListElementExprValue); - traverser->map_entry_key_callbacks = - _cel_AstVisitor_HasVisit(visitor, MapEntryExprKey); - traverser->map_entry_value_callbacks = - _cel_AstVisitor_HasVisit(visitor, MapEntryExprValue); - traverser->struct_field_value_callbacks = - _cel_AstVisitor_HasVisit(visitor, StructFieldExprValue); - traverser->comprehension_iter_range_callbacks = - _cel_AstVisitor_HasVisit(visitor, ComprehensionExprIterRange); - traverser->comprehension_accu_init_callbacks = - _cel_AstVisitor_HasVisit(visitor, ComprehensionExprAccuInit); - traverser->comprehension_loop_condition_callbacks = - _cel_AstVisitor_HasVisit(visitor, ComprehensionExprLoopCondition); - traverser->comprehension_loop_step_callbacks = - _cel_AstVisitor_HasVisit(visitor, ComprehensionExprLoopStep); - traverser->comprehension_result_callbacks = - _cel_AstVisitor_HasVisit(visitor, ComprehensionExprResult); -} - -static void _cel_AstTraverser_Destruct(CEL_NONNULL(cel_AstTraverser*) - traverser) { - _cel_Deque_Destruct(&traverser->records, cel_DefaultAllocator); -} - -CEL_NULLABLE(cel_AstTraverser*) -cel_AstTraverser_New(CEL_NONNULL(const cel_Ast*) ast, - CEL_NONNULL(cel_AstVisitor*) visitor) { - CEL_ASSERT_NOT_NULL(ast); - CEL_ASSERT_NOT_NULL(visitor); - - CEL_NULLABLE(cel_AstTraverser*) - ast_traverser = (CEL_NULLABLE(cel_AstTraverser*))_cel_Malloc( - sizeof(cel_AstTraverser), cel_nullptr); - if (ast_traverser == cel_nullptr) { - return cel_nullptr; - } - _cel_AstTraverser_Construct(ast_traverser, visitor); - CEL_NULLABLE(cel_Expr*) expr = cel_Ast_Expr(ast); - if (expr != cel_nullptr) { - if (!_cel_AstTraverser_PushExpr(ast_traverser, expr, - /*status=*/cel_nullptr)) { - cel_AstTraverser_Delete(ast_traverser); - return cel_nullptr; - } - } - return ast_traverser; -} - -void cel_AstTraverser_Delete(CEL_NULLABLE(cel_AstTraverser*) ast_traverser) { - if (ast_traverser == cel_nullptr) { - return; - } - _cel_AstTraverser_Destruct(ast_traverser); - _cel_FreeSized(ast_traverser, sizeof(cel_AstTraverser)); -} - -void cel_AstTraverser_StepIn(cel_AstTraverser* cel_nonnull ast_traverser) { - CEL_ASSERT_NOT_NULL(ast_traverser); - - ast_traverser->step = _cel_AstTraverserStep_kStepIn; - ast_traverser->stepped = true; -} - -void cel_AstTraverser_StepOut(cel_AstTraverser* cel_nonnull ast_traverser) { - CEL_ASSERT_NOT_NULL(ast_traverser); - - ast_traverser->step = _cel_AstTraverserStep_kStepOut; - ast_traverser->stepped = true; -} - -void cel_AstTraverser_StepOver(cel_AstTraverser* cel_nonnull ast_traverser) { - CEL_ASSERT_NOT_NULL(ast_traverser); - - ast_traverser->step = _cel_AstTraverserStep_kStepOver; - ast_traverser->stepped = true; -} - -bool cel_AstTraverser_Traverse(CEL_NONNULL(cel_AstTraverser*) ast_traverser, - CEL_NONNULL(cel_Status*) status) { - CEL_ASSERT_NOT_NULL(ast_traverser); - CEL_ASSERT(cel_Status_Ok(status)); - - while (true) { - _cel_AstTraverserRecord* record = _cel_AstTraverser_Peek(ast_traverser); - if (record == cel_nullptr) { - return false; - } - while (true) { - if (!record->data.previsited || !record->data.previsited_expr) { - ast_traverser->stepped = false; - switch ( - _cel_AstTraverserRecord_PreVisit(record, ast_traverser, status)) { - case _cel_AstVisitorControl_kStop: - return cel_Status_Ok(status); - case _cel_AstVisitorControl_kContinue: - CEL_ASSERT_NOT(ast_traverser->stepped); - CEL_ASSERT(cel_Status_Ok(status)); - break; - default: - CEL_UNREACHABLE(); - } - } else if (!record->data.pushed_deps) { - if (!_cel_AstTraverser_PushDeps(ast_traverser, record, status)) { - return false; - } - record->data.pushed_deps = true; - break; - } else if (!record->data.postvisited || !record->data.postvisited_expr) { - ast_traverser->stepped = false; - switch ( - _cel_AstTraverserRecord_PostVisit(record, ast_traverser, status)) { - case _cel_AstVisitorControl_kStop: - return cel_Status_Ok(status); - case _cel_AstVisitorControl_kContinue: - CEL_ASSERT_NOT(ast_traverser->stepped); - CEL_ASSERT(cel_Status_Ok(status)); - break; - default: - CEL_UNREACHABLE(); - } - } else { - _cel_AstTraverser_Pop(ast_traverser); - break; - } - } - } -} diff --git a/cel-c/constant.c b/cel-c/constant.c deleted file mode 100644 index 317d5b9..0000000 --- a/cel-c/constant.c +++ /dev/null @@ -1,67 +0,0 @@ -// Copyright 2025 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "cel-c/constant.h" - -#include - -#include "cel-c/assert.h" -#include "cel-c/config.h" -#include "cel-c/duration.h" -#include "cel-c/string_view.h" -#include "cel-c/timestamp.h" - -bool cel_Constant_Equals(CEL_NONNULL(const cel_Constant*) lhs, - CEL_NONNULL(const cel_Constant*) rhs) { - CEL_ASSERT_NOT_NULL(lhs); - CEL_ASSERT_NOT_NULL(rhs); - - if (lhs == rhs) { - return true; - } - - const cel_ConstantKind kind = cel_Constant_Kind(lhs); - if (kind != cel_Constant_Kind(rhs)) { - return false; - } - - switch (kind) { - case cel_ConstantKind_kUnspecified: - return true; - case cel_ConstantKind_kNull: - return true; - case cel_ConstantKind_kBool: - return cel_Constant_GetBool(lhs) == cel_Constant_GetBool(rhs); - case cel_ConstantKind_kInt: - return cel_Constant_GetInt(lhs) == cel_Constant_GetInt(rhs); - case cel_ConstantKind_kUint: - return cel_Constant_GetUint(lhs) == cel_Constant_GetUint(rhs); - case cel_ConstantKind_kDouble: - return cel_Constant_GetDouble(lhs) == cel_Constant_GetDouble(rhs); - case cel_ConstantKind_kBytes: - return cel_StringView_Equals(cel_Constant_GetBytes(lhs), - cel_Constant_GetBytes(rhs)); - case cel_ConstantKind_kString: - return cel_StringView_Equals(cel_Constant_GetString(lhs), - cel_Constant_GetString(rhs)); - case cel_ConstantKind_kDuration: - return cel_Duration_Equals(cel_Constant_GetDuration(lhs), - cel_Constant_GetDuration(rhs)); - case cel_ConstantKind_kTimestamp: - return cel_Timestamp_Equals(cel_Constant_GetTimestamp(lhs), - cel_Constant_GetTimestamp(rhs)); - default: - return false; - } -} diff --git a/cel-c/constant_proto.c b/cel-c/constant_proto.c deleted file mode 100644 index 08e3cbe..0000000 --- a/cel-c/constant_proto.c +++ /dev/null @@ -1,194 +0,0 @@ -// Copyright 2025 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "cel-c/constant_proto.h" - -#include -#include - -#include "cel/expr/syntax.upb.h" -#include "google/protobuf/duration.upb.h" -#include "google/protobuf/struct.upb.h" -#include "google/protobuf/timestamp.upb.h" -#include "cel-c/arena.h" -#include "cel-c/assert.h" -#include "cel-c/config.h" -#include "cel-c/constant.h" -#include "cel-c/duration.h" -#include "cel-c/duration_proto.h" -#include "cel-c/status.h" -#include "cel-c/string_view.h" -#include "cel-c/timestamp.h" -#include "cel-c/timestamp_proto.h" -#include "upb/mem/arena.h" - -bool cel_Constant_ToProto(CEL_NONNULL(const cel_Constant*) in, - CEL_NONNULL(upb_Arena*) arena, - CEL_NONNULL(cel_expr_Constant*) out, - CEL_NONNULL(cel_Status*) status) { - CEL_ASSERT_NOT_NULL(in); - CEL_ASSERT_NOT_NULL(arena); - CEL_ASSERT_NOT_NULL(out); - CEL_ASSERT_NOT_NULL(status); - - if (!cel_Status_Ok(status)) { - return false; - } - switch (cel_Constant_Kind(in)) { - case cel_ConstantKind_kUnspecified: - cel_expr_Constant_clear_constant_kind(out); - break; - case cel_ConstantKind_kNull: - cel_expr_Constant_set_null_value(out, google_protobuf_NULL_VALUE); - break; - case cel_ConstantKind_kBool: - cel_expr_Constant_set_bool_value(out, cel_Constant_GetBool(in)); - break; - case cel_ConstantKind_kInt: - cel_expr_Constant_set_int64_value(out, cel_Constant_GetInt(in)); - break; - case cel_ConstantKind_kUint: - cel_expr_Constant_set_uint64_value(out, cel_Constant_GetUint(in)); - break; - case cel_ConstantKind_kDouble: - cel_expr_Constant_set_double_value(out, - cel_Constant_GetDouble(in)); - break; - case cel_ConstantKind_kBytes: - cel_expr_Constant_set_bytes_value(out, cel_Constant_GetBytes(in)); - break; - case cel_ConstantKind_kString: - cel_expr_Constant_set_string_value(out, - cel_Constant_GetString(in)); - break; - case cel_ConstantKind_kDuration: { - CEL_NULLABLE(google_protobuf_Duration*) - out_duration = google_protobuf_Duration_new(arena); - if (out_duration == cel_nullptr) { - cel_OutOfMemoryStatus(status); - return false; - } - cel_Duration_ToProto(cel_Constant_GetDuration(in), out_duration); - cel_expr_Constant_set_duration_value(out, out_duration); - } break; - case cel_ConstantKind_kTimestamp: { - CEL_NULLABLE(google_protobuf_Timestamp*) - out_timestamp = google_protobuf_Timestamp_new(arena); - if (out_timestamp == cel_nullptr) { - cel_OutOfMemoryStatus(status); - return false; - } - cel_Timestamp_ToProto(cel_Constant_GetTimestamp(in), out_timestamp); - cel_expr_Constant_set_timestamp_value(out, out_timestamp); - } break; - default: - cel_InvalidArgumentStatusF(status, "cel: unexpected constant kind: %d", - cel_Constant_Kind(in)); - return false; - } - return true; -} - -bool cel_Constant_FromProto(CEL_NONNULL(cel_Constant*) out, - CEL_NONNULL(const cel_expr_Constant*) in, - CEL_NONNULL(cel_Arena*) arena, - CEL_NONNULL(cel_Status*) status) { - CEL_ASSERT_NOT_NULL(out); - CEL_ASSERT_NOT_NULL(in); - CEL_ASSERT_NOT_NULL(status); - - if (!cel_Status_Ok(status)) { - return false; - } - switch (cel_expr_Constant_constant_kind_case(in)) { - case cel_expr_Constant_constant_kind_NOT_SET: - *out = cel_UnspecifiedConstant(); - break; - case cel_expr_Constant_constant_kind_null_value: - cel_Constant_SetNull(out); - break; - case cel_expr_Constant_constant_kind_bool_value: - cel_Constant_SetBool(out, cel_expr_Constant_bool_value(in)); - break; - case cel_expr_Constant_constant_kind_int64_value: - cel_Constant_SetInt(out, cel_expr_Constant_int64_value(in)); - break; - case cel_expr_Constant_constant_kind_uint64_value: - cel_Constant_SetUint(out, cel_expr_Constant_uint64_value(in)); - break; - case cel_expr_Constant_constant_kind_double_value: - cel_Constant_SetDouble(out, cel_expr_Constant_double_value(in)); - break; - case cel_expr_Constant_constant_kind_bytes_value: { - cel_StringView val = cel_expr_Constant_bytes_value(in); - if (!cel_Arena_StrDup(arena, &val, val)) { - cel_OutOfMemoryStatus(status); - return false; - } - cel_Constant_SetBytes(out, val); - } break; - case cel_expr_Constant_constant_kind_string_value: { - cel_StringView val = cel_expr_Constant_string_value(in); - if (!cel_Arena_StrDup(arena, &val, val)) { - cel_OutOfMemoryStatus(status); - return false; - } - cel_Constant_SetString(out, val); - } break; - case cel_expr_Constant_constant_kind_duration_value: { - CEL_NULLABILITY_UNKNOWN(const google_protobuf_Duration*) - in_duration = cel_expr_Constant_duration_value(in); - cel_Duration out_duration; - if (in_duration != cel_nullptr) { - if (!cel_Duration_FromProto(&out_duration, in_duration)) { - cel_InvalidArgumentStatusF( - status, - "cel: invalid google.protobuf.Duration: { seconds: %" PRId64 - " nanos: %" PRId32 " }", - google_protobuf_Duration_seconds(in_duration), - google_protobuf_Duration_nanos(in_duration)); - return false; - } - } else { - out_duration = cel_Duration_kZero; - } - cel_Constant_SetDuration(out, out_duration); - } break; - case cel_expr_Constant_constant_kind_timestamp_value: { - CEL_NULLABILITY_UNKNOWN(const google_protobuf_Timestamp*) - in_timestamp = cel_expr_Constant_timestamp_value(in); - cel_Timestamp out_timestamp; - if (in_timestamp != cel_nullptr) { - if (!cel_Timestamp_FromProto(&out_timestamp, in_timestamp)) { - cel_InvalidArgumentStatusF( - status, - "cel: invalid google.protobuf.Timestamp: { seconds: %" PRId64 - " nanos: %" PRId32 " }", - google_protobuf_Timestamp_seconds(in_timestamp), - google_protobuf_Timestamp_nanos(in_timestamp)); - return false; - } - } else { - out_timestamp = cel_Timestamp_kUnixEpoch; - } - cel_Constant_SetTimestamp(out, out_timestamp); - } break; - default: - cel_InvalidArgumentStatusF( - status, "cel: unexpected constant kind: %d", - cel_expr_Constant_constant_kind_case(in)); - return false; - } - return true; -} diff --git a/cel-c/constant_proto_v1alpha1.c b/cel-c/constant_proto_v1alpha1.c deleted file mode 100644 index e6b8374..0000000 --- a/cel-c/constant_proto_v1alpha1.c +++ /dev/null @@ -1,203 +0,0 @@ -// Copyright 2025 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "cel-c/constant_proto_v1alpha1.h" - -#include -#include - -#include "google/api/expr/v1alpha1/syntax.upb.h" -#include "google/protobuf/duration.upb.h" -#include "google/protobuf/struct.upb.h" -#include "google/protobuf/timestamp.upb.h" -#include "cel-c/arena.h" -#include "cel-c/assert.h" -#include "cel-c/config.h" -#include "cel-c/constant.h" -#include "cel-c/duration.h" -#include "cel-c/duration_proto.h" -#include "cel-c/status.h" -#include "cel-c/string_view.h" -#include "cel-c/timestamp.h" -#include "cel-c/timestamp_proto.h" -#include "upb/mem/arena.h" - -bool cel_Constant_ToProtoV1Alpha1( - CEL_NONNULL(const cel_Constant*) in, CEL_NONNULL(upb_Arena*) arena, - CEL_NONNULL(google_api_expr_v1alpha1_Constant*) out, - CEL_NONNULL(cel_Status*) status) { - CEL_ASSERT_NOT_NULL(in); - CEL_ASSERT_NOT_NULL(arena); - CEL_ASSERT_NOT_NULL(out); - CEL_ASSERT_NOT_NULL(status); - - if (!cel_Status_Ok(status)) { - return false; - } - switch (cel_Constant_Kind(in)) { - case cel_ConstantKind_kUnspecified: - google_api_expr_v1alpha1_Constant_clear_constant_kind(out); - break; - case cel_ConstantKind_kNull: - google_api_expr_v1alpha1_Constant_set_null_value( - out, google_protobuf_NULL_VALUE); - break; - case cel_ConstantKind_kBool: - google_api_expr_v1alpha1_Constant_set_bool_value( - out, cel_Constant_GetBool(in)); - break; - case cel_ConstantKind_kInt: - google_api_expr_v1alpha1_Constant_set_int64_value( - out, cel_Constant_GetInt(in)); - break; - case cel_ConstantKind_kUint: - google_api_expr_v1alpha1_Constant_set_uint64_value( - out, cel_Constant_GetUint(in)); - break; - case cel_ConstantKind_kDouble: - google_api_expr_v1alpha1_Constant_set_double_value( - out, cel_Constant_GetDouble(in)); - break; - case cel_ConstantKind_kBytes: - google_api_expr_v1alpha1_Constant_set_bytes_value( - out, cel_Constant_GetBytes(in)); - break; - case cel_ConstantKind_kString: - google_api_expr_v1alpha1_Constant_set_string_value( - out, cel_Constant_GetString(in)); - break; - case cel_ConstantKind_kDuration: { - CEL_NULLABLE(google_protobuf_Duration*) - out_duration = google_protobuf_Duration_new(arena); - if (out_duration == cel_nullptr) { - cel_OutOfMemoryStatus(status); - return false; - } - cel_Duration_ToProto(cel_Constant_GetDuration(in), out_duration); - google_api_expr_v1alpha1_Constant_set_duration_value(out, out_duration); - } break; - case cel_ConstantKind_kTimestamp: { - CEL_NULLABLE(google_protobuf_Timestamp*) - out_timestamp = google_protobuf_Timestamp_new(arena); - if (out_timestamp == cel_nullptr) { - cel_OutOfMemoryStatus(status); - return false; - } - cel_Timestamp_ToProto(cel_Constant_GetTimestamp(in), out_timestamp); - google_api_expr_v1alpha1_Constant_set_timestamp_value(out, out_timestamp); - } break; - default: - cel_InvalidArgumentStatusF(status, "cel: unexpected constant kind: %d", - cel_Constant_Kind(in)); - return false; - } - return true; -} - -bool cel_Constant_FromProtoV1Alpha1( - CEL_NONNULL(cel_Constant*) out, - CEL_NONNULL(const google_api_expr_v1alpha1_Constant*) in, - CEL_NONNULL(cel_Arena*) arena, CEL_NONNULL(cel_Status*) status) { - CEL_ASSERT_NOT_NULL(out); - CEL_ASSERT_NOT_NULL(in); - CEL_ASSERT_NOT_NULL(status); - - if (!cel_Status_Ok(status)) { - return false; - } - switch (google_api_expr_v1alpha1_Constant_constant_kind_case(in)) { - case google_api_expr_v1alpha1_Constant_constant_kind_NOT_SET: - *out = cel_UnspecifiedConstant(); - break; - case google_api_expr_v1alpha1_Constant_constant_kind_null_value: - cel_Constant_SetNull(out); - break; - case google_api_expr_v1alpha1_Constant_constant_kind_bool_value: - cel_Constant_SetBool(out, - google_api_expr_v1alpha1_Constant_bool_value(in)); - break; - case google_api_expr_v1alpha1_Constant_constant_kind_int64_value: - cel_Constant_SetInt(out, - google_api_expr_v1alpha1_Constant_int64_value(in)); - break; - case google_api_expr_v1alpha1_Constant_constant_kind_uint64_value: - cel_Constant_SetUint(out, - google_api_expr_v1alpha1_Constant_uint64_value(in)); - break; - case google_api_expr_v1alpha1_Constant_constant_kind_double_value: - cel_Constant_SetDouble( - out, google_api_expr_v1alpha1_Constant_double_value(in)); - break; - case google_api_expr_v1alpha1_Constant_constant_kind_bytes_value: { - cel_StringView val = google_api_expr_v1alpha1_Constant_bytes_value(in); - if (!cel_Arena_StrDup(arena, &val, val)) { - cel_OutOfMemoryStatus(status); - return false; - } - cel_Constant_SetBytes(out, val); - } break; - case google_api_expr_v1alpha1_Constant_constant_kind_string_value: { - cel_StringView val = google_api_expr_v1alpha1_Constant_string_value(in); - if (!cel_Arena_StrDup(arena, &val, val)) { - cel_OutOfMemoryStatus(status); - return false; - } - cel_Constant_SetString(out, val); - } break; - case google_api_expr_v1alpha1_Constant_constant_kind_duration_value: { - CEL_NULLABILITY_UNKNOWN(const google_protobuf_Duration*) - in_duration = google_api_expr_v1alpha1_Constant_duration_value(in); - cel_Duration out_duration; - if (in_duration != cel_nullptr) { - if (!cel_Duration_FromProto(&out_duration, in_duration)) { - cel_InvalidArgumentStatusF( - status, - "cel: invalid google.protobuf.Duration: { seconds: %" PRId64 - " nanos: %" PRId32 " }", - google_protobuf_Duration_seconds(in_duration), - google_protobuf_Duration_nanos(in_duration)); - return false; - } - } else { - out_duration = cel_Duration_kZero; - } - cel_Constant_SetDuration(out, out_duration); - } break; - case google_api_expr_v1alpha1_Constant_constant_kind_timestamp_value: { - CEL_NULLABILITY_UNKNOWN(const google_protobuf_Timestamp*) - in_timestamp = google_api_expr_v1alpha1_Constant_timestamp_value(in); - cel_Timestamp out_timestamp; - if (in_timestamp != cel_nullptr) { - if (!cel_Timestamp_FromProto(&out_timestamp, in_timestamp)) { - cel_InvalidArgumentStatusF( - status, - "cel: invalid google.protobuf.Timestamp: { seconds: %" PRId64 - " nanos: %" PRId32 " }", - google_protobuf_Timestamp_seconds(in_timestamp), - google_protobuf_Timestamp_nanos(in_timestamp)); - return false; - } - } else { - out_timestamp = cel_Timestamp_kUnixEpoch; - } - cel_Constant_SetTimestamp(out, out_timestamp); - } break; - default: - cel_InvalidArgumentStatusF( - status, "cel: unexpected constant kind: %d", - google_api_expr_v1alpha1_Constant_constant_kind_case(in)); - return false; - } - return true; -} diff --git a/cel-c/cstring_view.c b/cel-c/cstring_view.c deleted file mode 100644 index a8362ef..0000000 --- a/cel-c/cstring_view.c +++ /dev/null @@ -1,90 +0,0 @@ -// Copyright 2025 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "cel-c/cstring_view.h" - -#include -#include - -#include "cel-c/assert.h" -#include "cel-c/config.h" - -size_t cel_CStringView_Count(cel_CStringView haystack, cel_CStringView needle) { - CEL_ASSERT_NOT(cel_CStringView_Empty(needle)); - - size_t count = 0; - const char* pos; - size_t needle_len = 0; - while ((pos = cel_CStringView_FindFirst(haystack, needle)) != cel_nullptr) { - if (needle_len == 0) { - needle_len = cel_CStringView_Size(needle); - } - cel_CStringView_RemovePrefix( - &haystack, (pos - cel_CStringView_Data(haystack)) + needle_len); - ++count; - } - return count; -} - -bool cel_CStringViewTokenizer_Next( - cel_CStringViewTokenizer* cel_nonnull tokenizer, - cel_CStringView* cel_nonnull token, size_t* cel_nonnull token_len) { - CEL_ASSERT_NOT_NULL(tokenizer); - CEL_ASSERT_NOT_NULL(token); - CEL_ASSERT_NOT_NULL(token_len); - - if (tokenizer->done) { - return false; - } - const char* next = - cel_CStringView_FindFirst(tokenizer->subject, tokenizer->delim); - if (next == cel_nullptr) { - *token = tokenizer->subject; - *token_len = cel_CStringView_Size(tokenizer->subject); - tokenizer->done = true; - return true; - } - if (tokenizer->delim_len == 0) { - tokenizer->delim_len = cel_CStringView_Size(tokenizer->delim); - } - const char* data = cel_CStringView_Data(tokenizer->subject); - *token = cel_CStringView_FromString(data); - *token_len = next - data; - cel_CStringView_RemovePrefix(&tokenizer->subject, - (next - data) + tokenizer->delim_len); - return true; -} - -bool cel_CStringView_EqualsIgnoreCase(cel_CStringView lhs, - cel_CStringView rhs) { - const char* lhs_data = cel_CStringView_Data(lhs); - const char* rhs_data = cel_CStringView_Data(rhs); - if (lhs_data == rhs_data) { - return true; - } - while (true) { - uint8_t lhs_c = (uint8_t)(*lhs_data++); - uint8_t rhs_c = (uint8_t)(*rhs_data++); - if (lhs_c == '\0' || rhs_c == '\0') { - return lhs_c == rhs_c; - } - if (lhs_c != rhs_c) { - lhs_c = lhs_c >= 'A' && lhs_c <= 'Z' ? lhs_c - 'A' + 'a' : lhs_c; - rhs_c = rhs_c >= 'A' && rhs_c <= 'Z' ? rhs_c - 'A' + 'a' : rhs_c; - if (lhs_c != rhs_c) { - return false; - } - } - } -} diff --git a/cel-c/decl.c b/cel-c/decl.c deleted file mode 100644 index ab6ce0f..0000000 --- a/cel-c/decl.c +++ /dev/null @@ -1,344 +0,0 @@ -// Copyright 2025 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "cel-c/decl.h" - -#include -#include -#include - -#include "cel-c/arena.h" -#include "cel-c/assert.h" -#include "cel-c/config.h" -#include "cel-c/constant.h" -#include "cel-c/function_scope.h" -#include "cel-c/string_view.h" -#include "cel-c/type.h" -#include "cel-c/type_kind.h" - -struct cel_IdentDecl { - cel_StringView name; - cel_DeclKind kind; - cel_StringView doc; - - const cel_Type* cel_nonnull type; - cel_Constant value; -}; - -struct cel_FunctionDecl { - cel_StringView name; - cel_DeclKind kind; - cel_StringView doc; - - cel_FunctionOverloadDecl* cel_nullable head; - cel_FunctionOverloadDecl* cel_nullable tail; - size_t overloads; -}; - -struct cel_FunctionOverloadDecl { - cel_FunctionOverloadDecl* cel_nullable prev; - cel_FunctionOverloadDecl* cel_nullable next; - cel_FunctionDecl* cel_nullable function; - cel_StringView id; - const cel_FunctionType* cel_nonnull type; - cel_FunctionScope scope; - cel_StringView doc; -}; - -struct cel_Decl { - union { - struct { - cel_StringView name; - cel_DeclKind kind; - cel_StringView doc; - }; - cel_IdentDecl ident_decl; - cel_FunctionDecl function_decl; - }; -}; - -cel_DeclKind cel_Decl_Kind(const cel_Decl* cel_nonnull decl) { - CEL_ASSERT_NOT_NULL(decl); - - return decl->kind; -} - -cel_StringView cel_Decl_Name(const cel_Decl* cel_nonnull decl) { - CEL_ASSERT_NOT_NULL(decl); - - return decl->name; -} - -cel_StringView cel_Decl_Doc(const cel_Decl* cel_nonnull decl) { - CEL_ASSERT_NOT_NULL(decl); - - return decl->doc; -} - -void cel_Decl_SetDoc(cel_Decl* cel_nonnull decl, cel_StringView doc) { - CEL_ASSERT_NOT_NULL(decl); - - decl->doc = doc; -} - -cel_IdentDecl* cel_nullable cel_IdentDecl_New(cel_StringView name, - cel_Arena* cel_nonnull arena) { - CEL_ASSERT_NOT_NULL(arena); - - cel_IdentDecl* decl = (cel_IdentDecl*)cel_Arena_Malloc( - arena, sizeof(cel_IdentDecl), cel_nullptr); - if (CEL_LIKELY(decl != cel_nullptr)) { - memset(decl, 0, sizeof(*decl)); - decl->name = name; - decl->kind = cel_DeclKind_kIdent; - decl->type = cel_DynType; - } - return decl; -} - -const cel_Type* cel_nonnull -cel_IdentDecl_Type(const cel_IdentDecl* cel_nonnull decl) { - CEL_ASSERT_NOT_NULL(decl); - - return decl->type; -} - -void cel_IdentDecl_SetType(cel_IdentDecl* cel_nonnull decl, - const cel_Type* cel_nonnull type) { - CEL_ASSERT_NOT_NULL(decl); - - decl->type = type; -} - -const cel_Constant* cel_nonnull -cel_IdentDecl_Value(const cel_IdentDecl* cel_nonnull decl) { - CEL_ASSERT_NOT_NULL(decl); - - return &decl->value; -} - -cel_Constant* cel_nonnull -cel_IdentDecl_MutableValue(cel_IdentDecl* cel_nonnull decl) { - CEL_ASSERT_NOT_NULL(decl); - - return &decl->value; -} - -cel_FunctionDecl* cel_nullable -cel_FunctionDecl_New(cel_StringView name, cel_Arena* cel_nonnull arena) { - CEL_ASSERT_NOT_NULL(arena); - - cel_FunctionDecl* decl = (cel_FunctionDecl*)cel_Arena_Malloc( - arena, sizeof(cel_FunctionDecl), cel_nullptr); - if (CEL_LIKELY(decl != cel_nullptr)) { - memset(decl, 0, sizeof(*decl)); - decl->name = name; - decl->kind = cel_DeclKind_kFunction; - } - return decl; -} - -size_t cel_FunctionDecl_Overloads(const cel_FunctionDecl* cel_nonnull decl, - cel_FunctionOverloadDecl * cel_nullable * - cel_nullable head, - cel_FunctionOverloadDecl * cel_nullable * - cel_nullable tail) { - CEL_ASSERT_NOT_NULL(decl); - - if (head != cel_nullptr) { - *head = decl->head; - } - if (tail != cel_nullptr) { - *tail = decl->tail; - } - return decl->overloads; -} - -static bool _cel_IsTypeAssignable(const cel_Type* cel_nonnull to, - const cel_Type* cel_nonnull from) { - if (cel_Type_Equals(to, from)) { - return true; - } - const cel_TypeKind to_kind = cel_Type_Kind(to); - if (to_kind == cel_TypeKind_kDyn) { - return true; - } - switch (to_kind) { - case cel_TypeKind_kBoolWrapper: - return _cel_IsTypeAssignable(cel_NullType, from) || - _cel_IsTypeAssignable(cel_BoolType, from); - case cel_TypeKind_kIntWrapper: - return _cel_IsTypeAssignable(cel_NullType, from) || - _cel_IsTypeAssignable(cel_IntType, from); - case cel_TypeKind_kUintWrapper: - return _cel_IsTypeAssignable(cel_NullType, from) || - _cel_IsTypeAssignable(cel_UintType, from); - case cel_TypeKind_kDoubleWrapper: - return _cel_IsTypeAssignable(cel_NullType, from) || - _cel_IsTypeAssignable(cel_DoubleType, from); - case cel_TypeKind_kBytesWrapper: - return _cel_IsTypeAssignable(cel_NullType, from) || - _cel_IsTypeAssignable(cel_BytesType, from); - case cel_TypeKind_kStringWrapper: - return _cel_IsTypeAssignable(cel_NullType, from) || - _cel_IsTypeAssignable(cel_StringType, from); - default: - break; - } - const cel_TypeKind from_kind = cel_Type_Kind(from); - if (to_kind != from_kind || - !cel_StringView_Equals(cel_Type_Name(to), cel_Type_Name(from))) { - return false; - } - size_t from_params_len; - const cel_Type* const* from_params = cel_Type_Params(from, &from_params_len); - size_t to_params_len; - const cel_Type* const* to_params = cel_Type_Params(to, &to_params_len); - if (from_params_len != to_params_len) { - return false; - } - bool params_overlap = true; - for (size_t i = 0; i < from_params_len && params_overlap; ++i) { - params_overlap = _cel_IsTypeAssignable(from_params[i], to_params[i]); - } - return params_overlap; -} - -static bool _cel_SignaturesOverlap( - const cel_FunctionOverloadDecl* cel_nonnull lhs, - const cel_FunctionOverloadDecl* cel_nonnull rhs) { - if (cel_StringView_Equals(cel_FunctionOverloadDecl_Id(lhs), - cel_FunctionOverloadDecl_Id(rhs))) { - return true; - } - if (cel_FunctionOverloadDecl_Scope(lhs) != - cel_FunctionOverloadDecl_Scope(rhs)) { - return false; - } - const cel_FunctionType* lhs_type = cel_FunctionOverloadDecl_Type(lhs); - const cel_FunctionType* rhs_type = cel_FunctionOverloadDecl_Type(rhs); - size_t lhs_type_args_len; - const cel_Type* const* lhs_type_args = - cel_FunctionType_Args(lhs_type, &lhs_type_args_len); - size_t rhs_type_args_len; - const cel_Type* const* rhs_type_args = - cel_FunctionType_Args(rhs_type, &rhs_type_args_len); - if (lhs_type_args_len != rhs_type_args_len) { - return false; - } - bool args_overlap = true; - for (size_t i = 0; i < lhs_type_args_len && args_overlap; ++i) { - args_overlap = _cel_IsTypeAssignable(lhs_type_args[i], rhs_type_args[i]); - } - return args_overlap; -} - -bool cel_FunctionDecl_AddOverload(cel_FunctionDecl* cel_nonnull decl, - cel_FunctionOverloadDecl* cel_nonnull - overload) { - CEL_ASSERT_NOT_NULL(decl); - CEL_ASSERT_NOT_NULL(overload); - CEL_ASSERT_NULL(overload->function); - - cel_FunctionOverloadDecl* head = decl->head; - for (; head != cel_nullptr; head = head->next) { - if (_cel_SignaturesOverlap(head, overload)) { - return false; - } - } - - overload->function = decl; - overload->prev = decl->tail; - if (decl->tail != cel_nullptr) { - decl->tail->next = overload; - } else { - decl->head = overload; - } - decl->tail = overload; - ++decl->overloads; - return true; -} - -cel_FunctionOverloadDecl* cel_nullable cel_FunctionOverloadDecl_New( - cel_StringView id, cel_FunctionScope scope, - const cel_FunctionType* cel_nonnull type, cel_Arena* cel_nonnull arena) { - CEL_ASSERT_NOT_NULL(arena); - CEL_ASSERT_NOT_NULL(type); - - cel_FunctionOverloadDecl* decl = (cel_FunctionOverloadDecl*)cel_Arena_Malloc( - arena, sizeof(cel_FunctionOverloadDecl), cel_nullptr); - if (CEL_LIKELY(decl != cel_nullptr)) { - memset(decl, 0, sizeof(*decl)); - decl->id = id; - decl->type = type; - decl->scope = scope; - } - return decl; -} - -cel_StringView cel_FunctionOverloadDecl_Id( - const cel_FunctionOverloadDecl* cel_nonnull decl) { - CEL_ASSERT_NOT_NULL(decl); - - return decl->id; -} - -cel_StringView cel_FunctionOverloadDecl_Doc( - const cel_FunctionOverloadDecl* cel_nonnull decl) { - CEL_ASSERT_NOT_NULL(decl); - - return decl->doc; -} - -void cel_FunctionOverloadDecl_SetDoc(cel_FunctionOverloadDecl* cel_nonnull decl, - cel_StringView doc) { - CEL_ASSERT_NOT_NULL(decl); - - decl->doc = doc; -} - -cel_FunctionScope cel_FunctionOverloadDecl_Scope( - const cel_FunctionOverloadDecl* cel_nonnull decl) { - CEL_ASSERT_NOT_NULL(decl); - - return decl->scope; -} - -cel_FunctionDecl* cel_nullable cel_FunctionOverloadDecl_Function( - const cel_FunctionOverloadDecl* cel_nonnull decl) { - CEL_ASSERT_NOT_NULL(decl); - - return decl->function; -} - -const cel_FunctionType* cel_nonnull cel_FunctionOverloadDecl_Type( - const cel_FunctionOverloadDecl* cel_nonnull decl) { - CEL_ASSERT_NOT_NULL(decl); - - return decl->type; -} - -cel_FunctionOverloadDecl* cel_nullable cel_FunctionOverloadDecl_Prev( - const cel_FunctionOverloadDecl* cel_nonnull decl) { - CEL_ASSERT_NOT_NULL(decl); - - return decl->prev; -} - -cel_FunctionOverloadDecl* cel_nullable cel_FunctionOverloadDecl_Next( - const cel_FunctionOverloadDecl* cel_nonnull decl) { - CEL_ASSERT_NOT_NULL(decl); - - return decl->next; -} diff --git a/cel-c/decl_proto.c b/cel-c/decl_proto.c deleted file mode 100644 index 5795ee9..0000000 --- a/cel-c/decl_proto.c +++ /dev/null @@ -1,183 +0,0 @@ -// Copyright 2025 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "cel-c/decl_proto.h" - -#include - -#include "cel/expr/checked.upb.h" -#include "cel-c/arena.h" -#include "cel-c/assert.h" -#include "cel-c/config.h" -#include "cel-c/constant_proto.h" -#include "cel-c/decl.h" -#include "cel-c/function_scope.h" -#include "cel-c/status.h" -#include "cel-c/string_view.h" -#include "cel-c/type.h" -#include "cel-c/type_proto.h" - -cel_Decl* cel_nullable cel_Decl_FromProto( - const cel_expr_Decl* cel_nonnull in, cel_Arena* cel_nonnull arena, - cel_Status* cel_nonnull status) { - CEL_ASSERT_NOT_NULL(in); - CEL_ASSERT_NOT_NULL(arena); - CEL_ASSERT(cel_Status_Ok(status)); - - const cel_expr_Decl_decl_kind_oneofcases decl_kind = - cel_expr_Decl_decl_kind_case(in); - switch (decl_kind) { - case cel_expr_Decl_decl_kind_ident: { - cel_StringView out_name; - if (CEL_UNLIKELY(!cel_Arena_StrDup(arena, &out_name, - cel_expr_Decl_name(in)))) { - cel_OutOfMemoryStatus(status); - return cel_nullptr; - } - cel_IdentDecl* out = cel_IdentDecl_New(out_name, arena); - if (CEL_UNLIKELY(out == cel_nullptr)) { - cel_OutOfMemoryStatus(status); - return cel_nullptr; - } - const cel_expr_Decl_IdentDecl* in_ident = - cel_expr_Decl_ident(in); - if (cel_expr_Decl_IdentDecl_has_type(in_ident)) { - const cel_Type* out_type = cel_Type_FromProto( - cel_expr_Decl_IdentDecl_type(in_ident), arena, status); - if (CEL_UNLIKELY(out_type == cel_nullptr)) { - return cel_nullptr; - } - cel_IdentDecl_SetType(out, out_type); - } - if (cel_expr_Decl_IdentDecl_has_value(in_ident)) { - if (CEL_UNLIKELY(!cel_Constant_FromProto( - cel_IdentDecl_MutableValue(out), - cel_expr_Decl_IdentDecl_value(in_ident), arena, - status))) { - return cel_nullptr; - } - } - cel_StringView out_doc; - if (CEL_UNLIKELY(!cel_Arena_StrDup( - arena, &out_doc, cel_expr_Decl_IdentDecl_doc(in_ident)))) { - cel_OutOfMemoryStatus(status); - return cel_nullptr; - } - cel_Decl_SetDoc(cel_Decl_UpCast(out), out_doc); - return cel_Decl_UpCast(out); - } - case cel_expr_Decl_decl_kind_function: { - cel_StringView out_name; - if (CEL_UNLIKELY(!cel_Arena_StrDup(arena, &out_name, - cel_expr_Decl_name(in)))) { - cel_OutOfMemoryStatus(status); - return cel_nullptr; - } - cel_FunctionDecl* out = cel_FunctionDecl_New(out_name, arena); - if (CEL_UNLIKELY(out == cel_nullptr)) { - cel_OutOfMemoryStatus(status); - return cel_nullptr; - } - const cel_expr_Decl_FunctionDecl* in_function = - cel_expr_Decl_function(in); - size_t in_overloads_len; - const cel_expr_Decl_FunctionDecl_Overload* const* - in_overloads_ptr = cel_expr_Decl_FunctionDecl_overloads( - in_function, &in_overloads_len); - for (size_t i = 0; i < in_overloads_len; ++i) { - const cel_expr_Decl_FunctionDecl_Overload* in_overload = - in_overloads_ptr[i]; - cel_StringView out_id; - if (CEL_UNLIKELY(!cel_Arena_StrDup( - arena, &out_id, - cel_expr_Decl_FunctionDecl_Overload_overload_id( - in_overload)))) { - cel_OutOfMemoryStatus(status); - return cel_nullptr; - } - const cel_Type* out_result; - if (cel_expr_Decl_FunctionDecl_Overload_has_result_type( - in_overload)) { - out_result = cel_Type_FromProto( - cel_expr_Decl_FunctionDecl_Overload_result_type( - in_overload), - arena, status); - if (CEL_UNLIKELY(out_result == cel_nullptr)) { - return cel_nullptr; - } - } else { - out_result = cel_DynType; - } - size_t in_params_len; - const cel_expr_Type* const* in_params_ptr = - cel_expr_Decl_FunctionDecl_Overload_params(in_overload, - &in_params_len); - const cel_Type** out_params_ptr; - cel_FunctionType* out_type = cel_FunctionType_New( - out_result, in_params_len, &out_params_ptr, arena); - if (CEL_UNLIKELY(out_type == cel_nullptr)) { - cel_OutOfMemoryStatus(status); - return cel_nullptr; - } - for (size_t j = 0; j < in_params_len; ++j) { - const cel_expr_Type* in_param = in_params_ptr[j]; - const cel_Type* out_param; - if (in_param != cel_nullptr) { - out_param = cel_Type_FromProto(in_param, arena, status); - if (CEL_UNLIKELY(out_param == cel_nullptr)) { - return cel_nullptr; - } - } else { - out_param = cel_DynType; - } - out_params_ptr[j] = out_param; - } - cel_FunctionOverloadDecl* out_overload = cel_FunctionOverloadDecl_New( - out_id, - cel_expr_Decl_FunctionDecl_Overload_is_instance_function( - in_overload) - ? cel_FunctionScope_kMember - : cel_FunctionScope_kGlobal, - out_type, arena); - if (CEL_UNLIKELY(out_overload == cel_nullptr)) { - cel_OutOfMemoryStatus(status); - return cel_nullptr; - } - cel_StringView out_doc; - if (CEL_UNLIKELY(!cel_Arena_StrDup( - arena, &out_doc, - cel_expr_Decl_FunctionDecl_Overload_doc(in_overload)))) { - cel_OutOfMemoryStatus(status); - return cel_nullptr; - } - cel_FunctionOverloadDecl_SetDoc(out_overload, out_doc); - CEL_USED(cel_FunctionDecl_AddOverload(out, out_overload)); - } - cel_StringView out_doc; - if (CEL_UNLIKELY(!cel_Arena_StrDup( - arena, &out_doc, - cel_expr_Decl_FunctionDecl_doc(in_function)))) { - cel_OutOfMemoryStatus(status); - return cel_nullptr; - } - cel_Decl_SetDoc(cel_Decl_UpCast(out), out_doc); - return cel_Decl_UpCast(out); - } - default: - cel_InvalidArgumentStatusF( - status, "cel: unexpected google.api.expr.Decl.decl_kind: %d", - decl_kind); - return cel_nullptr; - } -} diff --git a/cel-c/decl_proto_v1alpha1.c b/cel-c/decl_proto_v1alpha1.c deleted file mode 100644 index 6089290..0000000 --- a/cel-c/decl_proto_v1alpha1.c +++ /dev/null @@ -1,187 +0,0 @@ -// Copyright 2025 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "cel-c/decl_proto_v1alpha1.h" - -#include - -#include "google/api/expr/v1alpha1/checked.upb.h" -#include "cel-c/arena.h" -#include "cel-c/assert.h" -#include "cel-c/config.h" -#include "cel-c/constant_proto_v1alpha1.h" -#include "cel-c/decl.h" -#include "cel-c/function_scope.h" -#include "cel-c/status.h" -#include "cel-c/string_view.h" -#include "cel-c/type.h" -#include "cel-c/type_proto_v1alpha1.h" - -cel_Decl* cel_nullable cel_Decl_FromProtoV1Alpha1( - const google_api_expr_v1alpha1_Decl* cel_nonnull in, - cel_Arena* cel_nonnull arena, cel_Status* cel_nonnull status) { - CEL_ASSERT_NOT_NULL(in); - CEL_ASSERT_NOT_NULL(arena); - CEL_ASSERT(cel_Status_Ok(status)); - - const google_api_expr_v1alpha1_Decl_decl_kind_oneofcases decl_kind = - google_api_expr_v1alpha1_Decl_decl_kind_case(in); - switch (decl_kind) { - case google_api_expr_v1alpha1_Decl_decl_kind_ident: { - cel_StringView out_name; - if (CEL_UNLIKELY(!cel_Arena_StrDup( - arena, &out_name, google_api_expr_v1alpha1_Decl_name(in)))) { - cel_OutOfMemoryStatus(status); - return cel_nullptr; - } - cel_IdentDecl* out = cel_IdentDecl_New(out_name, arena); - if (CEL_UNLIKELY(out == cel_nullptr)) { - cel_OutOfMemoryStatus(status); - return cel_nullptr; - } - const google_api_expr_v1alpha1_Decl_IdentDecl* in_ident = - google_api_expr_v1alpha1_Decl_ident(in); - if (google_api_expr_v1alpha1_Decl_IdentDecl_has_type(in_ident)) { - const cel_Type* out_type = cel_Type_FromProtoV1Alpha1( - google_api_expr_v1alpha1_Decl_IdentDecl_type(in_ident), arena, - status); - if (CEL_UNLIKELY(out_type == cel_nullptr)) { - return cel_nullptr; - } - cel_IdentDecl_SetType(out, out_type); - } - if (google_api_expr_v1alpha1_Decl_IdentDecl_has_value(in_ident)) { - if (CEL_UNLIKELY(!cel_Constant_FromProtoV1Alpha1( - cel_IdentDecl_MutableValue(out), - google_api_expr_v1alpha1_Decl_IdentDecl_value(in_ident), arena, - status))) { - return cel_nullptr; - } - } - cel_StringView out_doc; - if (CEL_UNLIKELY(!cel_Arena_StrDup( - arena, &out_doc, - google_api_expr_v1alpha1_Decl_IdentDecl_doc(in_ident)))) { - cel_OutOfMemoryStatus(status); - return cel_nullptr; - } - cel_Decl_SetDoc(cel_Decl_UpCast(out), out_doc); - return cel_Decl_UpCast(out); - } - case google_api_expr_v1alpha1_Decl_decl_kind_function: { - cel_StringView out_name; - if (CEL_UNLIKELY(!cel_Arena_StrDup( - arena, &out_name, google_api_expr_v1alpha1_Decl_name(in)))) { - cel_OutOfMemoryStatus(status); - return cel_nullptr; - } - cel_FunctionDecl* out = cel_FunctionDecl_New(out_name, arena); - if (CEL_UNLIKELY(out == cel_nullptr)) { - cel_OutOfMemoryStatus(status); - return cel_nullptr; - } - const google_api_expr_v1alpha1_Decl_FunctionDecl* in_function = - google_api_expr_v1alpha1_Decl_function(in); - size_t in_overloads_len; - const google_api_expr_v1alpha1_Decl_FunctionDecl_Overload* const* - in_overloads_ptr = - google_api_expr_v1alpha1_Decl_FunctionDecl_overloads( - in_function, &in_overloads_len); - for (size_t i = 0; i < in_overloads_len; ++i) { - const google_api_expr_v1alpha1_Decl_FunctionDecl_Overload* in_overload = - in_overloads_ptr[i]; - cel_StringView out_id; - if (CEL_UNLIKELY(!cel_Arena_StrDup( - arena, &out_id, - google_api_expr_v1alpha1_Decl_FunctionDecl_Overload_overload_id( - in_overload)))) { - cel_OutOfMemoryStatus(status); - return cel_nullptr; - } - const cel_Type* out_result; - if (google_api_expr_v1alpha1_Decl_FunctionDecl_Overload_has_result_type( - in_overload)) { - out_result = cel_Type_FromProtoV1Alpha1( - google_api_expr_v1alpha1_Decl_FunctionDecl_Overload_result_type( - in_overload), - arena, status); - if (CEL_UNLIKELY(out_result == cel_nullptr)) { - return cel_nullptr; - } - } else { - out_result = cel_DynType; - } - size_t in_params_len; - const google_api_expr_v1alpha1_Type* const* in_params_ptr = - google_api_expr_v1alpha1_Decl_FunctionDecl_Overload_params( - in_overload, &in_params_len); - const cel_Type** out_params_ptr; - cel_FunctionType* out_type = cel_FunctionType_New( - out_result, in_params_len, &out_params_ptr, arena); - if (CEL_UNLIKELY(out_type == cel_nullptr)) { - cel_OutOfMemoryStatus(status); - return cel_nullptr; - } - for (size_t j = 0; j < in_params_len; ++j) { - const google_api_expr_v1alpha1_Type* in_param = in_params_ptr[j]; - const cel_Type* out_param; - if (in_param != cel_nullptr) { - out_param = cel_Type_FromProtoV1Alpha1(in_param, arena, status); - if (CEL_UNLIKELY(out_param == cel_nullptr)) { - return cel_nullptr; - } - } else { - out_param = cel_DynType; - } - out_params_ptr[j] = out_param; - } - cel_FunctionOverloadDecl* out_overload = cel_FunctionOverloadDecl_New( - out_id, - google_api_expr_v1alpha1_Decl_FunctionDecl_Overload_is_instance_function( - in_overload) - ? cel_FunctionScope_kMember - : cel_FunctionScope_kGlobal, - out_type, arena); - if (CEL_UNLIKELY(out_overload == cel_nullptr)) { - cel_OutOfMemoryStatus(status); - return cel_nullptr; - } - cel_StringView out_doc; - if (CEL_UNLIKELY(!cel_Arena_StrDup( - arena, &out_doc, - google_api_expr_v1alpha1_Decl_FunctionDecl_Overload_doc( - in_overload)))) { - cel_OutOfMemoryStatus(status); - return cel_nullptr; - } - cel_FunctionOverloadDecl_SetDoc(out_overload, out_doc); - CEL_USED(cel_FunctionDecl_AddOverload(out, out_overload)); - } - cel_StringView out_doc; - if (CEL_UNLIKELY(!cel_Arena_StrDup( - arena, &out_doc, - google_api_expr_v1alpha1_Decl_FunctionDecl_doc(in_function)))) { - cel_OutOfMemoryStatus(status); - return cel_nullptr; - } - cel_Decl_SetDoc(cel_Decl_UpCast(out), out_doc); - return cel_Decl_UpCast(out); - } - default: - cel_InvalidArgumentStatusF( - status, "cel: unexpected google.api.expr.v1alpha1.Decl.decl_kind: %d", - decl_kind); - return cel_nullptr; - } -} diff --git a/cel-c/duration.c b/cel-c/duration.c deleted file mode 100644 index 481ddf8..0000000 --- a/cel-c/duration.c +++ /dev/null @@ -1,109 +0,0 @@ -// Copyright 2025 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "cel-c/duration.h" - -#include -#include - -#include "cel-c/assert.h" -#include "cel-c/config.h" -#include "cel-c/src/ckdint.h" - -bool cel_Duration_Normalize(int64_t* cel_nonnull sec, - int32_t* cel_nonnull nsec) { - int32_t rem; - - // Normalize nsec. - rem = *nsec / INT32_C(1000000000); - if (rem != 0) { - if (CEL_UNLIKELY(_cel_ckd_add(sec, *sec, (int64_t)rem))) { - return false; - } - *nsec %= INT32_C(1000000000); - } - - // Normalize sign. - if (*sec < 0 && *nsec > 0) { - if (CEL_UNLIKELY(_cel_ckd_add(sec, *sec, INT64_C(1)))) { - return false; - } - *nsec -= INT32_C(1000000000); - } else if (*sec > 0 && *nsec < 0) { - if (CEL_UNLIKELY(_cel_ckd_sub(sec, *sec, INT64_C(1)))) { - return false; - } - *nsec += INT32_C(1000000000); - } - - return cel_Duration_Valid(*sec, *nsec); -} - -bool cel_Duration_Add(cel_Duration* cel_nonnull out, cel_Duration lhs, - cel_Duration rhs) { - CEL_ASSERT_NOT_NULL(out); - CEL_ASSERT(cel_Duration_Valid(lhs.sec, lhs.nsec)); - CEL_ASSERT(cel_Duration_Valid(rhs.sec, rhs.nsec)); - - int64_t lhs_sec = lhs.sec; - int64_t rhs_sec = rhs.sec; - int64_t sec; - int32_t nsec; - int32_t lhs_nsec = lhs.nsec; - int32_t rhs_nsec = rhs.nsec; - - if (CEL_UNLIKELY(_cel_ckd_add(&sec, lhs_sec, rhs_sec))) { - return false; - } - - if (CEL_UNLIKELY(_cel_ckd_add(&nsec, lhs_nsec, rhs_nsec))) { - return false; - } - - if (CEL_UNLIKELY(!cel_Duration_Normalize(&sec, &nsec))) { - return false; - } - - *out = cel_Duration_FromUnix(sec, nsec); - return true; -} - -bool cel_Duration_Sub(cel_Duration* cel_nonnull out, cel_Duration lhs, - cel_Duration rhs) { - CEL_ASSERT_NOT_NULL(out); - CEL_ASSERT(cel_Duration_Valid(lhs.sec, lhs.nsec)); - CEL_ASSERT(cel_Duration_Valid(rhs.sec, rhs.nsec)); - - int64_t lhs_sec = lhs.sec; - int64_t rhs_sec = rhs.sec; - int64_t sec; - int32_t nsec; - int32_t lhs_nsec = lhs.nsec; - int32_t rhs_nsec = rhs.nsec; - - if (CEL_UNLIKELY(_cel_ckd_sub(&sec, lhs_sec, rhs_sec))) { - return false; - } - - if (CEL_UNLIKELY(_cel_ckd_sub(&nsec, lhs_nsec, rhs_nsec))) { - return false; - } - - if (CEL_UNLIKELY(!cel_Duration_Normalize(&sec, &nsec))) { - return false; - } - - *out = cel_Duration_FromUnix(sec, nsec); - return true; -} diff --git a/cel-c/duration_proto.c b/cel-c/duration_proto.c deleted file mode 100644 index 2d1dcf6..0000000 --- a/cel-c/duration_proto.c +++ /dev/null @@ -1,50 +0,0 @@ -// Copyright 2025 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "cel-c/duration_proto.h" - -#include -#include - -#include "google/protobuf/duration.upb.h" -#include "cel-c/assert.h" -#include "cel-c/config.h" -#include "cel-c/duration.h" - -void cel_Duration_ToProto(cel_Duration in, - CEL_NONNULL(google_protobuf_Duration*) out) { - CEL_ASSERT_NOT_NULL(out); - - int64_t sec; - int32_t nsec; - cel_Duration_ToUnix(in, &sec, &nsec); - google_protobuf_Duration_set_seconds(out, sec); - google_protobuf_Duration_set_nanos(out, nsec); -} - -bool cel_Duration_FromProto(CEL_NONNULL(cel_Duration*) out, - CEL_NONNULL(const google_protobuf_Duration*) in) { - CEL_ASSERT_NOT_NULL(out); - CEL_ASSERT_NOT_NULL(in); - - int64_t sec; - int32_t nsec; - sec = google_protobuf_Duration_seconds(in); - nsec = google_protobuf_Duration_nanos(in); - if (!cel_Duration_Normalize(&sec, &nsec)) { - return false; - } - *out = cel_Duration_FromUnix(sec, nsec); - return true; -} diff --git a/cel-c/error.c b/cel-c/error.c deleted file mode 100644 index 706c854..0000000 --- a/cel-c/error.c +++ /dev/null @@ -1,290 +0,0 @@ -// Copyright 2025 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "cel-c/error.h" - -#include -#include -#include -#include -#include - -#include "cel-c/arena.h" -#include "cel-c/assert.h" -#include "cel-c/config.h" -#include "cel-c/error_code.h" -#include "cel-c/error_space.h" -#include "cel-c/status_code.h" -#include "cel-c/string_view.h" - -typedef struct _cel_ErrorPayload _cel_ErrorPayload; - -struct _cel_ErrorPayload { - struct _cel_ErrorPayload* cel_nullable prev; - struct _cel_ErrorPayload* cel_nullable next; - cel_StringView type_url; - cel_StringView value; -}; - -struct cel_Error { - cel_StringView message; - const cel_ErrorSpace* cel_nullable space; - int raw_code; - cel_ErrorCode code; - size_t payloads_len; - _cel_ErrorPayload* cel_nullable payloads_head; - _cel_ErrorPayload* cel_nullable payloads_tail; -}; - -static const cel_Error _cel_DefaultError = { - .message = CEL_STRINGVIEW_C(""), - .space = cel_nullptr, - .raw_code = cel_ErrorCode_kUnknown, - .code = cel_ErrorCode_kUnknown, - .payloads_len = 0, - .payloads_head = cel_nullptr, - .payloads_tail = cel_nullptr, -}; - -const cel_Error* const cel_nonnull cel_DefaultError = &_cel_DefaultError; - -cel_Error* cel_nullable cel_Error_New(cel_Arena* cel_nonnull arena) { - CEL_ASSERT_NOT_NULL(arena); - - cel_Error* error = - (cel_Error*)cel_Arena_Malloc(arena, sizeof(cel_Error), cel_nullptr); - if (CEL_LIKELY(error != cel_nullptr)) { - memset(error, 0, sizeof(*error)); - error->space = cel_CanonicalErrorSpace; - error->raw_code = cel_ErrorCode_kUnknown; - error->code = (cel_ErrorCode)error->raw_code; - } - return error; -} - -void cel_Error_Clear(cel_Error* cel_nonnull error) { - CEL_ASSERT_NOT_NULL(error); - - error->message = cel_StringView_FromString(""); - error->space = cel_CanonicalErrorSpace; - error->raw_code = cel_ErrorCode_kUnknown; - error->code = (cel_ErrorCode)error->raw_code; - cel_Error_ClearPayloads(error); -} - -cel_ErrorCode cel_Error_CanonicalCode(const cel_Error* cel_nonnull error) { - CEL_ASSERT_NOT_NULL(error); - - return error->code; -} - -int cel_Error_Code(const cel_Error* cel_nonnull error) { - CEL_ASSERT_NOT_NULL(error); - - return error->raw_code; -} - -void cel_Error_SetCode(cel_Error* cel_nonnull error, - const cel_ErrorSpace* cel_nonnull space, int code) { - CEL_ASSERT_NOT_NULL(error); - CEL_ASSERT_NOT_NULL(space); - - cel_StatusCode canonical_code = cel_ErrorSpace_Canonical(space, code); - CEL_ASSERT_NE(canonical_code, cel_StatusCode_kOk); - - if (CEL_UNLIKELY(canonical_code == cel_StatusCode_kOk)) { - space = cel_CanonicalErrorSpace; - code = cel_StatusCode_kUnknown; - canonical_code = cel_StatusCode_kUnknown; - } - - error->space = space; - error->raw_code = code; - error->code = (cel_ErrorCode)canonical_code; -} - -const cel_ErrorSpace* cel_nonnull -cel_Error_Space(const cel_Error* cel_nonnull error) { - CEL_ASSERT_NOT_NULL(error); - - const cel_ErrorSpace* space = error->space; - if (space == cel_nullptr) { - space = cel_CanonicalErrorSpace; - } - return space; -} - -cel_StringView cel_Error_Message(const cel_Error* cel_nonnull error) { - CEL_ASSERT_NOT_NULL(error); - - return error->message; -} - -void cel_Error_SetMessage(cel_Error* cel_nonnull error, - cel_StringView message) { - CEL_ASSERT_NOT_NULL(error); - - error->message = message; -} - -bool cel_Error_VFormatMessage(cel_Error* cel_nonnull error, - cel_Arena* cel_nonnull arena, - const char* cel_nonnull fmt, va_list args) { - CEL_ASSERT_NOT_NULL(error); - CEL_ASSERT_NOT_NULL(arena); - CEL_ASSERT_NOT_NULL(fmt); - - cel_StringView message; - if (!cel_Arena_VPrintF(arena, &message, fmt, args)) { - return false; - } - cel_Error_SetMessage(error, message); - return true; -} - -bool cel_Error_NextPayload(const cel_Error* cel_nonnull error, - cel_StringView* cel_nullable type_url, - cel_StringView* cel_nullable value, - cel_ErrorPayloadIterator* cel_nonnull iter) { - CEL_ASSERT_NOT_NULL(error); - CEL_ASSERT_NOT_NULL(iter); - const _cel_ErrorPayload* payload; - if (iter->rep == (uintptr_t)-1) { - payload = error->payloads_head; - } else { - payload = (const _cel_ErrorPayload*)iter->rep; - payload = payload->next; - } - - if (payload == cel_nullptr) { - return false; - } - - if (type_url != cel_nullptr) { - *type_url = payload->type_url; - } - if (value != cel_nullptr) { - *value = payload->value; - } - iter->rep = (uintptr_t)payload; - return true; -} - -size_t cel_Error_Payloads(const cel_Error* cel_nonnull error) { - CEL_ASSERT_NOT_NULL(error); - - return error->payloads_len; -} - -bool cel_Error_GetPayload(const cel_Error* cel_nonnull error, - cel_StringView type_url, - cel_StringView* cel_nullable value) { - CEL_ASSERT_NOT_NULL(error); - - if (cel_StringView_Empty(type_url)) { - return false; - } - - const _cel_ErrorPayload* payload = error->payloads_head; - while (payload != cel_nullptr) { - if (cel_StringView_Equals(type_url, payload->type_url)) { - if (value != cel_nullptr) { - *value = payload->value; - } - return true; - } - payload = payload->next; - } - return false; -} - -bool cel_Error_SetPayload(cel_Error* cel_nonnull error, cel_StringView type_url, - cel_StringView value, cel_Arena* cel_nonnull arena) { - CEL_ASSERT_NOT_NULL(error); - CEL_ASSERT_NOT(cel_StringView_Empty(type_url)); - CEL_ASSERT_NOT_NULL(arena); - - _cel_ErrorPayload* payload = error->payloads_head; - while (payload != cel_nullptr) { - if (cel_StringView_Equals(type_url, payload->type_url)) { - payload->value = value; - return true; - } - payload = payload->next; - } - - payload = (_cel_ErrorPayload*)cel_Arena_Malloc( - arena, sizeof(_cel_ErrorPayload), cel_nullptr); - if (CEL_UNLIKELY(payload == cel_nullptr)) { - return false; - } - memset(payload, 0, sizeof(*payload)); - payload->type_url = type_url; - payload->value = value; - payload->prev = error->payloads_tail; - - if (error->payloads_tail != cel_nullptr) { - error->payloads_tail->next = payload; - } else { - CEL_ASSERT_NULL(error->payloads_head); - error->payloads_head = payload; - } - error->payloads_tail = payload; - ++error->payloads_len; - return true; -} - -bool cel_Error_DeletePayload(cel_Error* cel_nonnull error, - cel_StringView type_url, - cel_StringView* cel_nullable value) { - CEL_ASSERT_NOT_NULL(error); - CEL_ASSERT_NOT(cel_StringView_Empty(type_url)); - - if (cel_StringView_Empty(type_url)) { - return false; - } - - _cel_ErrorPayload* payload = error->payloads_head; - while (payload != cel_nullptr) { - if (cel_StringView_Equals(type_url, payload->type_url)) { - if (value != cel_nullptr) { - *value = payload->value; - } - if (payload->prev != cel_nullptr) { - payload->prev->next = payload->next; - } else { - CEL_ASSERT_EQ(payload, error->payloads_head); - error->payloads_head = payload->next; - } - if (payload->next != cel_nullptr) { - payload->next->prev = payload->prev; - } else { - CEL_ASSERT_EQ(payload, error->payloads_tail); - error->payloads_tail = payload->prev; - } - --error->payloads_len; - return true; - } - payload = payload->next; - } - return false; -} - -void cel_Error_ClearPayloads(cel_Error* cel_nonnull error) { - CEL_ASSERT_NOT_NULL(error); - - error->payloads_len = 0; - error->payloads_head = cel_nullptr; - error->payloads_tail = cel_nullptr; -} diff --git a/cel-c/error_code.c b/cel-c/error_code.c deleted file mode 100644 index c151599..0000000 --- a/cel-c/error_code.c +++ /dev/null @@ -1,96 +0,0 @@ -// Copyright 2025 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "cel-c/error_code.h" - -#include "cel-c/assert.h" -#include "cel-c/config.h" - -CEL_NONNULL(const char*) cel_ErrorCode_Name(cel_ErrorCode code) { - CEL_ASSERT_NE(code, 0); - - switch (code) { - case cel_ErrorCode_kCancelled: - return "CANCELLED"; - case cel_ErrorCode_kInvalidArgument: - return "INVALID_ARGUMENT"; - case cel_ErrorCode_kDeadlineExceeded: - return "DEADLINE_EXCEEDED"; - case cel_ErrorCode_kNotFound: - return "NOT_FOUND"; - case cel_ErrorCode_kAlreadyExists: - return "ALREADY_EXISTS"; - case cel_ErrorCode_kPermissionDenied: - return "PERMISSION_DENIED"; - case cel_ErrorCode_kResourceExhausted: - return "RESOURCE_EXHAUSTED"; - case cel_ErrorCode_kFailedPrecondition: - return "FAILED_PRECONDITION"; - case cel_ErrorCode_kAborted: - return "ABORTED"; - case cel_ErrorCode_kOutOfRange: - return "OUT_OF_RANGE"; - case cel_ErrorCode_kUnimplemented: - return "UNIMPLEMENTED"; - case cel_ErrorCode_kInternal: - return "INTERNAL"; - case cel_ErrorCode_kUnavailable: - return "UNAVAILABLE"; - case cel_ErrorCode_kDataLoss: - return "DATA_LOSS"; - case cel_ErrorCode_kUnauthenticated: - return "UNAUTHENTICATED"; - default: - return "UNKNOWN"; - } -} - -CEL_NONNULL(const char*) cel_ErrorCode_Message(cel_ErrorCode code) { - switch (code) { - case cel_ErrorCode_kCancelled: - return "the operation was cancelled"; - case cel_ErrorCode_kUnknown: - return "unknown error"; - case cel_ErrorCode_kInvalidArgument: - return "request contains an invalid argument"; - case cel_ErrorCode_kDeadlineExceeded: - return "deadline expired before operation could complete"; - case cel_ErrorCode_kNotFound: - return "requested entity was not found"; - case cel_ErrorCode_kAlreadyExists: - return "requested entity already exists"; - case cel_ErrorCode_kPermissionDenied: - return "caller does not have permission"; - case cel_ErrorCode_kResourceExhausted: - return "resource has been exhausted"; - case cel_ErrorCode_kFailedPrecondition: - return "precondition check failed"; - case cel_ErrorCode_kAborted: - return "operation was aborted"; - case cel_ErrorCode_kOutOfRange: - return "operation was attempted past the valid range"; - case cel_ErrorCode_kUnimplemented: - return "operation is not implemented, supported, or enabled"; - case cel_ErrorCode_kInternal: - return "internal error encountered"; - case cel_ErrorCode_kUnavailable: - return "service is currently unavailable"; - case cel_ErrorCode_kDataLoss: - return "unrecoverable data loss or corruption"; - case cel_ErrorCode_kUnauthenticated: - return "request is missing required authentication credential"; - default: - return "there was an error, that's all we know"; - } -} diff --git a/cel-c/error_proto.c b/cel-c/error_proto.c deleted file mode 100644 index ac23949..0000000 --- a/cel-c/error_proto.c +++ /dev/null @@ -1,105 +0,0 @@ -// Copyright 2025 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "cel-c/error_proto.h" - -#include -#include - -#include "google/protobuf/any.upb.h" -#include "google/rpc/status.upb.h" -#include "cel-c/arena.h" -#include "cel-c/assert.h" -#include "cel-c/config.h" -#include "cel-c/error.h" -#include "cel-c/error_code_proto.h" -#include "cel-c/string_view.h" -#include "upb/base/string_view.h" - -static bool _cel_Error_StrDup(cel_StringView in, cel_Arena* cel_nonnull arena, - cel_StringView* cel_nonnull out) { - if (cel_StringView_Empty(in)) { - *out = cel_StringView_FromString(""); - return true; - } - char* copied = - (char*)cel_Arena_Malloc(arena, cel_StringView_Size(in), cel_nullptr); - if (copied == cel_nullptr) { - return false; - } - memcpy(copied, cel_StringView_Data(in), cel_StringView_Size(in)); - *out = cel_StringView_FromArray(copied, cel_StringView_Size(in)); - return true; -} - -bool cel_Error_ToProto(const cel_Error* cel_nonnull in, - cel_Arena* cel_nonnull arena, - google_rpc_Status* cel_nonnull out) { - CEL_ASSERT_NOT_NULL(in); - CEL_ASSERT_NOT_NULL(arena); - CEL_ASSERT_NOT_NULL(out); - - google_rpc_Status_set_code( - out, cel_ErrorCode_ToProto(cel_Error_CanonicalCode(in))); - cel_StringView in_message = cel_Error_Message(in); - upb_StringView out_message; - if (!_cel_Error_StrDup(in_message, arena, &out_message)) { - return false; - } - google_rpc_Status_set_message(out, out_message); - - size_t in_payloads_len = cel_Error_Payloads(in); - if (in_payloads_len == 0) { - google_rpc_Status_clear_details(out); - } else { - google_protobuf_Any** out_payloads = - google_rpc_Status_resize_details(out, in_payloads_len, arena); - if (out_payloads == cel_nullptr) { - return false; - } - size_t i = 0; - cel_StringView in_type_url; - cel_StringView in_value; - cel_ErrorPayloadIterator iter = cel_Error_BeginPayloads(in); - bool oom = false; - while (cel_Error_NextPayload(in, &in_type_url, &in_value, &iter)) { - google_protobuf_Any* out_payload = google_protobuf_Any_new(arena); - if (out_payload == cel_nullptr) { - oom = true; - break; - } - out_payloads[i++] = out_payload; - upb_StringView out_type_url; - if (!_cel_Error_StrDup(in_type_url, arena, &out_type_url)) { - oom = true; - break; - } - google_protobuf_Any_set_type_url(out_payload, out_type_url); - upb_StringView out_value; - if (!_cel_Error_StrDup(in_value, arena, &out_value)) { - oom = true; - break; - } - google_protobuf_Any_set_value(out_payload, out_value); - } - if (i < in_payloads_len) { - google_rpc_Status_resize_details(out, i, arena); - } - if (oom) { - return false; - } - } - - return true; -} diff --git a/cel-c/error_space.c b/cel-c/error_space.c deleted file mode 100644 index d16b128..0000000 --- a/cel-c/error_space.c +++ /dev/null @@ -1,686 +0,0 @@ -// Copyright 2025 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "cel-c/error_space.h" - -#include -#include -#include - -#ifdef _WIN32 -#ifndef WIN32_LEAN_AND_MEAN -#define WIN32_LEAN_AND_MEAN 1 -#endif -#ifndef NOMINMAX -#define NOMINMAX 1 -#endif -#include -#include -#endif - -#include "cel-c/assert.h" -#include "cel-c/config.h" -#include "cel-c/cstring_view.h" -#include "cel-c/status_code.h" - -int cel_GenericErrorSpace_CurrentCode() { return errno; } - -int cel_SystemErrorSpace_CurrentCode() { -#ifndef _WIN32 - return cel_GenericErrorSpace_CurrentCode(); -#else - return (int)GetLastError(); -#endif -} - -static bool _cel_CanonicalErrorSpace_OutOfMemory( - CEL_NONNULL(const cel_ErrorSpace*) space, int code) { - CEL_ASSERT_EQ(space, cel_CanonicalErrorSpace); - - // The canonical error space does not have an out of memory condition. - return false; -} - -static cel_StatusCode _cel_CanonicalErrorSpace_Canonical( - CEL_NONNULL(const cel_ErrorSpace*) space, int code) { - CEL_ASSERT_EQ(space, cel_CanonicalErrorSpace); - - return (cel_StatusCode)code; -} - -static int _cel_CanonicalErrorSpace_Message(CEL_NONNULL(const cel_ErrorSpace*) - space, - int code, CEL_NONNULL(char*) buf, - size_t buflen) { - CEL_ASSERT_EQ(space, cel_CanonicalErrorSpace); - CEL_ASSERT_NOT_NULL(buf); - CEL_ASSERT_GT(buflen, 0); - - if (CEL_UNLIKELY(buflen == 0)) { - return 0; - } - if (code == 0) { - buf[0] = '\0'; - return 0; - } - const char* desc = cel_StatusCode_Message(code); - if (desc == cel_nullptr) { - buf[0] = '\0'; - return 0; - } - size_t desc_len = strlen(desc); - if (desc_len == 0) { - buf[0] = '\0'; - return 0; - } - size_t to_copy = desc_len >= buflen ? buflen - 1 : desc_len; - memcpy(buf, desc, to_copy); - buf[to_copy] = '\0'; - return 0; -} - -static const cel_ErrorSpaceVTable _cel_CanonicalErrorSpaceVTable = { - .name = CEL_CSTRINGVIEW_C("canonical"), - .OutOfMemory = _cel_CanonicalErrorSpace_OutOfMemory, - .Canonical = _cel_CanonicalErrorSpace_Canonical, - .Message = _cel_CanonicalErrorSpace_Message, -}; - -static const cel_ErrorSpace _cel_CanonicalErrorSpace = { - .vtable = &_cel_CanonicalErrorSpaceVTable, -}; - -CEL_NONNULL(const cel_ErrorSpace*) -const cel_CanonicalErrorSpace = &_cel_CanonicalErrorSpace; - -static cel_StatusCode _cel_StatusCode_FromPosix(int code) { - switch (code) { - case 0: - return cel_StatusCode_kOk; - case EINVAL: - CEL_ATTRIBUTE_FALLTHROUGH; - case ENAMETOOLONG: - CEL_ATTRIBUTE_FALLTHROUGH; - case E2BIG: - CEL_ATTRIBUTE_FALLTHROUGH; - case EDESTADDRREQ: - CEL_ATTRIBUTE_FALLTHROUGH; - case EDOM: - CEL_ATTRIBUTE_FALLTHROUGH; - case EFAULT: - CEL_ATTRIBUTE_FALLTHROUGH; - case EILSEQ: - CEL_ATTRIBUTE_FALLTHROUGH; - case ENOPROTOOPT: - CEL_ATTRIBUTE_FALLTHROUGH; - case ENOTSOCK: - CEL_ATTRIBUTE_FALLTHROUGH; - case ENOTTY: - CEL_ATTRIBUTE_FALLTHROUGH; - case EPROTOTYPE: - CEL_ATTRIBUTE_FALLTHROUGH; - case ESPIPE: - return cel_StatusCode_kInvalidArgument; - case ETIMEDOUT: - return cel_StatusCode_kDeadlineExceeded; - case ENODEV: - CEL_ATTRIBUTE_FALLTHROUGH; - case ENOENT: - CEL_ATTRIBUTE_FALLTHROUGH; -#ifdef ENOMEDIUM - case ENOMEDIUM: - CEL_ATTRIBUTE_FALLTHROUGH; -#endif - case ENXIO: - CEL_ATTRIBUTE_FALLTHROUGH; - case ESRCH: - return cel_StatusCode_kNotFound; - case EEXIST: - CEL_ATTRIBUTE_FALLTHROUGH; - case EADDRNOTAVAIL: - CEL_ATTRIBUTE_FALLTHROUGH; -#ifdef ENOTUNIQ - case ENOTUNIQ: - CEL_ATTRIBUTE_FALLTHROUGH; -#endif - case EALREADY: - return cel_StatusCode_kAlreadyExists; - case EPERM: - CEL_ATTRIBUTE_FALLTHROUGH; - case EACCES: - CEL_ATTRIBUTE_FALLTHROUGH; -#ifdef ENOKEY - case ENOKEY: - CEL_ATTRIBUTE_FALLTHROUGH; -#endif - case EROFS: - return cel_StatusCode_kPermissionDenied; - case ENOTEMPTY: - CEL_ATTRIBUTE_FALLTHROUGH; - case EISDIR: - CEL_ATTRIBUTE_FALLTHROUGH; - case ENOTDIR: - CEL_ATTRIBUTE_FALLTHROUGH; - case EADDRINUSE: - CEL_ATTRIBUTE_FALLTHROUGH; - case EBADF: - CEL_ATTRIBUTE_FALLTHROUGH; -#ifdef EBADFD - case EBADFD: - CEL_ATTRIBUTE_FALLTHROUGH; -#endif - case ECHILD: - CEL_ATTRIBUTE_FALLTHROUGH; - case EISCONN: - CEL_ATTRIBUTE_FALLTHROUGH; -#ifdef EISNAM - case EISNAM: - CEL_ATTRIBUTE_FALLTHROUGH; -#endif -#ifdef ENOTBLK - case ENOTBLK: - CEL_ATTRIBUTE_FALLTHROUGH; -#endif - case ENOTCONN: - CEL_ATTRIBUTE_FALLTHROUGH; - case EPIPE: - CEL_ATTRIBUTE_FALLTHROUGH; -#ifdef ESHUTDOWN - case ESHUTDOWN: - CEL_ATTRIBUTE_FALLTHROUGH; -#endif - case ETXTBSY: - CEL_ATTRIBUTE_FALLTHROUGH; -#ifdef EUNATCH - case EUNATCH: - CEL_ATTRIBUTE_FALLTHROUGH; -#endif - case EBUSY: - return cel_StatusCode_kFailedPrecondition; - case ENOSPC: - CEL_ATTRIBUTE_FALLTHROUGH; -#ifdef EDQUOT - case EDQUOT: - CEL_ATTRIBUTE_FALLTHROUGH; -#endif - case EMFILE: - CEL_ATTRIBUTE_FALLTHROUGH; - case EMLINK: - CEL_ATTRIBUTE_FALLTHROUGH; - case ENFILE: - CEL_ATTRIBUTE_FALLTHROUGH; - case ENOBUFS: - CEL_ATTRIBUTE_FALLTHROUGH; -#ifdef ENODATA - case ENODATA: - CEL_ATTRIBUTE_FALLTHROUGH; -#endif -#ifdef EUSERS - case EUSERS: - CEL_ATTRIBUTE_FALLTHROUGH; -#endif - case ENOMEM: - return cel_StatusCode_kResourceExhausted; -#ifdef ECHRNG - case ECHRNG: - CEL_ATTRIBUTE_FALLTHROUGH; -#endif - case EFBIG: - CEL_ATTRIBUTE_FALLTHROUGH; - case EOVERFLOW: - CEL_ATTRIBUTE_FALLTHROUGH; - case ERANGE: - return cel_StatusCode_kOutOfRange; -#ifdef ENOPKG - case ENOPKG: - CEL_ATTRIBUTE_FALLTHROUGH; -#endif - case ENOSYS: - CEL_ATTRIBUTE_FALLTHROUGH; - case ENOTSUP: - CEL_ATTRIBUTE_FALLTHROUGH; - case EAFNOSUPPORT: - CEL_ATTRIBUTE_FALLTHROUGH; -#ifdef EPFNOSUPPORT - case EPFNOSUPPORT: - CEL_ATTRIBUTE_FALLTHROUGH; -#endif - case EPROTONOSUPPORT: - CEL_ATTRIBUTE_FALLTHROUGH; -#ifdef ESOCKTNOSUPPORT - case ESOCKTNOSUPPORT: - CEL_ATTRIBUTE_FALLTHROUGH; -#endif - case EXDEV: - return cel_StatusCode_kUnimplemented; - case EAGAIN: - CEL_ATTRIBUTE_FALLTHROUGH; -#ifdef ECOMM - case ECOMM: - CEL_ATTRIBUTE_FALLTHROUGH; -#endif - case ECONNREFUSED: - CEL_ATTRIBUTE_FALLTHROUGH; - case ECONNABORTED: - CEL_ATTRIBUTE_FALLTHROUGH; - case ECONNRESET: - CEL_ATTRIBUTE_FALLTHROUGH; - case EINTR: - CEL_ATTRIBUTE_FALLTHROUGH; -#ifdef EHOSTDOWN - case EHOSTDOWN: - CEL_ATTRIBUTE_FALLTHROUGH; -#endif - case EHOSTUNREACH: - CEL_ATTRIBUTE_FALLTHROUGH; - case ENETDOWN: - CEL_ATTRIBUTE_FALLTHROUGH; - case ENETRESET: - CEL_ATTRIBUTE_FALLTHROUGH; - case ENETUNREACH: - CEL_ATTRIBUTE_FALLTHROUGH; - case ENOLCK: - CEL_ATTRIBUTE_FALLTHROUGH; -#ifdef ENONET - case ENONET: - CEL_ATTRIBUTE_FALLTHROUGH; -#endif - case ENOLINK: - return cel_StatusCode_kUnavailable; -#ifdef ESTALE - case ESTALE: - CEL_ATTRIBUTE_FALLTHROUGH; -#endif - case EDEADLK: - return cel_StatusCode_kAborted; - case ECANCELED: - return cel_StatusCode_kCancelled; - default: - return cel_StatusCode_kUnknown; - } -} - -static bool _cel_GenericErrorSpace_OutOfMemory( - CEL_NONNULL(const cel_ErrorSpace*) space, int code) { - CEL_ASSERT_EQ(space, cel_GenericErrorSpace); - - return code == ENOMEM; -} - -static cel_StatusCode _cel_GenericErrorSpace_Canonical( - CEL_NONNULL(const cel_ErrorSpace*) space, int code) { - CEL_ASSERT_EQ(space, cel_GenericErrorSpace); - - return _cel_StatusCode_FromPosix(code); -} - -static int _cel_GenericErrorSpace_Message(CEL_NONNULL(const cel_ErrorSpace*) - space, - int code, CEL_NONNULL(char*) buf, - size_t buflen) { - CEL_ASSERT_EQ(space, cel_GenericErrorSpace); - CEL_ASSERT_NOT_NULL(buf); - CEL_ASSERT_GT(buflen, 0); - - if (CEL_UNLIKELY(buflen == 0)) { - return 0; - } - if (code == 0) { - buf[0] = '\0'; - return 0; - } -#if defined(__GLIBC__) && defined(__GLIBC_MINOR__) && \ - (__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 31)) - const char* desc = strerrordesc_np(code); - if (desc == cel_nullptr) { - buf[0] = '\0'; - return 0; - } - size_t desc_len = strlen(desc); - if (desc_len == 0) { - buf[0] = '\0'; - return 0; - } - size_t to_copy = desc_len >= buflen ? buflen - 1 : desc_len; - memcpy(buf, desc, to_copy); - buf[to_copy] = '\0'; - return 0; -#elif defined(_WIN32) - if (code < 0 || code >= _sys_nerr) { - return EINVAL; - } - const char* desc = _sys_errlist[code]; - if (desc == cel_nullptr) { - buf[0] = '\0'; - return 0; - } - size_t desc_len = strlen(desc); - if (desc_len == 0) { - buf[0] = '\0'; - return 0; - } - size_t to_copy = desc_len >= buflen ? buflen - 1 : desc_len; - memcpy(buf, desc, to_copy); - buf[to_copy] = '\0'; - return 0; -#elif defined(__GLIBC__) && defined(_GNU_SOURCE) && _GNU_SOURCE - // GNU extension - char* desc = strerror_r(code, buf, buflen); - if (desc == cel_nullptr) { - buf[0] = '\0'; - return 0; - } - if (desc == buf) { - return (ptrdiff_t)strnlen(buf, buflen); - } - size_t desc_len = strlen(desc); - if (desc_len == 0) { - buf[0] = '\0'; - return 0; - } - size_t to_copy = desc_len >= buflen ? buflen - 1 : desc_len; - memcpy(buf, desc, to_copy); - buf[to_copy] = '\0'; - return 0; -#elif defined(_POSIX_C_SOURCE) && (_POSIX_C_SOURCE >= 200112L) && \ - (!defined(_GNU_SOURCE) || !_GNU_SOURCE) - // XSI compliant. - int err = strerror_r(code, buf, buflen); - if (err) { -#if defined(__GLIBC__) && defined(__GLIBC_MINOR__) && \ - (__GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ < 13)) - if (err == -1) { - err = errno; - } -#endif - return err; - } - return 0; -#else - // No other alternative, just use strerror and hope it is thread-safe. - const char* desc = strerror(code); - if (desc == cel_nullptr) { - buf[0] = '\0'; - return 0; - } - size_t desc_len = strlen(desc); - if (desc_len == 0) { - buf[0] = '\0'; - return 0; - } - size_t to_copy = desc_len >= buflen ? buflen - 1 : desc_len; - memcpy(buf, desc, to_copy); - buf[to_copy] = '\0'; - return 0; -#endif -} - -static const cel_ErrorSpaceVTable _cel_GenericErrorSpaceVTable = { - .name = CEL_CSTRINGVIEW_C("generic"), - .OutOfMemory = _cel_GenericErrorSpace_OutOfMemory, - .Canonical = _cel_GenericErrorSpace_Canonical, - .Message = _cel_GenericErrorSpace_Message, -}; - -static const cel_ErrorSpace _cel_GenericErrorSpace = { - .vtable = &_cel_GenericErrorSpaceVTable, -}; - -CEL_NONNULL(const cel_ErrorSpace*) -const cel_GenericErrorSpace = &_cel_GenericErrorSpace; - -static bool _cel_SystemErrorSpace_OutOfMemory(CEL_NONNULL(const cel_ErrorSpace*) - space, - int code) { - CEL_ASSERT_EQ(space, cel_SystemErrorSpace); - -#ifndef _WIN32 - return cel_ErrorSpace_OutOfMemory(cel_GenericErrorSpace, code); -#else - return code == ERROR_NOT_ENOUGH_MEMORY || code == ERROR_OUTOFMEMORY; -#endif -} - -static cel_StatusCode _cel_SystemErrorSpace_Canonical( - CEL_NONNULL(const cel_ErrorSpace*) space, int code) { - CEL_ASSERT_EQ(space, cel_SystemErrorSpace); - -#ifndef _WIN32 - return cel_ErrorSpace_Canonical(cel_GenericErrorSpace, code); -#else - // Borrowed from std::system_category() in MSVC STL. - switch (code) { - case 0: - return cel_StatusCode_kOk; - case ERROR_INVALID_FUNCTION: - return _cel_StatusCode_FromPosix(ENOSYS); - case ERROR_FILE_NOT_FOUND: - return _cel_StatusCode_FromPosix(ENOENT); - case ERROR_PATH_NOT_FOUND: - return _cel_StatusCode_FromPosix(ENOENT); - case ERROR_TOO_MANY_OPEN_FILES: - return _cel_StatusCode_FromPosix(ENFILE); - case ERROR_ACCESS_DENIED: - return _cel_StatusCode_FromPosix(EACCES); - case ERROR_INVALID_HANDLE: - return _cel_StatusCode_FromPosix(EINVAL); - case ERROR_NOT_ENOUGH_MEMORY: - return _cel_StatusCode_FromPosix(ENOMEM); - case ERROR_INVALID_ACCESS: - return _cel_StatusCode_FromPosix(EACCES); - case ERROR_OUTOFMEMORY: - return _cel_StatusCode_FromPosix(ENOMEM); - case ERROR_INVALID_DRIVE: - return _cel_StatusCode_FromPosix(ENODEV); - case ERROR_CURRENT_DIRECTORY: - return _cel_StatusCode_FromPosix(EACCES); - case ERROR_NOT_SAME_DEVICE: - return _cel_StatusCode_FromPosix(EXDEV); - case ERROR_WRITE_PROTECT: - return _cel_StatusCode_FromPosix(EACCES); - case ERROR_BAD_UNIT: - return _cel_StatusCode_FromPosix(ENODEV); - case ERROR_NOT_READY: - return _cel_StatusCode_FromPosix(EAGAIN); - case ERROR_SEEK: - return _cel_StatusCode_FromPosix(EIO); - case ERROR_WRITE_FAULT: - return _cel_StatusCode_FromPosix(EIO); - case ERROR_READ_FAULT: - return _cel_StatusCode_FromPosix(EIO); - case ERROR_SHARING_VIOLATION: - return _cel_StatusCode_FromPosix(EACCES); - case ERROR_LOCK_VIOLATION: - return _cel_StatusCode_FromPosix(ENOLCK); - case ERROR_HANDLE_DISK_FULL: - return _cel_StatusCode_FromPosix(ENOSPC); - case ERROR_NOT_SUPPORTED: - return _cel_StatusCode_FromPosix(ENOTSUP); - case ERROR_BAD_NETPATH: - return _cel_StatusCode_FromPosix(ENOENT); - case ERROR_DEV_NOT_EXIST: - return _cel_StatusCode_FromPosix(ENODEV); - case ERROR_BAD_NET_NAME: - return _cel_StatusCode_FromPosix(ENOENT); - case ERROR_FILE_EXISTS: - return _cel_StatusCode_FromPosix(EEXIST); - case ERROR_CANNOT_MAKE: - return _cel_StatusCode_FromPosix(EACCES); - case ERROR_INVALID_PARAMETER: - return _cel_StatusCode_FromPosix(EINVAL); - case ERROR_BROKEN_PIPE: - return _cel_StatusCode_FromPosix(EPIPE); - case ERROR_OPEN_FAILED: - return _cel_StatusCode_FromPosix(EIO); - case ERROR_BUFFER_OVERFLOW: - return _cel_StatusCode_FromPosix(ENAMETOOLONG); - case ERROR_DISK_FULL: - return _cel_StatusCode_FromPosix(ENOSPC); - case ERROR_SEM_TIMEOUT: - return _cel_StatusCode_FromPosix(ETIMEDOUT); - case ERROR_INVALID_NAME: - return _cel_StatusCode_FromPosix(ENOENT); - case ERROR_NEGATIVE_SEEK: - return _cel_StatusCode_FromPosix(EINVAL); - case ERROR_BUSY_DRIVE: - return _cel_StatusCode_FromPosix(EBUSY); - case ERROR_DIR_NOT_EMPTY: - return _cel_StatusCode_FromPosix(ENOTEMPTY); - case ERROR_BUSY: - return _cel_StatusCode_FromPosix(EBUSY); - case ERROR_ALREADY_EXISTS: - return _cel_StatusCode_FromPosix(EEXIST); - case ERROR_FILENAME_EXCED_RANGE: - return _cel_StatusCode_FromPosix(ENAMETOOLONG); - case ERROR_LOCKED: - return _cel_StatusCode_FromPosix(ENOLCK); - case WAIT_TIMEOUT: - return _cel_StatusCode_FromPosix(ETIMEDOUT); - case ERROR_DIRECTORY: - return _cel_StatusCode_FromPosix(EINVAL); - case ERROR_OPERATION_ABORTED: - return _cel_StatusCode_FromPosix(ECANCELED); - case ERROR_NOACCESS: - return _cel_StatusCode_FromPosix(EACCES); - case ERROR_CANTOPEN: - return _cel_StatusCode_FromPosix(EIO); - case ERROR_CANTREAD: - return _cel_StatusCode_FromPosix(EIO); - case ERROR_CANTWRITE: - return _cel_StatusCode_FromPosix(EIO); - case ERROR_RETRY: - return _cel_StatusCode_FromPosix(EAGAIN); - case ERROR_TIMEOUT: - return _cel_StatusCode_FromPosix(ETIMEDOUT); - case ERROR_OPEN_FILES: - return _cel_StatusCode_FromPosix(EBUSY); - case ERROR_DEVICE_IN_USE: - return _cel_StatusCode_FromPosix(EBUSY); - case ERROR_REPARSE_TAG_INVALID: - return _cel_StatusCode_FromPosix(EINVAL); - case WSAEINTR: - return _cel_StatusCode_FromPosix(EINTR); - case WSAEBADF: - return _cel_StatusCode_FromPosix(EBADF); - case WSAEACCES: - return _cel_StatusCode_FromPosix(EACCES); - case WSAEFAULT: - return _cel_StatusCode_FromPosix(EFAULT); - case WSAEINVAL: - return _cel_StatusCode_FromPosix(EINVAL); - case WSAEMFILE: - return _cel_StatusCode_FromPosix(EMFILE); - case WSAEWOULDBLOCK: - return _cel_StatusCode_FromPosix(EWOULDBLOCK); - case WSAEINPROGRESS: - return _cel_StatusCode_FromPosix(EINPROGRESS); - case WSAEALREADY: - return _cel_StatusCode_FromPosix(EALREADY); - case WSAENOTSOCK: - return _cel_StatusCode_FromPosix(ENOTSOCK); - case WSAEDESTADDRREQ: - return _cel_StatusCode_FromPosix(EDESTADDRREQ); - case WSAEMSGSIZE: - return _cel_StatusCode_FromPosix(EMSGSIZE); - case WSAEPROTOTYPE: - return _cel_StatusCode_FromPosix(EPROTOTYPE); - case WSAENOPROTOOPT: - return _cel_StatusCode_FromPosix(ENOPROTOOPT); - case WSAEPROTONOSUPPORT: - return _cel_StatusCode_FromPosix(EPROTONOSUPPORT); - case WSAEOPNOTSUPP: - return _cel_StatusCode_FromPosix(EOPNOTSUPP); - case WSAEAFNOSUPPORT: - return _cel_StatusCode_FromPosix(EAFNOSUPPORT); - case WSAEADDRINUSE: - return _cel_StatusCode_FromPosix(EADDRINUSE); - case WSAEADDRNOTAVAIL: - return _cel_StatusCode_FromPosix(EADDRNOTAVAIL); - case WSAENETDOWN: - return _cel_StatusCode_FromPosix(ENETDOWN); - case WSAENETUNREACH: - return _cel_StatusCode_FromPosix(ENETUNREACH); - case WSAENETRESET: - return _cel_StatusCode_FromPosix(ENETRESET); - case WSAECONNABORTED: - return _cel_StatusCode_FromPosix(ECONNABORTED); - case WSAECONNRESET: - return _cel_StatusCode_FromPosix(ECONNRESET); - case WSAENOBUFS: - return _cel_StatusCode_FromPosix(ENOBUFS); - case WSAEISCONN: - return _cel_StatusCode_FromPosix(EISCONN); - case WSAENOTCONN: - return _cel_StatusCode_FromPosix(ENOTCONN); - case WSAETIMEDOUT: - return _cel_StatusCode_FromPosix(ETIMEDOUT); - case WSAECONNREFUSED: - return _cel_StatusCode_FromPosix(ECONNREFUSED); - case WSAENAMETOOLONG: - return _cel_StatusCode_FromPosix(ENAMETOOLONG); - case WSAEHOSTUNREACH: - return _cel_StatusCode_FromPosix(EHOSTUNREACH); - default: - return cel_StatusCode_kUnknown; - } -#endif -} - -static int _cel_SystemErrorSpace_Message(CEL_NONNULL(const cel_ErrorSpace*) - space, - int code, CEL_NONNULL(char*) buf, - size_t buflen) { - CEL_ASSERT_EQ(space, cel_SystemErrorSpace); - CEL_ASSERT_NOT_NULL(buf); - CEL_ASSERT_GT(buflen, 0); - -#ifndef _WIN32 - return cel_ErrorSpace_Message(cel_GenericErrorSpace, code, buf, buflen); -#else - if (CEL_UNLIKELY(buflen == 0)) { - return 0; - } - if (code == 0) { - buf[0] = '\0'; - return 0; - } - DWORD ret = FormatMessageA( - FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, cel_nullptr, - (DWORD)(unsigned int)code, 0, buf, (DWORD)buflen, cel_nullptr); - if (ret == 0) { - buf[0] = '\0'; - return (int)GetLastError(); - } - CEL_ASSERT_LE(ret, buflen); - if (ret == buflen) { - --ret; - } - buf[ret] = '\0'; - return 0; -#endif -} - -static const cel_ErrorSpaceVTable _cel_SystemErrorSpaceVTable = { - .name = CEL_CSTRINGVIEW_C("system"), - .OutOfMemory = _cel_SystemErrorSpace_OutOfMemory, - .Canonical = _cel_SystemErrorSpace_Canonical, - .Message = _cel_SystemErrorSpace_Message, -}; - -static const cel_ErrorSpace _cel_SystemErrorSpace = { - .vtable = &_cel_SystemErrorSpaceVTable, -}; - -CEL_NONNULL(const cel_ErrorSpace*) -const cel_SystemErrorSpace = &_cel_SystemErrorSpace; diff --git a/cel-c/error_status.c b/cel-c/error_status.c deleted file mode 100644 index 593c257..0000000 --- a/cel-c/error_status.c +++ /dev/null @@ -1,70 +0,0 @@ -// Copyright 2025 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "cel-c/error_status.h" - -#include -#include - -#include "cel-c/arena.h" -#include "cel-c/assert.h" -#include "cel-c/config.h" -#include "cel-c/error.h" -#include "cel-c/status.h" -#include "cel-c/string_view.h" - -bool cel_Error_FromStatus(cel_Error* cel_nonnull out, - const cel_Status* cel_nonnull in, - cel_Arena* cel_nonnull arena) { - CEL_ASSERT_NOT_NULL(out); - CEL_ASSERT_NOT_NULL(in); - CEL_ASSERT_NOT(cel_Status_Ok(in)); - CEL_ASSERT_NOT_NULL(arena); - - if (CEL_UNLIKELY(cel_Status_Ok(in))) { - cel_Error_Clear(out); - return true; - } - - cel_Error_SetCode(out, cel_Status_Space(in), cel_Status_Code(in)); - - cel_StringView in_message = cel_Status_Message(in); - cel_StringView out_message; - if (cel_StringView_Empty(in_message)) { - out_message = cel_StringView_FromString(""); - } else { - if (!cel_Arena_StrDup(arena, &out_message, in_message)) { - return false; - } - } - cel_Error_SetMessage(out, out_message); - - cel_StringView in_type_url; - cel_StringView in_value; - cel_StatusPayloadIterator in_iter = cel_Status_BeginPayloads(in); - while (cel_Status_NextPayload(in, &in_type_url, &in_value, &in_iter)) { - cel_StringView out_type_url; - cel_StringView out_value; - if (!cel_Arena_StrDup(arena, &out_type_url, in_type_url)) { - return false; - } - if (!cel_Arena_StrDup(arena, &out_value, in_value)) { - return false; - } - if (!cel_Error_SetPayload(out, out_type_url, out_value, arena)) { - return false; - } - } - return true; -} diff --git a/cel-c/hash.c b/cel-c/hash.c deleted file mode 100644 index 5708236..0000000 --- a/cel-c/hash.c +++ /dev/null @@ -1,249 +0,0 @@ -// Copyright 2025 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "cel-c/hash.h" - -#include -#include -#include - -#include "cel-c/assert.h" -#include "cel-c/src/bit.h" -#include "cel-c/src/config.h" -#include "cel-c/src/uint128.h" -#include "cel-c/src/unaligned.h" - -static CEL_NONNULL(const void*) const _cel_kHashSeed = &_cel_kHashSeed; - -CEL_ATTRIBUTE_NODISCARD -static uint64_t _cel_HashSeed() { -#if (!defined(__clang__) || __clang_major__ > 11) && \ - (!defined(__apple_build_version__) || __apple_build_version__ >= 19558921) - return (uint64_t)((uintptr_t)&_cel_kHashSeed); -#else - return (uint64_t)((uintptr_t)_cel_kHashSeed); -#endif -} - -cel_HashState cel_HashState_Initialize() { - return ((cel_HashState){_cel_HashSeed()}); -} - -static void _cel_HashRead9To16(const uint8_t* cel_nonnull p, size_t n, - uint64_t* cel_nonnull low, - uint64_t* cel_nonnull high) { - const uint64_t lo = _cel_UnalignedLoad64(p); - const uint64_t hi = _cel_UnalignedLoad64(p + n - 8); -#ifdef _CEL_IS_LITTLE_ENDIAN - const uint64_t most_significant = hi; - const uint64_t least_significant = lo; -#else - const uint64_t most_significant = lo; - const uint64_t least_significant = hi; -#endif - *low = least_significant; - *high = most_significant; -} - -CEL_ATTRIBUTE_NODISCARD -static uint64_t _cel_HashRead4To8(const uint8_t* cel_nonnull p, size_t n) { - const uint32_t low = _cel_UnalignedLoad32(p); - const uint32_t hi = _cel_UnalignedLoad32(p + n - 4); -#ifdef _CEL_IS_LITTLE_ENDIAN - const uint32_t most_significant = hi; - const uint32_t least_significant = low; -#else - const uint32_t most_significant = low; - const uint32_t least_significant = hi; -#endif - return (((uint64_t)most_significant) << (n - 4) * 8) | least_significant; -} - -CEL_ATTRIBUTE_NODISCARD -static uint32_t _cel_HashRead1To3(const uint8_t* cel_nonnull p, size_t n) { - const uint8_t mem0 = p[0]; - const uint8_t mem1 = p[n / 2]; - const uint8_t mem2 = p[n - 1]; -#ifdef _CEL_IS_LITTLE_ENDIAN - const uint8_t significant2 = mem2; - const uint8_t significant1 = mem1; - const uint8_t significant0 = mem0; -#else - const uint8_t significant2 = mem0; - const uint8_t significant1 = n == 2 ? mem0 : mem1; - const uint8_t significant0 = mem2; -#endif - return (uint32_t)(significant0 | (significant1 << (n / 2 * 8)) | - (significant2 << ((n - 1) * 8))); -} - -CEL_ATTRIBUTE_NODISCARD -static uint64_t _cel_HashMix(uint64_t a, uint64_t b) { - _cel_Uint128 m = _cel_Uint128_From(a + b); - m = _cel_Uint128_Mul(m, _cel_Uint128_From(UINT64_C(0x9ddfea08eb382d69))); - m = _cel_Uint128_Xor(m, _cel_Uint128_ShiftRight(m, 64)); - return _cel_Uint128_To(uint64_t, m); -} - -static const uint64_t _cel_kHashSalt[5] = { - UINT64_C(0x243F6A8885A308D3), UINT64_C(0x13198A2E03707344), - UINT64_C(0xA4093822299F31D0), UINT64_C(0x082EFA98EC4E6C89), - UINT64_C(0x452821E638D01377), -}; - -CEL_ATTRIBUTE_NODISCARD -static uint64_t _cel_LowLevelHashMix(uint64_t a, uint64_t b) { - _cel_Uint128 m = _cel_Uint128_From(a); - m = _cel_Uint128_Mul(m, _cel_Uint128_From(b)); - return _cel_Uint128_To(uint64_t, m) ^ - _cel_Uint128_To(uint64_t, _cel_Uint128_ShiftRight(m, 64)); -} - -CEL_ATTRIBUTE_NODISCARD -static uint64_t _cel_LowLevelHashN(const uint8_t* cel_nonnull p, size_t n) { - CEL_ASSERT_GT(n, 16); - const size_t starting_n = n; - const uint8_t* const last_16_p = p + starting_n - 16; - uint64_t state = _cel_HashSeed() ^ _cel_kHashSalt[0]; - - if (n > 64) { - uint64_t dup_state[3]; - dup_state[0] = state; - dup_state[1] = state; - dup_state[2] = state; - - do { - const uint64_t a = _cel_UnalignedLoad64(p); - const uint64_t b = _cel_UnalignedLoad64(p + 8); - const uint64_t c = _cel_UnalignedLoad64(p + 16); - const uint64_t d = _cel_UnalignedLoad64(p + 24); - const uint64_t e = _cel_UnalignedLoad64(p + 32); - const uint64_t f = _cel_UnalignedLoad64(p + 40); - const uint64_t g = _cel_UnalignedLoad64(p + 48); - const uint64_t h = _cel_UnalignedLoad64(p + 56); - - state = _cel_LowLevelHashMix(a ^ _cel_kHashSalt[1], b ^ state); - dup_state[0] = - _cel_LowLevelHashMix(c ^ _cel_kHashSalt[2], d ^ dup_state[0]); - dup_state[1] = - _cel_LowLevelHashMix(e ^ _cel_kHashSalt[3], f ^ dup_state[1]); - dup_state[2] = - _cel_LowLevelHashMix(g ^ _cel_kHashSalt[4], h ^ dup_state[2]); - - p += 64; - n -= 64; - } while (n > 64); - - state = (state ^ dup_state[0]) ^ (dup_state[1] + dup_state[2]); - } - - if (n > 32) { - uint64_t dup_state[2]; - - const uint64_t a = _cel_UnalignedLoad64(p); - const uint64_t b = _cel_UnalignedLoad64(p + 8); - const uint64_t c = _cel_UnalignedLoad64(p + 16); - const uint64_t d = _cel_UnalignedLoad64(p + 24); - - dup_state[0] = _cel_LowLevelHashMix(a ^ _cel_kHashSalt[1], b ^ state); - dup_state[1] = _cel_LowLevelHashMix(c ^ _cel_kHashSalt[2], d ^ state); - state = dup_state[0] ^ dup_state[1]; - - p += 32; - n -= 32; - } - - if (n > 16) { - const uint64_t a = _cel_UnalignedLoad64(p); - const uint64_t b = _cel_UnalignedLoad64(p + 8); - - state = _cel_LowLevelHashMix(a ^ _cel_kHashSalt[1], b ^ state); - } - - const uint64_t a = _cel_UnalignedLoad64(last_16_p); - const uint64_t b = _cel_UnalignedLoad64(last_16_p + 8); - - return _cel_LowLevelHashMix(a ^ _cel_kHashSalt[1] ^ starting_n, b ^ state); -} - -cel_HashState cel_HashState_CombineN(cel_HashState state, - const void* cel_nullable data, - size_t size) { - uint64_t v; - if (size > 16) { - if (CEL_UNLIKELY(size > 1024)) { - do { - state.val = _cel_HashMix(state.val, _cel_LowLevelHashN(data, 1024)); - size -= 1024; - data = ((const uint8_t*)data) + 1024; - } while (size > 1024); - return cel_HashState_CombineN(state, data, size); - } - v = _cel_LowLevelHashN((const uint8_t*)data, size); - } else if (size > 8) { - uint64_t lo; - uint64_t hi; - _cel_HashRead9To16(data, size, &lo, &hi); - lo = _cel_rotr(lo, 53); - state.val *= UINT64_C(0x9ddfea08eb382d69); - lo += state.val; - state.val ^= hi; - _cel_Uint128 m = _cel_Uint128_From(state.val); - m = _cel_Uint128_Mul(m, _cel_Uint128_From(lo)); - m = _cel_Uint128_Xor(m, _cel_Uint128_ShiftRight(m, 64)); - return ((cel_HashState){_cel_Uint128_To(uint64_t, m)}); - } else if (size > 3) { - v = _cel_HashRead4To8(data, size); - } else if (size > 0) { - v = _cel_HashRead1To3(data, size); - } else { - return state; - } - return ((cel_HashState){_cel_HashMix(state.val, v)}); -} - -cel_HashState cel_HashState_Combine64(cel_HashState state, uint64_t data) { - return ((cel_HashState){_cel_HashMix(state.val, data)}); -} - -cel_HashState cel_HashState_CombineLD(cel_HashState state, long double value) { - const int cat = fpclassify(value); - switch (cat) { - case FP_INFINITE: - // Add the sign bit to differentiate between +Inf and -Inf - state = cel_HashState_CombineB(state, signbit(value)); - break; - case FP_NAN: - CEL_ATTRIBUTE_FALLTHROUGH; - case FP_ZERO: - CEL_ATTRIBUTE_FALLTHROUGH; - default: - // Category is enough for these. - break; - case FP_NORMAL: - CEL_ATTRIBUTE_FALLTHROUGH; - case FP_SUBNORMAL: { - // We can't convert `value` directly to double because this would have - // undefined behavior if the value is out of range. - // std::frexp gives us a value in the range (-1, -.5] or [.5, 1) that is - // guaranteed to be in range for `double`. The truncation is - // implementation defined, but that works as long as it is deterministic. - int exp; - double mant = (double)frexpl(value, &exp); - state = cel_HashState_CombineD(state, mant); - state = cel_HashState_CombineI(state, exp); - } break; - } - return cel_HashState_CombineI(state, cat); -} diff --git a/cel-c/operators.c b/cel-c/operators.c deleted file mode 100644 index 0ee546f..0000000 --- a/cel-c/operators.c +++ /dev/null @@ -1,246 +0,0 @@ -// Copyright 2025 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "cel-c/operators.h" - -#include -#include - -#include "cel-c/assert.h" -#include "cel-c/config.h" -#include "cel-c/string_view.h" - -typedef struct { - cel_StringView string; - cel_StringView alias; - int precedence; -} cel_OpData; - -static const cel_OpData cel_kUnaryOpData[] = { - { - .string = CEL_STRINGVIEW_C(""), - .alias = CEL_STRINGVIEW_C(""), - .precedence = 0, - }, - { - .string = CEL_STRINGVIEW_C("!_"), - .alias = CEL_STRINGVIEW_C(""), - .precedence = 2, - }, - { - .string = CEL_STRINGVIEW_C("-_"), - .alias = CEL_STRINGVIEW_C(""), - .precedence = 2, - }, - { - .string = CEL_STRINGVIEW_C("@not_strictly_false"), - .alias = CEL_STRINGVIEW_C("__not_strictly_false__"), - .precedence = 0, - }, -}; - -bool cel_UnaryOp_FromString(cel_StringView str, CEL_NONNULL(cel_UnaryOp*) op) { - CEL_ASSERT_NOT_NULL(op); - - for (size_t i = 1; i < cel_arraysize(cel_kUnaryOpData); ++i) { - const cel_OpData* const data = &cel_kUnaryOpData[i]; - if (cel_StringView_Equals(str, data->string) || - (!cel_StringView_Empty(data->alias) && - cel_StringView_Equals(str, data->alias))) { - *op = (cel_UnaryOp)(int)i; - return true; - } - } - return false; -} - -cel_StringView cel_UnaryOp_ToString(cel_UnaryOp op) { - CEL_ASSERT_GE(op, 0); - CEL_ASSERT_LT(op, cel_arraysize(cel_kUnaryOpData)); - - return cel_kUnaryOpData[op].string; -} - -int cel_UnaryOp_Precedence(cel_UnaryOp op) { - CEL_ASSERT_GE(op, 0); - CEL_ASSERT_LT(op, cel_arraysize(cel_kUnaryOpData)); - - return cel_kUnaryOpData[op].precedence; -} - -static const cel_OpData cel_kBinaryOpData[] = { - { - .string = CEL_STRINGVIEW_C(""), - .alias = CEL_STRINGVIEW_C(""), - .precedence = 0, - }, - { - .string = CEL_STRINGVIEW_C("_&&_"), - .alias = CEL_STRINGVIEW_C(""), - .precedence = 6, - }, - { - .string = CEL_STRINGVIEW_C("_||_"), - .alias = CEL_STRINGVIEW_C(""), - .precedence = 7, - }, - { - .string = CEL_STRINGVIEW_C("_==_"), - .alias = CEL_STRINGVIEW_C(""), - .precedence = 5, - }, - { - .string = CEL_STRINGVIEW_C("_!=_"), - .alias = CEL_STRINGVIEW_C(""), - .precedence = 5, - }, - { - .string = CEL_STRINGVIEW_C("_<_"), - .alias = CEL_STRINGVIEW_C(""), - .precedence = 5, - }, - { - .string = CEL_STRINGVIEW_C("_<=_"), - .alias = CEL_STRINGVIEW_C(""), - .precedence = 5, - }, - { - .string = CEL_STRINGVIEW_C("_>_"), - .alias = CEL_STRINGVIEW_C(""), - .precedence = 5, - }, - { - .string = CEL_STRINGVIEW_C("_>=_"), - .alias = CEL_STRINGVIEW_C(""), - .precedence = 5, - }, - { - .string = CEL_STRINGVIEW_C("_+_"), - .alias = CEL_STRINGVIEW_C(""), - .precedence = 4, - }, - { - .string = CEL_STRINGVIEW_C("_-_"), - .alias = CEL_STRINGVIEW_C(""), - .precedence = 4, - }, - { - .string = CEL_STRINGVIEW_C("_*_"), - .alias = CEL_STRINGVIEW_C(""), - .precedence = 3, - }, - { - .string = CEL_STRINGVIEW_C("_/_"), - .alias = CEL_STRINGVIEW_C(""), - .precedence = 3, - }, - { - .string = CEL_STRINGVIEW_C("_%_"), - .alias = CEL_STRINGVIEW_C(""), - .precedence = 3, - }, - { - .string = CEL_STRINGVIEW_C("_[_]"), - .alias = CEL_STRINGVIEW_C(""), - .precedence = 1, - }, - { - .string = CEL_STRINGVIEW_C("@in"), - .alias = CEL_STRINGVIEW_C("_in_"), - .precedence = 5, - }, - { - .string = CEL_STRINGVIEW_C("_[?_]"), - .alias = CEL_STRINGVIEW_C(""), - .precedence = 0, - }, - { - .string = CEL_STRINGVIEW_C("_?._"), - .alias = CEL_STRINGVIEW_C(""), - .precedence = 0, - }, -}; - -bool cel_BinaryOp_FromString(cel_StringView str, - CEL_NONNULL(cel_BinaryOp*) op) { - CEL_ASSERT_NOT_NULL(op); - - for (size_t i = 1; i < cel_arraysize(cel_kBinaryOpData); ++i) { - const cel_OpData* const data = &cel_kBinaryOpData[i]; - if (cel_StringView_Equals(str, data->string) || - (!cel_StringView_Empty(data->alias) && - cel_StringView_Equals(str, data->alias))) { - *op = (cel_BinaryOp)(int)i; - return true; - } - } - return false; -} - -cel_StringView cel_BinaryOp_ToString(cel_BinaryOp op) { - CEL_ASSERT_GE(op, 0); - CEL_ASSERT_LT(op, cel_arraysize(cel_kBinaryOpData)); - - return cel_kBinaryOpData[op].string; -} - -int cel_BinaryOp_Precedence(cel_BinaryOp op) { - CEL_ASSERT_GE(op, 0); - CEL_ASSERT_LT(op, cel_arraysize(cel_kBinaryOpData)); - - return cel_kBinaryOpData[op].precedence; -} - -static const cel_OpData cel_kTernaryOpData[] = { - { - .string = CEL_STRINGVIEW_C(""), - .alias = CEL_STRINGVIEW_C(""), - .precedence = 0, - }, - { - .string = CEL_STRINGVIEW_C("_?_:_"), - .alias = CEL_STRINGVIEW_C(""), - .precedence = 8, - }, -}; - -bool cel_TernaryOp_FromString(cel_StringView str, - CEL_NONNULL(cel_TernaryOp*) op) { - CEL_ASSERT_NOT_NULL(op); - - for (size_t i = 1; i < cel_arraysize(cel_kTernaryOpData); ++i) { - const cel_OpData* const data = &cel_kTernaryOpData[i]; - if (cel_StringView_Equals(str, data->string) || - (!cel_StringView_Empty(data->alias) && - cel_StringView_Equals(str, data->alias))) { - *op = (cel_TernaryOp)(int)i; - return true; - } - } - return false; -} - -cel_StringView cel_TernaryOp_ToString(cel_TernaryOp op) { - CEL_ASSERT_GE(op, 0); - CEL_ASSERT_LT(op, cel_arraysize(cel_kTernaryOpData)); - - return cel_kTernaryOpData[op].string; -} - -int cel_TernaryOp_Precedence(cel_TernaryOp op) { - CEL_ASSERT_GE(op, 0); - CEL_ASSERT_LT(op, cel_arraysize(cel_kTernaryOpData)); - - return cel_kTernaryOpData[op].precedence; -} diff --git a/cel-c/ref.c b/cel-c/ref.c deleted file mode 100644 index 52e1f70..0000000 --- a/cel-c/ref.c +++ /dev/null @@ -1,189 +0,0 @@ -// Copyright 2025 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "cel-c/ref.h" - -#include -#include -#include - -#include "cel-c/arena.h" -#include "cel-c/assert.h" -#include "cel-c/config.h" -#include "cel-c/constant.h" -#include "cel-c/string_view.h" - -struct cel_IdentRef { - cel_StringView name; - cel_RefKind kind; - - cel_Constant value; -}; - -struct cel_FunctionRef { - cel_StringView name; - cel_RefKind kind; - - cel_FunctionOverloadRef* head; - cel_FunctionOverloadRef* tail; - size_t overloads; -}; - -struct cel_FunctionOverloadRef { - cel_FunctionOverloadRef* prev; - cel_FunctionOverloadRef* next; - cel_StringView id; -#ifndef NDEBUG - const cel_FunctionRef* func; -#endif -}; - -struct cel_Ref { - union { - struct { - cel_StringView name; - cel_RefKind kind; - }; - cel_IdentRef variable_ref; - cel_FunctionRef function_ref; - }; -}; - -cel_RefKind cel_Ref_Kind(const cel_Ref* cel_nonnull ref) { - CEL_ASSERT_NOT_NULL(ref); - - return ref->kind; -} - -cel_StringView cel_Ref_Name(const cel_Ref* cel_nonnull ref) { - CEL_ASSERT_NOT_NULL(ref); - - return ref->name; -} - -cel_IdentRef* cel_nullable cel_IdentRef_New(cel_StringView name, - cel_Arena* cel_nonnull arena) { - CEL_ASSERT_NOT_NULL(arena); - - cel_IdentRef* ref = - (cel_IdentRef*)cel_Arena_Malloc(arena, sizeof(cel_IdentRef), cel_nullptr); - if (CEL_LIKELY(ref != cel_nullptr)) { - memset(ref, 0, sizeof(*ref)); - ref->name = name; - ref->kind = cel_RefKind_kIdent; - } - return ref; -} - -const cel_Constant* cel_nonnull -cel_IdentRef_Value(const cel_IdentRef* cel_nonnull ref) { - CEL_ASSERT_NOT_NULL(ref); - - return &ref->value; -} - -cel_FunctionRef* cel_nullable -cel_FunctionRef_New(cel_StringView name, cel_Arena* cel_nonnull arena) { - CEL_ASSERT_NOT_NULL(arena); - - cel_FunctionRef* ref = (cel_FunctionRef*)cel_Arena_Malloc( - arena, sizeof(cel_FunctionRef), cel_nullptr); - if (CEL_LIKELY(ref != cel_nullptr)) { - memset(ref, 0, sizeof(*ref)); - ref->name = name; - ref->kind = cel_RefKind_kFunction; - } - return ref; -} - -size_t cel_FunctionRef_Overloads(const cel_FunctionRef* cel_nonnull ref, - cel_FunctionOverloadRef * cel_nullable * - cel_nullable head, - cel_FunctionOverloadRef * cel_nullable * - cel_nullable tail) { - CEL_ASSERT_NOT_NULL(ref); - - if (head != cel_nullptr) { - *head = ref->head; - } - if (tail != cel_nullptr) { - *tail = ref->tail; - } - return ref->overloads; -} - -bool cel_FunctionRef_AppendOverload(cel_FunctionRef* cel_nonnull ref, - cel_FunctionOverloadRef* cel_nonnull - overload) { - CEL_ASSERT_NOT_NULL(ref); - CEL_ASSERT_NOT_NULL(overload); -#ifndef NDEBUG - CEL_ASSERT_NULL(overload->func); -#endif - - cel_FunctionOverloadRef* head = ref->head; - for (; head != cel_nullptr; head = head->next) { - if (cel_StringView_Equals(head->id, overload->id)) { - return false; - } - } - - overload->prev = ref->tail; - if (ref->tail != cel_nullptr) { - ref->tail->next = overload; - } else { - ref->head = overload; - } - ref->tail = overload; - ++ref->overloads; - -#ifndef NDEBUG - overload->func = ref; -#endif - return true; -} - -cel_FunctionOverloadRef* cel_nullable -cel_FunctionOverloadRef_New(cel_StringView id, cel_Arena* cel_nonnull arena) { - CEL_ASSERT_NOT_NULL(arena); - - cel_FunctionOverloadRef* ref = (cel_FunctionOverloadRef*)cel_Arena_Malloc( - arena, sizeof(cel_FunctionOverloadRef), cel_nullptr); - if (CEL_LIKELY(ref != cel_nullptr)) { - memset(ref, 0, sizeof(*ref)); - ref->id = id; - } - return ref; -} - -cel_StringView cel_FunctionOverloadRef_Id( - const cel_FunctionOverloadRef* cel_nonnull ref) { - CEL_ASSERT_NOT_NULL(ref); - - return ref->id; -} - -cel_FunctionOverloadRef* cel_nullable -cel_FunctionOverloadRef_Prev(const cel_FunctionOverloadRef* cel_nonnull ref) { - CEL_ASSERT_NOT_NULL(ref); - - return ref->prev; -} - -cel_FunctionOverloadRef* cel_nullable -cel_FunctionOverloadRef_Next(const cel_FunctionOverloadRef* cel_nonnull ref) { - CEL_ASSERT_NOT_NULL(ref); - - return ref->next; -} diff --git a/cel-c/ref_proto.c b/cel-c/ref_proto.c deleted file mode 100644 index 6bc95f0..0000000 --- a/cel-c/ref_proto.c +++ /dev/null @@ -1,86 +0,0 @@ -// Copyright 2025 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "cel-c/ref_proto.h" - -#include - -#include "cel/expr/checked.upb.h" -#include "cel-c/arena.h" -#include "cel-c/assert.h" -#include "cel-c/config.h" -#include "cel-c/constant_proto.h" -#include "cel-c/ref.h" -#include "cel-c/status.h" -#include "cel-c/string_view.h" -#include "upb/base/string_view.h" - -cel_Ref* cel_nullable cel_Ref_FromProto( - const cel_expr_Reference* cel_nonnull in, - cel_Arena* cel_nonnull arena, cel_Status* cel_nonnull status) { - CEL_ASSERT_NOT_NULL(in); - CEL_ASSERT_NOT_NULL(arena); - CEL_ASSERT_NOT_NULL(status); - CEL_ASSERT(cel_Status_Ok(status)); - - cel_StringView out_name; - if (!cel_Arena_StrDup(arena, &out_name, cel_expr_Reference_name(in))) { - cel_OutOfMemoryStatus(status); - return cel_nullptr; - } - size_t in_overloads_len; - const upb_StringView* in_overloads_ptr = - cel_expr_Reference_overload_id(in, &in_overloads_len); - if (in_overloads_len > 0 && cel_expr_Reference_has_value(in)) { - cel_InvalidArgumentStatus( - status, cel_StringView_From("cel: resolved reference has both function " - "overloads and a constant")); - return cel_nullptr; - } - if (in_overloads_len > 0) { - cel_FunctionRef* out = cel_FunctionRef_New(out_name, arena); - if (out == cel_nullptr) { - cel_OutOfMemoryStatus(status); - return cel_nullptr; - } - for (size_t i = 0; i < in_overloads_len; ++i) { - cel_StringView out_id; - if (!cel_Arena_StrDup(arena, &out_id, in_overloads_ptr[i])) { - cel_OutOfMemoryStatus(status); - return cel_nullptr; - } - cel_FunctionOverloadRef* overload_ref = - cel_FunctionOverloadRef_New(out_id, arena); - if (overload_ref == cel_nullptr) { - cel_OutOfMemoryStatus(status); - return cel_nullptr; - } - CEL_USED(cel_FunctionRef_AppendOverload(out, overload_ref)); - } - return cel_Ref_UpCast(out); - } - cel_IdentRef* out = cel_IdentRef_New(out_name, arena); - if (out == cel_nullptr) { - cel_OutOfMemoryStatus(status); - return cel_nullptr; - } - if (cel_expr_Reference_has_value(in)) { - if (!cel_Constant_FromProto(cel_IdentRef_MutableValue(out), - cel_expr_Reference_value(in), arena, - status)) { - return cel_nullptr; - } - } - return cel_Ref_UpCast(out); -} diff --git a/cel-c/ref_proto_v1alpha1.c b/cel-c/ref_proto_v1alpha1.c deleted file mode 100644 index d5051a2..0000000 --- a/cel-c/ref_proto_v1alpha1.c +++ /dev/null @@ -1,88 +0,0 @@ -// Copyright 2025 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "cel-c/ref_proto_v1alpha1.h" - -#include - -#include "google/api/expr/v1alpha1/checked.upb.h" -#include "cel-c/arena.h" -#include "cel-c/assert.h" -#include "cel-c/config.h" -#include "cel-c/constant_proto_v1alpha1.h" -#include "cel-c/ref.h" -#include "cel-c/status.h" -#include "cel-c/string_view.h" -#include "upb/base/string_view.h" - -cel_Ref* cel_nullable cel_Ref_FromProtoV1Alpha1( - const google_api_expr_v1alpha1_Reference* cel_nonnull in, - cel_Arena* cel_nonnull arena, cel_Status* cel_nonnull status) { - CEL_ASSERT_NOT_NULL(in); - CEL_ASSERT_NOT_NULL(arena); - CEL_ASSERT_NOT_NULL(status); - CEL_ASSERT(cel_Status_Ok(status)); - - cel_StringView out_name; - if (!cel_Arena_StrDup(arena, &out_name, - google_api_expr_v1alpha1_Reference_name(in))) { - cel_OutOfMemoryStatus(status); - return cel_nullptr; - } - size_t in_overloads_len; - const upb_StringView* in_overloads_ptr = - google_api_expr_v1alpha1_Reference_overload_id(in, &in_overloads_len); - if (in_overloads_len > 0 && - google_api_expr_v1alpha1_Reference_has_value(in)) { - cel_InvalidArgumentStatus( - status, cel_StringView_From("cel: resolved reference has both function " - "overloads and a constant")); - return cel_nullptr; - } - if (in_overloads_len > 0) { - cel_FunctionRef* out = cel_FunctionRef_New(out_name, arena); - if (out == cel_nullptr) { - cel_OutOfMemoryStatus(status); - return cel_nullptr; - } - for (size_t i = 0; i < in_overloads_len; ++i) { - cel_StringView out_id; - if (!cel_Arena_StrDup(arena, &out_id, in_overloads_ptr[i])) { - cel_OutOfMemoryStatus(status); - return cel_nullptr; - } - cel_FunctionOverloadRef* overload_ref = - cel_FunctionOverloadRef_New(out_id, arena); - if (overload_ref == cel_nullptr) { - cel_OutOfMemoryStatus(status); - return cel_nullptr; - } - CEL_USED(cel_FunctionRef_AppendOverload(out, overload_ref)); - } - return cel_Ref_UpCast(out); - } - cel_IdentRef* out = cel_IdentRef_New(out_name, arena); - if (out == cel_nullptr) { - cel_OutOfMemoryStatus(status); - return cel_nullptr; - } - if (google_api_expr_v1alpha1_Reference_has_value(in)) { - if (!cel_Constant_FromProtoV1Alpha1( - cel_IdentRef_MutableValue(out), - google_api_expr_v1alpha1_Reference_value(in), arena, status)) { - return cel_nullptr; - } - } - return cel_Ref_UpCast(out); -} diff --git a/cel-c/src/any.c b/cel-c/src/any.c deleted file mode 100644 index c471397..0000000 --- a/cel-c/src/any.c +++ /dev/null @@ -1,183 +0,0 @@ -// Copyright 2025 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "cel-c/src/any.h" - -#include -#include - -#include "cel-c/assert.h" -#include "cel-c/config.h" -#include "cel-c/status.h" -#include "cel-c/status_code.h" -#include "cel-c/string_view.h" -#include "cel-c/well_known_types.h" -#include "upb/mem/arena.h" -#include "upb/message/message.h" -#include "upb/mini_table/message.h" -#include "upb/reflection/def.h" -#include "upb/reflection/message.h" -#include "upb/wire/decode.h" - -_cel_AnyUnpackResult _cel_AnyUnpack( - const upb_Message* cel_nonnull in_message, - const upb_DefPool* cel_nonnull def_pool, const cel_AnyWellKnownType* wkt, - upb_Arena* cel_nonnull arena, - upb_Message* cel_nullable* cel_nonnull out_message, - const upb_MessageDef* cel_nullable* cel_nonnull out_message_def) { - CEL_ASSERT_NOT_NULL(in_message); - CEL_ASSERT_NOT_NULL(def_pool); - CEL_ASSERT_NOT_NULL(wkt); - CEL_ASSERT_NOT_NULL(arena); - CEL_ASSERT_NOT_NULL(out_message); - CEL_ASSERT_NOT_NULL(out_message_def); - - bool unpacked = false; - - while (true) { - // We expect the type URL to be in the format `/`. - cel_StringView type_url = - upb_Message_GetFieldByDef(in_message, wkt->type_url_def).str_val; - const char* type_url_data = cel_StringView_Data(type_url); - const char* slash = - memchr(type_url_data, '/', cel_StringView_Size(type_url)); - if (slash == type_url_data || slash == cel_nullptr) { - if (!unpacked) { - *out_message = cel_nullptr; - *out_message_def = cel_nullptr; - } - return _cel_AnyUnpackResult_kBadTypeUrl; - } - cel_StringView type_name = type_url; - cel_StringView_RemovePrefix(&type_name, (slash - type_url_data) + 1); - const upb_MessageDef* message_def = upb_DefPool_FindMessageByNameWithSize( - def_pool, cel_StringView_Data(type_name), - cel_StringView_Size(type_name)); - if (message_def == cel_nullptr) { - if (!unpacked) { - *out_message = cel_nullptr; - *out_message_def = cel_nullptr; - } - return _cel_AnyUnpackResult_kDefNotFound; - } - const upb_MiniTable* message_tab = upb_MessageDef_MiniTable(message_def); - upb_Message* message = upb_Message_New(message_tab, arena); - if (message == cel_nullptr) { - if (!unpacked) { - *out_message = cel_nullptr; - *out_message_def = cel_nullptr; - } - return _cel_AnyUnpackResult_kOutOfMemory; - } - cel_StringView value = - upb_Message_GetFieldByDef(in_message, wkt->value_def).str_val; - upb_DecodeStatus status = upb_Decode( - cel_StringView_Data(value), cel_StringView_Size(value), message, - message_tab, upb_DefPool_ExtensionRegistry(def_pool), - kUpb_DecodeOption_AliasString, arena); - if (status == kUpb_DecodeStatus_Ok) { - *out_message = message; - *out_message_def = message_def; - if (upb_MessageDef_WellKnownType(message_def) == kUpb_WellKnown_Any) { - CEL_ASSERT_EQ(message_def, wkt->def); - in_message = message; - unpacked = true; - continue; - } - return _cel_AnyUnpackResult_kOk; - } - if (!unpacked) { - *out_message = cel_nullptr; - *out_message_def = cel_nullptr; - } - switch (status) { - case kUpb_DecodeStatus_Ok: - CEL_UNREACHABLE(); - case kUpb_DecodeStatus_Malformed: - return _cel_AnyUnpackResult_kMalformed; - case kUpb_DecodeStatus_OutOfMemory: - return _cel_AnyUnpackResult_kOutOfMemory; - case kUpb_DecodeStatus_BadUtf8: - return _cel_AnyUnpackResult_kBadUtf8; - case kUpb_DecodeStatus_MaxDepthExceeded: - return _cel_AnyUnpackResult_kMaxDepthExceeded; - default: - return _cel_AnyUnpackResult_kUnknown; - } - } -} - -void _cel_AnyUnpackResult_ToStatus(_cel_AnyUnpackResult result, - cel_Status* cel_nonnull status) { - switch (result) { - case _cel_AnyUnpackResult_kOk: - cel_Status_Clear(status); - return; - case _cel_AnyUnpackResult_kOutOfMemory: - cel_OutOfMemoryStatus(status); - return; - default: - cel_CanonicalStatus( - status, _cel_AnyUnpackResult_ToStatusCode(result), - cel_StringView_FromString(_cel_AnyUnpackResult_ToMessage(result))); - return; - } -} - -cel_StatusCode _cel_AnyUnpackResult_ToStatusCode(_cel_AnyUnpackResult result) { - switch (result) { - case _cel_AnyUnpackResult_kOk: - return cel_StatusCode_kOk; - case _cel_AnyUnpackResult_kOutOfMemory: - return cel_StatusCode_kResourceExhausted; - case _cel_AnyUnpackResult_kBadTypeUrl: - return cel_StatusCode_kInvalidArgument; - case _cel_AnyUnpackResult_kDefNotFound: - return cel_StatusCode_kNotFound; - case _cel_AnyUnpackResult_kMalformed: - return cel_StatusCode_kInvalidArgument; - case _cel_AnyUnpackResult_kBadUtf8: - return cel_StatusCode_kInvalidArgument; - case _cel_AnyUnpackResult_kMaxDepthExceeded: - return cel_StatusCode_kInvalidArgument; - case _cel_AnyUnpackResult_kUnknown: - return cel_StatusCode_kUnknown; - default: - CEL_UNREACHABLE(); - } -} - -const char* cel_nonnull -_cel_AnyUnpackResult_ToMessage(_cel_AnyUnpackResult result) { - switch (result) { - case _cel_AnyUnpackResult_kOk: - return "OK"; - case _cel_AnyUnpackResult_kOutOfMemory: - return "out of memory"; - case _cel_AnyUnpackResult_kBadTypeUrl: - return "bad type URL"; - case _cel_AnyUnpackResult_kDefNotFound: - return "descriptor not found"; - case _cel_AnyUnpackResult_kMalformed: - return "malformed wire format"; - case _cel_AnyUnpackResult_kBadUtf8: - return "bad UTF-8"; - case _cel_AnyUnpackResult_kMaxDepthExceeded: - return "max depth exceeded"; - case _cel_AnyUnpackResult_kUnknown: - return "unknown error"; - default: - CEL_UNREACHABLE(); - } -} diff --git a/cel-c/src/bit.c b/cel-c/src/bit.c deleted file mode 100644 index 4031d14..0000000 --- a/cel-c/src/bit.c +++ /dev/null @@ -1,129 +0,0 @@ -// Copyright 2024 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "cel-c/src/bit.h" - -#include // IWYU pragma: keep -#include // IWYU pragma: keep - -#include "cel-c/config.h" - -#if CEL_HAVE_INCLUDE() -#include -#endif - -#if !(defined(__STDC_VERSION_STDBIT_H__) && \ - __STDC_VERSION_STDBIT_H__ >= 202311L) - -#if !(((defined(__GNUC__) && !defined(__clang__)) || \ - CEL_HAVE_BUILTIN(__builtin_clz)) || \ - (defined(_MSC_VER) && (defined(_M_X64) || defined(_M_ARM64) || \ - defined(_M_X86) || defined(_M_ARM)))) -static const unsigned char _cel_kLeadingZerosDeBruijn[32] = { - 0, 9, 1, 10, 13, 21, 2, 29, 11, 14, 16, 18, 22, 25, 3, 30, - 8, 12, 20, 28, 15, 17, 24, 7, 19, 27, 23, 6, 26, 5, 4, 31, -}; - -int _cel_leading_zeros_ui(unsigned int x) { - CEL_STATIC_ASSERT(sizeof(x) == 4); - if (x == 0) { - return sizeof(x) * CHAR_BIT; - } - x |= x >> 1; - x |= x >> 2; - x |= x >> 4; - x |= x >> 8; - x |= x >> 16; - return ( - int)_cel_kLeadingZerosDeBruijn[((unsigned int)(x * 0x07c4acddu)) >> 27]; -} -#endif - -#if !(((defined(__GNUC__) && !defined(__clang__)) || \ - CEL_HAVE_BUILTIN(__builtin_clzl)) || \ - (defined(_MSC_VER) && (defined(_M_X64) || defined(_M_ARM64) || \ - defined(_M_X86) || defined(_M_ARM)))) -int _cel_leading_zeros_ul(unsigned long x) { - CEL_STATIC_ASSERT(sizeof(x) == 4 || sizeof(x) == 8); -#if LONG_MAX == INT32_MAX - return _cel_leading_zeros_ui((unsigned int)x); -#elif LONG_MAX == INT64_MAX - return _cel_leading_zeros_ull((unsigned long long)x); -#else -#error Unreachable. -#endif -} -#endif - -#if !(((defined(__GNUC__) && !defined(__clang__)) || \ - CEL_HAVE_BUILTIN(__builtin_clzll)) || \ - (defined(_MSC_VER) && (defined(_M_X64) || defined(_M_ARM64)))) -int _cel_leading_zeros_ull(unsigned long long x) { - CEL_STATIC_ASSERT(sizeof(x) == 8); - int count = _cel_leading_zeros_ui((unsigned int)(x >> 32)); - return count == sizeof(unsigned int) * CHAR_BIT - ? count + _cel_leading_zeros_ui((unsigned int)x) - : count; -} -#endif - -#if !(((defined(__GNUC__) && !defined(__clang__)) || \ - CEL_HAVE_BUILTIN(__builtin_ctz)) || \ - (defined(_MSC_VER) && (defined(_M_X64) || defined(_M_ARM64) || \ - defined(_M_X86) || defined(_M_ARM)))) -static const unsigned char _cel_kTralingZerosDeBruijn[32] = { - 0, 1, 28, 2, 29, 14, 24, 3, 30, 22, 20, 15, 25, 17, 4, 8, - 31, 27, 13, 23, 21, 19, 16, 7, 26, 12, 18, 6, 11, 5, 10, 9, -}; - -int _cel_trailing_zeros_ui(unsigned int x) { - CEL_STATIC_ASSERT(sizeof(x) == 4); - if (x == 0) { - return sizeof(x) * CHAR_BIT; - } - return ( - int)_cel_kTralingZerosDeBruijn[((unsigned int)((v & -v) * 0x077cb531u)) >> - 27]; -} -#endif - -#if !(((defined(__GNUC__) && !defined(__clang__)) || \ - CEL_HAVE_BUILTIN(__builtin_ctzl)) || \ - (defined(_MSC_VER) && (defined(_M_X64) || defined(_M_ARM64) || \ - defined(_M_X86) || defined(_M_ARM)))) -int _cel_trailing_zeros_ul(unsigned long x) { - CEL_STATIC_ASSERT(sizeof(x) == 4 || sizeof(x) == 8); -#if LONG_MAX == INT32_MAX - return _cel_trailing_zeros_ui((unsigned int)x); -#elif LONG_MAX == INT64_MAX - return _cel_trailing_zeros_ull((unsigned long long)x); -#else -#error Unreachable. -#endif -} -#endif - -#if !(((defined(__GNUC__) && !defined(__clang__)) || \ - CEL_HAVE_BUILTIN(__builtin_ctzll)) || \ - (defined(_MSC_VER) && (defined(_M_X64) || defined(_M_ARM64)))) -int _cel_trailing_zeros_ull(unsigned long long x) { - CEL_STATIC_ASSERT(sizeof(x) == 8); - int count = _cel_trailing_zeros_ui((unsigned int)x); - return count == sizeof(unsigned int) * CHAR_BIT - ? count + _cel_trailing_zeros_ui((unsigned int)(x >> 32)) - : count; -} -#endif - -#endif diff --git a/cel-c/src/bitset.c b/cel-c/src/bitset.c deleted file mode 100644 index 2fb3c1b..0000000 --- a/cel-c/src/bitset.c +++ /dev/null @@ -1,54 +0,0 @@ -// Copyright 2024 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "cel-c/src/bitset.h" - -#include // IWYU pragma: keep -#include - -#include "cel-c/assert.h" -#include "cel-c/config.h" -#include "cel-c/src/bit.h" - -bool _cel_BitSet_Next(CEL_NULLABLE(const _cel_BitSetWord*) words, size_t bits, - CEL_NONNULL(size_t*) bit) { - CEL_ASSERT(words != cel_nullptr || bits == 0); - CEL_ASSERT_NOT_NULL(bit); - size_t i = *bit; - // If `i` is `_cel_BitSet_kBegin`, `++i` will wrap back around to 0. - ++i; - while (i < bits) { - const _cel_BitSetWord word_index = _cel_BitSet_WordIndexForBit(i); - const _cel_BitSetWord word = words[word_index]; - // Check if any bits are set in word. If they are not, skip to the next - // word. - if (word != 0) { - const int bit_index = _cel_BitSet_BitIndexForBit(i); - const _cel_BitSetWord word_mask = - ~((((_cel_BitSetWord)1) << bit_index) - 1); - const _cel_BitSetWord masked_word = word & word_mask; - // If the masked word does not have any bits set, we can skip to the next - // word. - if (masked_word != 0) { - const int n = _cel_trailing_zeros(masked_word); - CEL_ASSERT(n >= ((size_t)bit_index) && n < _cel_BitSet_kBitsPerWord); - *bit = (word_index * _cel_BitSet_kBitsPerWord) + n; - return true; - } - } - i = ((word_index + 1) * _cel_BitSet_kBitsPerWord); - } - *bit = bits; - return false; -} diff --git a/cel-c/src/charconv.c b/cel-c/src/charconv.c deleted file mode 100644 index 04df620..0000000 --- a/cel-c/src/charconv.c +++ /dev/null @@ -1,393 +0,0 @@ -// Copyright 2025 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "cel-c/src/charconv.h" - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "cel-c/assert.h" -#include "cel-c/config.h" -#include "cel-c/src/ckdint.h" -#include "cel-c/src/config.h" -#include "cel-c/src/ctype.h" - -// NOLINTBEGIN(runtime/int) -// NOLINTBEGIN(google-runtime-int) - -CEL_ATTRIBUTE_NODISCARD -static bool _cel_FromChar(char* cel_nonnull out, char in, int base) { - if (in >= '0' && in <= '9') { - *out = in - '0'; - return *out < base; - } - if (base >= 10 && in >= 'a' && in <= 'z') { - *out = (in - 'a') + (char)10; - return *out < base; - } - if (base >= 10 && in >= 'A' && in <= 'Z') { - *out = (in - 'A') + (char)10; - return *out < base; - } - return false; -} - -_cel_FromCharsResult _cel_FromChars_signed(const char* cel_nonnull first, - const char* cel_nonnull last, - long long* cel_nonnull val, int base, - long long min, long long max) { - bool negative = first != last && *first == '-'; - if (negative) { - ++first; - } - _cel_FromCharsResult result; - result.ec = 0; - bool digits = false; - *val = 0; - while (first != last) { - char digit; - if (!_cel_FromChar(&digit, *first, base)) { - break; - } - if (_cel_ckd_mul(val, *val, (long long)base)) { - result.ec = ERANGE; - break; - } - if (_cel_ckd_add(val, *val, (long long)digit)) { - result.ec = ERANGE; - break; - } - if (*val < min || *val > max) { - result.ec = ERANGE; - break; - } - digits = true; - ++first; - } - result.ptr = first; - if (!digits) { - result.ec = EINVAL; - } else if (negative && _cel_ckd_mul(val, *val, (long long)-1) && - (*val < min || *val > max)) { - result.ec = ERANGE; - } - return result; -} - -_cel_FromCharsResult _cel_FromChars_unsigned( - const char* cel_nonnull first, const char* cel_nonnull last, - unsigned long long* cel_nonnull val, int base, unsigned long long max) { - _cel_FromCharsResult result; - result.ec = 0; - bool digits = false; - *val = 0; - while (first != last) { - char digit; - if (!_cel_FromChar(&digit, *first, base)) { - break; - } - if (_cel_ckd_mul(val, *val, (unsigned long long)base)) { - result.ec = ERANGE; - break; - } - if (_cel_ckd_add(val, *val, (unsigned long long)digit)) { - result.ec = ERANGE; - break; - } - if (*val > max) { - result.ec = ERANGE; - break; - } - digits = true; - ++first; - } - result.ptr = first; - if (!digits) { - result.ec = EINVAL; - } - return result; -} - -typedef struct { - char str[5]; - uint8_t len; -} _cel_FromChars_LocaleRadix; - -CEL_ATTRIBUTE_NODISCARD -static _cel_FromChars_LocaleRadix _cel_FromChars_GetLocaleRadix() { - _cel_FromChars_LocaleRadix result; -#ifdef LC_GLOBAL_LOCALE - struct lconv* lc = localeconv(); - result.len = (uint8_t)strlen(lc->decimal_point); - CEL_ASSERT_GT(result.len, 0); - CEL_ASSERT_LE(result.len, 4); - memcpy(result.str, lc->decimal_point, result.len); - result.str[result.len] = '\0'; -#else - char buffer[/*1*/ 1 + /**/ 4 + /*5*/ 1 + /*\0*/ 1]; - snprintf(buffer, sizeof(buffer) / sizeof(buffer[0]), "%.1f", 1.5f); - size_t len = strlen(buffer); - CEL_ASSERT_GT(len, 2); - CEL_ASSERT_EQ(buffer[0], '1'); - CEL_ASSERT_EQ(buffer[len - 1], '5'); - size_t out_len = len - 2; - CEL_ASSERT_GE(out_len, 1); - CEL_ASSERT_LE(out_len, 4); - result.len = (uint8_t)(len - 2); - memcpy(result.str, buffer + 1, out_len); - result.str[result.len] = '\0'; -#endif - return result; -} - -CEL_ATTRIBUTE_NODISCARD -static const char* cel_nonnull _cel_FromChars_MatchMinus( - const char* cel_nonnull first, const char* cel_nonnull last) { - if (first == last || *first != '-') { - return first; - } - return first + 1; -} - -CEL_ATTRIBUTE_NODISCARD -static const char* cel_nonnull _cel_FromChars_MatchDigits( - const char* cel_nonnull first, const char* cel_nonnull last) { - while (first != last) { - if (!_cel_isdigit(*first)) { - break; - } - ++first; - } - return first; -} - -CEL_ATTRIBUTE_NODISCARD -static const char* cel_nonnull _cel_FromChars_MatchDot( - const char* cel_nonnull first, const char* cel_nonnull last) { - if (first == last || *first != '.') { - return first; - } - return first + 1; -} - -CEL_ATTRIBUTE_NODISCARD -static const char* cel_nonnull _cel_FromChars_MatchE( - const char* cel_nonnull first, const char* cel_nonnull last) { - if (first == last || (*first != 'e' && *first != 'E')) { - return first; - } - return first + 1; -} - -CEL_ATTRIBUTE_NODISCARD -static const char* cel_nonnull _cel_FromChars_MatchSign( - const char* cel_nonnull first, const char* cel_nonnull last) { - if (first == last || (*first != '-' && *first != '+')) { - return first; - } - return first + 1; -} - -CEL_ATTRIBUTE_NODISCARD -static int _cel_FromChars_Match(const char* cel_nonnull first, - const char* cel_nonnull last, - char* cel_nonnull out, size_t maxlen, - const char* cel_nullable* cel_nonnull end, - const char* cel_nullable* cel_nonnull radix, - uint8_t* cel_nonnull radixadj) { - const char* cel_nonnull ptr = first; - ptr = _cel_FromChars_MatchMinus(ptr, last); - ptr = _cel_FromChars_MatchDigits(ptr, last); - const char* cel_nullable sep = _cel_FromChars_MatchDot(ptr, last); - if (sep == ptr) { - sep = NULL; - } else { - const char* next = sep; - sep = ptr; - ptr = next; - } - ptr = _cel_FromChars_MatchDigits(ptr, last); - ptr = _cel_FromChars_MatchE(ptr, last); - ptr = _cel_FromChars_MatchSign(ptr, last); - ptr = _cel_FromChars_MatchDigits(ptr, last); - *end = ptr; - size_t len = ptr - first; - if (len >= maxlen) { - return ERANGE; - } - if (sep != NULL) { - _cel_FromChars_LocaleRadix r = _cel_FromChars_GetLocaleRadix(); - size_t before_radix = sep - first; - size_t after_radix = sep < ptr ? (ptr - (sep + 1)) : 0; - memcpy(out, first, before_radix); - memcpy(out + before_radix, r.str, r.len); - memcpy(out + before_radix + r.len, sep + 1, after_radix); - out[before_radix + r.len + after_radix] = '\0'; - *radix = sep; - *radixadj = r.len - 1; - } else { - memcpy(out, first, len); - out[len] = '\0'; - *radix = NULL; - *radixadj = 0; - } - return 0; -} - -_cel_FromCharsResult _cel_FromChars_f(const char* cel_nonnull first, - const char* cel_nonnull last, - float* cel_nonnull val) { - _cel_FromCharsResult result; - char buffer[FLT_MANT_DIG + FLT_MAX_EXP + 1 + 4 + 1 + 1]; - const char* radix; - uint8_t radixadj; - result.ec = _cel_FromChars_Match(first, last, buffer, sizeof(buffer) - 3, - &result.ptr, &radix, &radixadj); - if (result.ec != 0) { - return result; - } - size_t radixoff = SIZE_MAX; - if (radix != NULL) { - radixoff = radix - first; - } - int prev_errno = errno; - errno = 0; - char* endptr; - *val = strtof(buffer, &endptr); - result.ec = errno; - result.ptr = first + (endptr - buffer) - - (endptr - buffer > radixoff ? radixadj : ((uint8_t)0)); - errno = prev_errno; - return result; -} - -_cel_FromCharsResult _cel_FromChars_d(const char* cel_nonnull first, - const char* cel_nonnull last, - double* cel_nonnull val) { - _cel_FromCharsResult result; - const char* radix; - uint8_t radixadj; - char buffer[DBL_MANT_DIG + DBL_MAX_EXP + 1 + 4 + 1 + 1]; - result.ec = _cel_FromChars_Match(first, last, buffer, sizeof(buffer) - 3, - &result.ptr, &radix, &radixadj); - if (result.ec != 0) { - return result; - } - size_t radixoff = SIZE_MAX; - if (radix != NULL) { - radixoff = radix - first; - } - int prev_errno = errno; - errno = 0; - char* endptr; - *val = strtod(buffer, &endptr); - result.ec = errno; - result.ptr = first + (endptr - buffer) - - (endptr - buffer > radixoff ? radixadj : ((uint8_t)0)); - errno = prev_errno; - return result; -} - -static const char* _cel_ToChars_kDigits = - "0123456789abcdefghijklmnopqrstuvwxyz"; - -static void _cel_ToChars_Reverse(char* cel_nonnull first, - char* cel_nonnull last) { - if (first < last) { - --last; - while (first < last) { - char c = *first; - *first = *last; - *last = c; - ++first; - --last; - } - } -} - -size_t _cel_ToChars_ll(char* cel_nonnull out, long long val, int base) { - CEL_ASSERT_NOT_NULL(out); - CEL_ASSERT_GE(base, 2); - CEL_ASSERT_LE(base, 36); - - const bool negative = val < 0; - if (negative) { - *out++ = '-'; - } - char* begin = out; - do { - int i = (int)(val % base); - if (negative) { - i = -i; - } - *out++ = _cel_ToChars_kDigits[i]; - val /= base; - } while (val != 0); - _cel_ToChars_Reverse(begin, out); - return (size_t)(out - begin) + negative; -} - -size_t _cel_ToChars_ull(char* cel_nonnull out, unsigned long long val, - int base) { - CEL_ASSERT_NOT_NULL(out); - CEL_ASSERT_GE(base, 2); - CEL_ASSERT_LE(base, 36); - - char* begin = out; - do { - int i = (int)(val % base); - *out++ = _cel_ToChars_kDigits[i]; - val /= base; - } while (val != 0); - _cel_ToChars_Reverse(begin, out); - return (size_t)(out - begin); -} - -CEL_ATTRIBUTE_NODISCARD -static size_t _cel_ToChars_FixLocale(char* cel_nonnull p) { - _cel_FromChars_LocaleRadix radix = _cel_FromChars_GetLocaleRadix(); - size_t n = strlen(p); - char* r = strstr(p, radix.str); - if (r == NULL) { - return n; - } - if (radix.len != 1) { - memmove(r + 1, r + radix.len, (p + n) - (r + radix.len)); - n -= radix.len - 1; - p[n] = '\0'; - } - *r = '.'; - return n; -} - -size_t _cel_ToChars_f(char* cel_nonnull first, float val) { - first[0] = '\0'; - snprintf(first, _CEL_MAX_FLOAT_CHARS, "%.9g", val); - return _cel_ToChars_FixLocale(first); -} - -size_t _cel_ToChars_d(char* cel_nonnull first, double val) { - first[0] = '\0'; - snprintf(first, _CEL_MAX_DOUBLE_CHARS, "%.17g", val); - return _cel_ToChars_FixLocale(first); -} - -// NOLINTEND(google-runtime-int) -// NOLINTEND(runtime/int) diff --git a/cel-c/src/ctype.c b/cel-c/src/ctype.c deleted file mode 100644 index 0eb6e1e..0000000 --- a/cel-c/src/ctype.c +++ /dev/null @@ -1,98 +0,0 @@ -// Copyright 2025 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "cel-c/src/ctype.h" - -const unsigned char _cel_CType_kProperties[256] = { - 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, // 0x00 - 0x40, 0x68, 0x48, 0x48, 0x48, 0x48, 0x40, 0x40, - 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, // 0x10 - 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, - 0x28, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, // 0x20 - 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, - 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, // 0x30 - 0x84, 0x84, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, - 0x10, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x05, // 0x40 - 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, - 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, // 0x50 - 0x05, 0x05, 0x05, 0x10, 0x10, 0x10, 0x10, 0x10, - 0x10, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x05, // 0x60 - 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, - 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, // 0x70 - 0x05, 0x05, 0x05, 0x10, 0x10, 0x10, 0x10, 0x40, -}; - -const char _cel_CType_kToLower[256] = { - '\x00', '\x01', '\x02', '\x03', '\x04', '\x05', '\x06', '\x07', '\x08', - '\x09', '\x0a', '\x0b', '\x0c', '\x0d', '\x0e', '\x0f', '\x10', '\x11', - '\x12', '\x13', '\x14', '\x15', '\x16', '\x17', '\x18', '\x19', '\x1a', - '\x1b', '\x1c', '\x1d', '\x1e', '\x1f', '\x20', '\x21', '\x22', '\x23', - '\x24', '\x25', '\x26', '\x27', '\x28', '\x29', '\x2a', '\x2b', '\x2c', - '\x2d', '\x2e', '\x2f', '\x30', '\x31', '\x32', '\x33', '\x34', '\x35', - '\x36', '\x37', '\x38', '\x39', '\x3a', '\x3b', '\x3c', '\x3d', '\x3e', - '\x3f', '\x40', 'a', 'b', 'c', 'd', 'e', 'f', 'g', - 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', - 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', - 'z', '\x5b', '\x5c', '\x5d', '\x5e', '\x5f', '\x60', '\x61', '\x62', - '\x63', '\x64', '\x65', '\x66', '\x67', '\x68', '\x69', '\x6a', '\x6b', - '\x6c', '\x6d', '\x6e', '\x6f', '\x70', '\x71', '\x72', '\x73', '\x74', - '\x75', '\x76', '\x77', '\x78', '\x79', '\x7a', '\x7b', '\x7c', '\x7d', - '\x7e', '\x7f', '\x80', '\x81', '\x82', '\x83', '\x84', '\x85', '\x86', - '\x87', '\x88', '\x89', '\x8a', '\x8b', '\x8c', '\x8d', '\x8e', '\x8f', - '\x90', '\x91', '\x92', '\x93', '\x94', '\x95', '\x96', '\x97', '\x98', - '\x99', '\x9a', '\x9b', '\x9c', '\x9d', '\x9e', '\x9f', '\xa0', '\xa1', - '\xa2', '\xa3', '\xa4', '\xa5', '\xa6', '\xa7', '\xa8', '\xa9', '\xaa', - '\xab', '\xac', '\xad', '\xae', '\xaf', '\xb0', '\xb1', '\xb2', '\xb3', - '\xb4', '\xb5', '\xb6', '\xb7', '\xb8', '\xb9', '\xba', '\xbb', '\xbc', - '\xbd', '\xbe', '\xbf', '\xc0', '\xc1', '\xc2', '\xc3', '\xc4', '\xc5', - '\xc6', '\xc7', '\xc8', '\xc9', '\xca', '\xcb', '\xcc', '\xcd', '\xce', - '\xcf', '\xd0', '\xd1', '\xd2', '\xd3', '\xd4', '\xd5', '\xd6', '\xd7', - '\xd8', '\xd9', '\xda', '\xdb', '\xdc', '\xdd', '\xde', '\xdf', '\xe0', - '\xe1', '\xe2', '\xe3', '\xe4', '\xe5', '\xe6', '\xe7', '\xe8', '\xe9', - '\xea', '\xeb', '\xec', '\xed', '\xee', '\xef', '\xf0', '\xf1', '\xf2', - '\xf3', '\xf4', '\xf5', '\xf6', '\xf7', '\xf8', '\xf9', '\xfa', '\xfb', - '\xfc', '\xfd', '\xfe', '\xff', -}; - -const char _cel_CType_kToUpper[256] = { - '\x00', '\x01', '\x02', '\x03', '\x04', '\x05', '\x06', '\x07', '\x08', - '\x09', '\x0a', '\x0b', '\x0c', '\x0d', '\x0e', '\x0f', '\x10', '\x11', - '\x12', '\x13', '\x14', '\x15', '\x16', '\x17', '\x18', '\x19', '\x1a', - '\x1b', '\x1c', '\x1d', '\x1e', '\x1f', '\x20', '\x21', '\x22', '\x23', - '\x24', '\x25', '\x26', '\x27', '\x28', '\x29', '\x2a', '\x2b', '\x2c', - '\x2d', '\x2e', '\x2f', '\x30', '\x31', '\x32', '\x33', '\x34', '\x35', - '\x36', '\x37', '\x38', '\x39', '\x3a', '\x3b', '\x3c', '\x3d', '\x3e', - '\x3f', '\x40', '\x41', '\x42', '\x43', '\x44', '\x45', '\x46', '\x47', - '\x48', '\x49', '\x4a', '\x4b', '\x4c', '\x4d', '\x4e', '\x4f', '\x50', - '\x51', '\x52', '\x53', '\x54', '\x55', '\x56', '\x57', '\x58', '\x59', - '\x5a', '\x5b', '\x5c', '\x5d', '\x5e', '\x5f', '\x60', 'A', 'B', - 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', - 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', - 'U', 'V', 'W', 'X', 'Y', 'Z', '\x7b', '\x7c', '\x7d', - '\x7e', '\x7f', '\x80', '\x81', '\x82', '\x83', '\x84', '\x85', '\x86', - '\x87', '\x88', '\x89', '\x8a', '\x8b', '\x8c', '\x8d', '\x8e', '\x8f', - '\x90', '\x91', '\x92', '\x93', '\x94', '\x95', '\x96', '\x97', '\x98', - '\x99', '\x9a', '\x9b', '\x9c', '\x9d', '\x9e', '\x9f', '\xa0', '\xa1', - '\xa2', '\xa3', '\xa4', '\xa5', '\xa6', '\xa7', '\xa8', '\xa9', '\xaa', - '\xab', '\xac', '\xad', '\xae', '\xaf', '\xb0', '\xb1', '\xb2', '\xb3', - '\xb4', '\xb5', '\xb6', '\xb7', '\xb8', '\xb9', '\xba', '\xbb', '\xbc', - '\xbd', '\xbe', '\xbf', '\xc0', '\xc1', '\xc2', '\xc3', '\xc4', '\xc5', - '\xc6', '\xc7', '\xc8', '\xc9', '\xca', '\xcb', '\xcc', '\xcd', '\xce', - '\xcf', '\xd0', '\xd1', '\xd2', '\xd3', '\xd4', '\xd5', '\xd6', '\xd7', - '\xd8', '\xd9', '\xda', '\xdb', '\xdc', '\xdd', '\xde', '\xdf', '\xe0', - '\xe1', '\xe2', '\xe3', '\xe4', '\xe5', '\xe6', '\xe7', '\xe8', '\xe9', - '\xea', '\xeb', '\xec', '\xed', '\xee', '\xef', '\xf0', '\xf1', '\xf2', - '\xf3', '\xf4', '\xf5', '\xf6', '\xf7', '\xf8', '\xf9', '\xfa', '\xfb', - '\xfc', '\xfd', '\xfe', '\xff', -}; diff --git a/cel-c/src/empty_list_value.c b/cel-c/src/empty_list_value.c deleted file mode 100644 index 7c8a9aa..0000000 --- a/cel-c/src/empty_list_value.c +++ /dev/null @@ -1,170 +0,0 @@ -// Copyright 2025 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "cel-c/src/empty_list_value.h" - -#include -#include -#include -#include - -#include "cel-c/assert.h" -#include "cel-c/config.h" -#include "cel-c/error.h" -#include "cel-c/error_code.h" -#include "cel-c/status.h" -#include "cel-c/string_view.h" -#include "cel-c/value.h" - -static const cel_ListValueIteratorVTable _cel_EmptyListValueIteratorVTable; - -static bool _cel_EmptyListValue_FastSize( - const cel_ListValueVTable* cel_nonnull vtable, cel_ValueContent content, - size_t* cel_nonnull size) { - CEL_ASSERT_EQ(vtable, &_cel_EmptyListValueVTable); - CEL_ASSERT_NOT_NULL(size); - - *size = 0; - return true; -} - -static bool _cel_EmptyListValue_SlowSize( - const cel_ListValueVTable* cel_nonnull vtable, cel_ValueContent content, - const cel_ValueContext* cel_nonnull context, cel_Value* cel_nonnull size, - cel_Status* cel_nonnull status) { - CEL_ASSERT_EQ(vtable, &_cel_EmptyListValueVTable); - CEL_ASSERT_NOT_NULL(context); - CEL_ASSERT_NOT_NULL(size); - CEL_ASSERT_NOT_NULL(status); - - if (CEL_UNLIKELY(!cel_Status_Ok(status))) { - return false; - } - - cel_Value_SetInt(size, 0); - return true; -} - -static bool _cel_EmptyListValue_Get( - const cel_ListValueVTable* cel_nonnull vtable, cel_ValueContent content, - const cel_ValueContext* cel_nonnull context, size_t index, - cel_Value* cel_nonnull element, cel_Status* cel_nonnull status) { - CEL_ASSERT_EQ(vtable, &_cel_EmptyListValueVTable); - CEL_ASSERT_NOT_NULL(context); - CEL_ASSERT_NOT_NULL(element); - CEL_ASSERT_NOT_NULL(status); - - if (CEL_UNLIKELY(!cel_Status_Ok(status))) { - return false; - } - - cel_Error* error = cel_Error_New(context->arena); - if (CEL_UNLIKELY(error == cel_nullptr)) { - cel_OutOfMemoryStatus(status); - return false; - } - cel_Error_SetCanonicalCode(error, cel_ErrorCode_kOutOfRange); - cel_Error_SetMessage(error, cel_StringView_From("index out of range")); - cel_Value_SetError(element, error); - return true; -} - -static cel_ListValueIterator* cel_nullable _cel_EmptyListValue_NewIterator( - const cel_ListValueVTable* cel_nonnull vtable, cel_ValueContent content, - const cel_ValueContext* cel_nonnull context, - cel_Status* cel_nonnull status) { - CEL_ASSERT_EQ(vtable, &_cel_EmptyListValueVTable); - CEL_ASSERT_NOT_NULL(context); - CEL_ASSERT_NOT_NULL(status); - - if (CEL_UNLIKELY(!cel_Status_Ok(status))) { - return cel_nullptr; - } - - return &_cel_EmptyListValueIterator; -} - -const cel_ListValueVTable _cel_EmptyListValueVTable = { - .Equals = cel_nullptr, - .FastSize = &_cel_EmptyListValue_FastSize, - .SlowSize = &_cel_EmptyListValue_SlowSize, - .Get = &_cel_EmptyListValue_Get, - .NewIterator = &_cel_EmptyListValue_NewIterator, -}; - -static bool _cel_EmptyListValueIterator_Next1( - cel_ValueIterator* cel_nonnull iterator, - const cel_ValueContext* cel_nonnull context, - cel_Value* cel_nonnull key_or_value, cel_Status* cel_nonnull status) { - CEL_ASSERT_NOT_NULL(iterator); - CEL_ASSERT_EQ(iterator->vtable, &_cel_EmptyListValueIteratorVTable.super); - CEL_ASSERT_NOT_NULL(context); - CEL_ASSERT_NOT_NULL(key_or_value); - CEL_ASSERT_NOT_NULL(status); - - return false; -} - -static bool _cel_EmptyListValueIterator_Next2( - cel_ValueIterator* cel_nonnull iterator, - const cel_ValueContext* cel_nonnull context, cel_Value* cel_nonnull key, - cel_Value* cel_nonnull value, cel_Status* cel_nonnull status) { - CEL_ASSERT_NOT_NULL(iterator); - CEL_ASSERT_EQ(iterator->vtable, &_cel_EmptyListValueIteratorVTable.super); - CEL_ASSERT_NOT_NULL(context); - CEL_ASSERT_NOT_NULL(key); - CEL_ASSERT_NOT_NULL(value); - CEL_ASSERT_NOT_NULL(status); - - return false; -} - -static bool _cel_EmptyListValueIterator_Remaining( - const cel_ValueIterator* cel_nonnull iterator, - size_t* cel_nonnull remaining) { - CEL_ASSERT_NOT_NULL(iterator); - CEL_ASSERT_EQ(iterator->vtable, &_cel_EmptyListValueIteratorVTable.super); - CEL_ASSERT_NOT_NULL(remaining); - - *remaining = 0; - return true; -} - -static bool _cel_EmptyListValueIterator_Next( - cel_ListValueIterator* cel_nonnull iterator, - const cel_ValueContext* cel_nonnull context, size_t* cel_nullable index, - cel_Value* cel_nonnull value, cel_Status* cel_nonnull status) { - CEL_ASSERT_NOT_NULL(iterator); - CEL_ASSERT_EQ(iterator->vtable, &_cel_EmptyListValueIteratorVTable); - CEL_ASSERT_NOT_NULL(context); - CEL_ASSERT_NOT_NULL(value); - CEL_ASSERT_NOT_NULL(status); - - return false; -} - -static const cel_ListValueIteratorVTable _cel_EmptyListValueIteratorVTable = { - .super = - { - .Delete = cel_nullptr, - .Next1 = &_cel_EmptyListValueIterator_Next1, - .Next2 = &_cel_EmptyListValueIterator_Next2, - .Remaining = &_cel_EmptyListValueIterator_Remaining, - }, - .Next = &_cel_EmptyListValueIterator_Next, -}; - -cel_ListValueIterator _cel_EmptyListValueIterator = { - .vtable = &_cel_EmptyListValueIteratorVTable, -}; diff --git a/cel-c/src/empty_map_value.c b/cel-c/src/empty_map_value.c deleted file mode 100644 index 6f133a9..0000000 --- a/cel-c/src/empty_map_value.c +++ /dev/null @@ -1,211 +0,0 @@ -// Copyright 2025 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "cel-c/src/empty_map_value.h" - -#include -#include -#include -#include - -#include "cel-c/assert.h" -#include "cel-c/config.h" -#include "cel-c/error.h" -#include "cel-c/error_code.h" -#include "cel-c/status.h" -#include "cel-c/string_view.h" -#include "cel-c/value.h" - -static const cel_MapValueIteratorVTable _cel_EmptyMapValueIteratorVTable; - -static bool _cel_EmptyMapValue_FastSize( - const cel_MapValueVTable* cel_nonnull vtable, cel_ValueContent content, - size_t* cel_nonnull size) { - CEL_ASSERT_EQ(vtable, &_cel_EmptyMapValueVTable); - CEL_ASSERT_NOT_NULL(size); - - *size = 0; - return true; -} - -static bool _cel_EmptyMapValue_SlowSize( - const cel_MapValueVTable* cel_nonnull vtable, cel_ValueContent content, - const cel_ValueContext* cel_nonnull context, cel_Value* cel_nonnull size, - cel_Status* cel_nonnull status) { - CEL_ASSERT_EQ(vtable, &_cel_EmptyMapValueVTable); - CEL_ASSERT_NOT_NULL(context); - CEL_ASSERT_NOT_NULL(size); - CEL_ASSERT_NOT_NULL(status); - - if (CEL_UNLIKELY(!cel_Status_Ok(status))) { - return false; - } - - cel_Value_SetInt(size, 0); - return true; -} - -static bool _cel_EmptyMapValue_Get(const cel_MapValueVTable* cel_nonnull vtable, - cel_ValueContent content, - const cel_ValueContext* cel_nonnull context, - const cel_MapValueKey* cel_nonnull key, - cel_Value* cel_nonnull value, - cel_Status* cel_nonnull status) { - CEL_ASSERT_EQ(vtable, &_cel_EmptyMapValueVTable); - CEL_ASSERT_NOT_NULL(context); - CEL_ASSERT_NOT_NULL(key); - CEL_ASSERT_NOT_NULL(value); - CEL_ASSERT_NOT_NULL(status); - - if (CEL_UNLIKELY(!cel_Status_Ok(status))) { - return false; - } - - cel_Error* error = cel_Error_New(context->arena); - if (CEL_UNLIKELY(error == cel_nullptr)) { - cel_OutOfMemoryStatus(status); - return false; - } - cel_Error_SetCanonicalCode(error, cel_ErrorCode_kNotFound); - cel_Error_SetMessage(error, cel_StringView_From("no such key")); - cel_Value_SetError(value, error); - return true; -} - -static bool _cel_EmptyMapValue_Find( - const cel_MapValueVTable* cel_nonnull vtable, cel_ValueContent content, - const cel_ValueContext* cel_nonnull context, - const cel_MapValueKey* cel_nonnull key, cel_Value* cel_nonnull value, - cel_Status* cel_nonnull status) { - CEL_ASSERT_EQ(vtable, &_cel_EmptyMapValueVTable); - CEL_ASSERT_NOT_NULL(context); - CEL_ASSERT_NOT_NULL(key); - CEL_ASSERT_NOT_NULL(value); - CEL_ASSERT_NOT_NULL(status); - - return false; -} - -static bool _cel_EmptyMapValue_Has(const cel_MapValueVTable* cel_nonnull vtable, - cel_ValueContent content, - const cel_ValueContext* cel_nonnull context, - const cel_MapValueKey* cel_nonnull key, - cel_Value* cel_nonnull result, - cel_Status* cel_nonnull status) { - CEL_ASSERT_EQ(vtable, &_cel_EmptyMapValueVTable); - CEL_ASSERT_NOT_NULL(context); - CEL_ASSERT_NOT_NULL(key); - CEL_ASSERT_NOT_NULL(result); - CEL_ASSERT_NOT_NULL(status); - - if (CEL_UNLIKELY(!cel_Status_Ok(status))) { - return false; - } - - cel_Value_SetFalse(result); - return true; -} - -static cel_MapValueIterator* cel_nullable _cel_EmptyMapValue_NewIterator( - const cel_MapValueVTable* cel_nonnull vtable, cel_ValueContent content, - const cel_ValueContext* cel_nonnull context, - cel_Status* cel_nonnull status) { - CEL_ASSERT_EQ(vtable, &_cel_EmptyMapValueVTable); - CEL_ASSERT_NOT_NULL(context); - CEL_ASSERT_NOT_NULL(status); - - if (CEL_UNLIKELY(!cel_Status_Ok(status))) { - return cel_nullptr; - } - - return &_cel_EmptyMapValueIterator; -} - -const cel_MapValueVTable _cel_EmptyMapValueVTable = { - .Equals = cel_nullptr, - .FastSize = &_cel_EmptyMapValue_FastSize, - .SlowSize = &_cel_EmptyMapValue_SlowSize, - .Get = &_cel_EmptyMapValue_Get, - .Find = &_cel_EmptyMapValue_Find, - .Has = &_cel_EmptyMapValue_Has, - .NewIterator = &_cel_EmptyMapValue_NewIterator, -}; - -static bool _cel_EmptyMapValueIterator_Next1( - cel_ValueIterator* cel_nonnull iterator, - const cel_ValueContext* cel_nonnull context, - cel_Value* cel_nonnull key_or_value, cel_Status* cel_nonnull status) { - CEL_ASSERT_NOT_NULL(iterator); - CEL_ASSERT_EQ(iterator->vtable, &_cel_EmptyMapValueIteratorVTable.super); - CEL_ASSERT_NOT_NULL(context); - CEL_ASSERT_NOT_NULL(key_or_value); - CEL_ASSERT_NOT_NULL(status); - - return false; -} - -static bool _cel_EmptyMapValueIterator_Next2( - cel_ValueIterator* cel_nonnull iterator, - const cel_ValueContext* cel_nonnull context, cel_Value* cel_nonnull key, - cel_Value* cel_nonnull value, cel_Status* cel_nonnull status) { - CEL_ASSERT_NOT_NULL(iterator); - CEL_ASSERT_EQ(iterator->vtable, &_cel_EmptyMapValueIteratorVTable.super); - CEL_ASSERT_NOT_NULL(context); - CEL_ASSERT_NOT_NULL(key); - CEL_ASSERT_NOT_NULL(value); - CEL_ASSERT_NOT_NULL(status); - - return false; -} - -static bool _cel_EmptyMapValueIterator_Remaining( - const cel_ValueIterator* cel_nonnull iterator, - size_t* cel_nonnull remaining) { - CEL_ASSERT_NOT_NULL(iterator); - CEL_ASSERT_EQ(iterator->vtable, &_cel_EmptyMapValueIteratorVTable.super); - CEL_ASSERT_NOT_NULL(remaining); - - *remaining = 0; - return true; -} - -static bool _cel_EmptyMapValueIterator_Next( - cel_MapValueIterator* cel_nonnull iterator, - const cel_ValueContext* cel_nonnull context, - cel_MapValueKey* cel_nullable key, cel_Value* cel_nonnull value, - cel_Status* cel_nonnull status) { - CEL_ASSERT_NOT_NULL(iterator); - CEL_ASSERT_EQ(iterator->vtable, &_cel_EmptyMapValueIteratorVTable); - CEL_ASSERT_NOT_NULL(context); - CEL_ASSERT_NOT_NULL(key); - CEL_ASSERT_NOT_NULL(value); - CEL_ASSERT_NOT_NULL(status); - - return false; -} - -static const cel_MapValueIteratorVTable _cel_EmptyMapValueIteratorVTable = { - .super = - { - .Delete = cel_nullptr, - .Next1 = &_cel_EmptyMapValueIterator_Next1, - .Next2 = &_cel_EmptyMapValueIterator_Next2, - .Remaining = &_cel_EmptyMapValueIterator_Remaining, - }, - .Next = &_cel_EmptyMapValueIterator_Next, -}; - -cel_MapValueIterator _cel_EmptyMapValueIterator = { - .vtable = &_cel_EmptyMapValueIteratorVTable, -}; diff --git a/cel-c/src/generic_array.c b/cel-c/src/generic_array.c deleted file mode 100644 index 8d38fcb..0000000 --- a/cel-c/src/generic_array.c +++ /dev/null @@ -1,374 +0,0 @@ -// Copyright 2025 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "cel-c/src/generic_array.h" - -#include -#include // IWYU pragma: keep -#include -#include - -#include "cel-c/alloc.h" -#include "cel-c/arena.h" -#include "cel-c/assert.h" -#include "cel-c/src/config.h" -#include "cel-c/src/asan.h" -#include "cel-c/src/ckdint.h" - -static void _cel_GenericArray_Annotate(CEL_NULLABLE(const void*) ptr, - size_t cap, size_t old_len, - size_t new_len, size_t ele_size) { - _cel_sanitizer_annotate_contiguous_container( - ptr, (((CEL_NULLABLE(const char*))ptr) + (cap * ele_size)), - (((CEL_NULLABLE(const char*))ptr) + (old_len * ele_size)), - (((CEL_NULLABLE(const char*))ptr) + (new_len * ele_size))); -} - -// This function abstracts away the complication ASan imposes on us resizing. -CEL_ATTRIBUTE_NODISCARD -static bool _cel_GenericArray_ReallocateAllocator( - CEL_NONNULL(_cel_GenericArray*) arr, CEL_NONNULL(cel_Allocator*) alloc, - size_t new_len, size_t new_cap, size_t ele_size) { - CEL_ASSERT_NE(new_cap, arr->cap); - CEL_ASSERT_LE(new_len, new_cap); - size_t new_cap_bytes; - if (CEL_UNLIKELY(_cel_ckd_mul(&new_cap_bytes, new_cap, ele_size))) { - errno = ENOMEM; - return false; - } - size_t actual_new_cap_bytes; - CEL_NULLABLE(void*) new_ptr; -#ifdef _CEL_HAVE_ASAN - // Under ASan we cannot reallocate directly as we have to perform bookkeeping - // work. Instead perform an allocation, copy, and deallocate the old - // allocation. - new_ptr = cel_Allocator_Malloc(alloc, new_cap_bytes, &actual_new_cap_bytes); - if (CEL_UNLIKELY(new_ptr == cel_nullptr)) { - return false; - } - new_cap = actual_new_cap_bytes / ele_size; - // Annotate new allocation with ASan to match the state before copying to it. - _cel_GenericArray_Annotate(new_ptr, new_cap, new_cap, new_len, ele_size); - memcpy(new_ptr, arr->ptr, - (arr->len < new_len ? arr->len : new_len) * ele_size); - // Annotate the old allocation back to its original state, which is the whole - // allocation is valid. - _cel_GenericArray_Annotate(arr->ptr, arr->cap, arr->len, arr->cap, ele_size); - cel_Allocator_FreeSized(alloc, arr->ptr, arr->cap * ele_size); -#else - new_ptr = cel_Allocator_Realloc(alloc, arr->ptr, arr->cap * ele_size, - new_cap_bytes, &actual_new_cap_bytes); - if (CEL_UNLIKELY(new_ptr == cel_nullptr)) { - return false; - } - new_cap = actual_new_cap_bytes / ele_size; -#endif - arr->ptr = new_ptr; - arr->cap = new_cap; - arr->len = new_len; - return true; -} - -void _cel_GenericArray_Construct(CEL_NONNULL(_cel_GenericArray*) arr) { - CEL_ASSERT_NOT_NULL(arr); - memset(arr, '\0', sizeof(*arr)); -} - -void _cel_GenericArray_DestructAllocator(CEL_NONNULL(_cel_GenericArray*) arr, - CEL_NONNULL(cel_Allocator*) alloc, - size_t ele_size) { - CEL_ASSERT_NOT_NULL(arr); - CEL_ASSERT_NOT_NULL(alloc); - CEL_ASSERT_GT(ele_size, 0); - CEL_ASSERT_LE(arr->len, arr->cap); - if (arr->cap > 0) { - _cel_GenericArray_Annotate(arr->ptr, arr->cap, /*old_len=*/arr->len, - /*new_len=*/arr->cap, ele_size); - cel_Allocator_FreeSized(alloc, arr->ptr, arr->cap * ele_size); - } -} - -bool _cel_GenericArray_ReserveAllocator(CEL_NONNULL(_cel_GenericArray*) arr, - CEL_NONNULL(cel_Allocator*) alloc, - size_t new_cap, size_t ele_size) { - CEL_ASSERT_NOT_NULL(arr); - CEL_ASSERT_NOT_NULL(alloc); - CEL_ASSERT_GT(ele_size, 0); - CEL_ASSERT_LE(arr->len, arr->cap); - if (arr->cap >= new_cap) { - return true; - } - return _cel_GenericArray_ReallocateAllocator(arr, alloc, arr->len, new_cap, - ele_size); -} - -bool _cel_GenericArray_ReserveArena(CEL_NONNULL(_cel_GenericArray*) arr, - CEL_NONNULL(cel_Arena*) arena, - size_t new_cap, size_t ele_size) { - CEL_ASSERT_NOT_NULL(arr); - CEL_ASSERT_NOT_NULL(arena); - CEL_ASSERT_GT(ele_size, 0); - CEL_ASSERT_LE(arr->len, arr->cap); - if (arr->cap >= new_cap) { - return true; - } - size_t new_cap_bytes; - if (CEL_UNLIKELY(_cel_ckd_mul(&new_cap_bytes, new_cap, ele_size))) { - errno = ENOMEM; - return false; - } - CEL_NULLABLE(void*) - new_ptr = cel_Arena_Realloc(arena, arr->ptr, arr->cap * ele_size, - new_cap_bytes, cel_nullptr); - if (CEL_UNLIKELY(new_ptr == cel_nullptr)) { - return false; - } - arr->ptr = new_ptr; - arr->cap = new_cap; - return true; -} - -void _cel_GenericArray_ShrinkToFitAllocator(CEL_NONNULL(_cel_GenericArray*) arr, - CEL_NONNULL(cel_Allocator*) alloc, - size_t ele_size) { - CEL_ASSERT_NOT_NULL(arr); - CEL_ASSERT_NOT_NULL(alloc); - CEL_ASSERT_GT(ele_size, 0); - CEL_ASSERT_LE(arr->len, arr->cap); - if (arr->len == arr->cap) { - return; - } - if (arr->len == 0) { - _cel_GenericArray_ResetAllocator(arr, alloc, ele_size); - return; - } - CEL_USED(_cel_GenericArray_ReallocateAllocator(arr, alloc, arr->len, arr->len, - ele_size)); -} - -CEL_NULLABLE(void*) -_cel_GenericArray_ResizeAllocator(CEL_NONNULL(_cel_GenericArray*) arr, - CEL_NONNULL(cel_Allocator*) alloc, - size_t new_len, size_t ele_size) { - CEL_ASSERT_NOT_NULL(arr); - CEL_ASSERT_NOT_NULL(alloc); - CEL_ASSERT_GT(ele_size, 0); - CEL_ASSERT_LE(arr->len, arr->cap); - if (CEL_UNLIKELY(!_cel_GenericArray_ReserveAllocator(arr, alloc, new_len, - ele_size))) { - return cel_nullptr; - } - CEL_NULLABLE(void*) ptr; - if (new_len < arr->len) { - ptr = ((CEL_NONNULL(char*))arr->ptr) + (new_len * ele_size); - } else { - ptr = ((CEL_NONNULL(char*))arr->ptr) + (arr->len * ele_size); - } - _cel_GenericArray_Annotate(arr->ptr, arr->cap, arr->len, new_len, ele_size); - arr->len = new_len; - return ptr; -} - -CEL_NULLABLE(void*) -_cel_GenericArray_ResizeArena(CEL_NONNULL(_cel_GenericArray*) arr, - CEL_NONNULL(cel_Arena*) arena, size_t new_len, - size_t ele_size) { - CEL_ASSERT_NOT_NULL(arr); - CEL_ASSERT_NOT_NULL(arena); - CEL_ASSERT_GT(ele_size, 0); - CEL_ASSERT_LE(arr->len, arr->cap); - if (CEL_UNLIKELY(!_cel_GenericArray_ReserveArena(arr, arena, new_len, - ele_size))) { - return cel_nullptr; - } - CEL_NULLABLE(void*) ptr; - if (new_len < arr->len) { - ptr = ((CEL_NONNULL(char*))arr->ptr) + (new_len * ele_size); - } else { - ptr = ((CEL_NONNULL(char*))arr->ptr) + (arr->len * ele_size); - } - arr->len = new_len; - return ptr; -} - -CEL_NULLABLE(void*) -_cel_GenericArray_AppendAllocator(CEL_NONNULL(_cel_GenericArray*) arr, - CEL_NONNULL(cel_Allocator*) alloc, size_t n, - size_t ele_size) { - CEL_ASSERT_NOT_NULL(arr); - CEL_ASSERT_NOT_NULL(alloc); - CEL_ASSERT_GT(ele_size, 0); - CEL_ASSERT_LE(arr->len, arr->cap); - if (n == 0) { - return cel_nullptr; - } - if (CEL_UNLIKELY(n > arr->cap - arr->len)) { - size_t min_cap; - if (CEL_UNLIKELY(_cel_ckd_add(&min_cap, arr->len, n))) { - errno = ENOMEM; - return cel_nullptr; - } - size_t new_cap = arr->cap; - if (new_cap < 8) { - new_cap = 8; - } - while (new_cap < min_cap) { - if (CEL_UNLIKELY(_cel_ckd_mul(&new_cap, new_cap, (size_t)2))) { - new_cap = min_cap; - break; - } - }; - size_t old_len = arr->len; - if (CEL_UNLIKELY(!_cel_GenericArray_ReallocateAllocator( - arr, alloc, old_len + n, new_cap, ele_size))) { - return cel_nullptr; - } - // _cel_GenericArray_ReallocateAllocator has already done the len upate and - // annotation update. - CEL_NONNULL(void*) - ptr = ((CEL_NONNULL(char*))arr->ptr) + (old_len * ele_size); - return ptr; - } - size_t new_len = arr->len + n; - _cel_GenericArray_Annotate(arr->ptr, arr->cap, arr->len, new_len, ele_size); - CEL_NONNULL(void*) - ptr = ((CEL_NONNULL(char*))arr->ptr) + (arr->len * ele_size); - arr->len = new_len; - return ptr; -} - -CEL_NULLABLE(void*) -_cel_GenericArray_AppendArena(CEL_NONNULL(_cel_GenericArray*) arr, - CEL_NONNULL(cel_Arena*) arena, size_t n, - size_t ele_size) { - CEL_ASSERT_NOT_NULL(arr); - CEL_ASSERT_NOT_NULL(arena); - CEL_ASSERT_GT(ele_size, 0); - CEL_ASSERT_LE(arr->len, arr->cap); - if (n == 0) { - return cel_nullptr; - } - if (CEL_UNLIKELY(n > arr->cap - arr->len)) { - size_t min_cap; - if (CEL_UNLIKELY(_cel_ckd_add(&min_cap, arr->len, n))) { - errno = ENOMEM; - return cel_nullptr; - } - size_t new_cap = arr->cap; - if (new_cap < 8) { - new_cap = 8; - } - while (new_cap < min_cap) { - if (CEL_UNLIKELY(_cel_ckd_mul(&new_cap, new_cap, (size_t)2))) { - new_cap = min_cap; - break; - } - } - size_t new_cap_bytes; - if (CEL_UNLIKELY(_cel_ckd_mul(&new_cap_bytes, new_cap, ele_size))) { - if (CEL_UNLIKELY(new_cap == min_cap || - _cel_ckd_mul(&new_cap_bytes, min_cap, ele_size))) { - errno = ENOMEM; - return cel_nullptr; - } - new_cap = min_cap; - } - CEL_NULLABLE(void*) - ptr = cel_Arena_Realloc(arena, arr->ptr, arr->cap * ele_size, new_cap_bytes, - cel_nullptr); - if (CEL_UNLIKELY(ptr == cel_nullptr)) { - return cel_nullptr; - } - arr->ptr = ptr; - arr->cap = new_cap; - } - CEL_NONNULL(void*) - ptr = ((CEL_NONNULL(char*))arr->ptr) + (arr->len * ele_size); - arr->len += n; - return ptr; -} - -void _cel_GenericArray_PopAllocator(CEL_NONNULL(_cel_GenericArray*) arr, - size_t ele_size) { - CEL_ASSERT_NOT_NULL(arr); - CEL_ASSERT_GT(ele_size, 0); - CEL_ASSERT_NOT(_cel_GenericArray_Empty(arr)); - CEL_ASSERT_LE(arr->len, arr->cap); - size_t new_len = arr->len - 1; - _cel_GenericArray_Annotate(arr->ptr, arr->cap, arr->len, new_len, ele_size); - arr->len = new_len; -} - -void _cel_GenericArray_PopArena(CEL_NONNULL(_cel_GenericArray*) arr) { - CEL_ASSERT_NOT_NULL(arr); - CEL_ASSERT_NOT(_cel_GenericArray_Empty(arr)); - CEL_ASSERT_LE(arr->len, arr->cap); - --(arr->len); -} - -void _cel_GenericArray_EraseAllocator(CEL_NONNULL(_cel_GenericArray*) arr, - size_t idx, size_t ele_size) { - CEL_ASSERT_NOT_NULL(arr); - CEL_ASSERT_LT(idx, _cel_GenericArray_Size(arr)); - CEL_ASSERT_GT(ele_size, 0); - - CEL_NONNULL(char*) - ptr = ((CEL_NONNULL(char*))arr->ptr); - memmove(ptr + (idx * ele_size), ptr + ((idx + 1) * ele_size), - (arr->len - (idx + 1)) * ele_size); - _cel_GenericArray_PopAllocator(arr, ele_size); -} - -void _cel_GenericArray_EraseArena(CEL_NONNULL(_cel_GenericArray*) arr, - size_t idx, size_t ele_size) { - CEL_ASSERT_NOT_NULL(arr); - CEL_ASSERT_LT(idx, _cel_GenericArray_Size(arr)); - CEL_ASSERT_GT(ele_size, 0); - - CEL_NONNULL(char*) - ptr = ((CEL_NONNULL(char*))arr->ptr); - memmove(ptr + (idx * ele_size), ptr + ((idx + 1) * ele_size), - (arr->len - (idx + 1)) * ele_size); - _cel_GenericArray_PopArena(arr); -} - -void _cel_GenericArray_ClearAllocator(CEL_NONNULL(_cel_GenericArray*) arr, - size_t ele_size) { - CEL_ASSERT_NOT_NULL(arr); - CEL_ASSERT_LE(arr->len, arr->cap); - _cel_GenericArray_Annotate(arr->ptr, arr->cap, /*old_len=*/arr->len, - /*new_len=*/0, ele_size); - arr->len = 0; -} - -void _cel_GenericArray_ClearArena(CEL_NONNULL(_cel_GenericArray*) arr) { - CEL_ASSERT_NOT_NULL(arr); - CEL_ASSERT_LE(arr->len, arr->cap); - arr->len = 0; -} - -void _cel_GenericArray_ResetAllocator(CEL_NONNULL(_cel_GenericArray*) arr, - CEL_NONNULL(cel_Allocator*) alloc, - size_t ele_size) { - CEL_ASSERT_NOT_NULL(arr); - CEL_ASSERT_NOT_NULL(alloc); - CEL_ASSERT_GT(ele_size, 0); - CEL_ASSERT_LE(arr->len, arr->cap); - if (arr->cap > 0) { - _cel_GenericArray_Annotate(arr->ptr, arr->cap, /*old_len=*/arr->len, - /*new_len=*/arr->cap, ele_size); - cel_Allocator_FreeSized(alloc, arr->ptr, arr->cap * ele_size); - } - memset(arr, '\0', sizeof(*arr)); -} diff --git a/cel-c/src/generic_deque.c b/cel-c/src/generic_deque.c deleted file mode 100644 index 1344567..0000000 --- a/cel-c/src/generic_deque.c +++ /dev/null @@ -1,771 +0,0 @@ -// Copyright 2025 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "cel-c/src/generic_deque.h" - -#include -#include // IWYU pragma: keep -#include -#include - -#include "cel-c/alloc.h" -#include "cel-c/arena.h" -#include "cel-c/assert.h" -#include "cel-c/config.h" -#include "cel-c/src/align.h" -#include "cel-c/src/asan.h" - -typedef struct _cel_GenericDequeBlock _cel_GenericDequeBlock; - -struct _cel_GenericDequeBlock { - CEL_NULLABLE(struct _cel_GenericDequeBlock*) prev; - CEL_NULLABLE(struct _cel_GenericDequeBlock*) next; - size_t cap; -}; - -static void _cel_GenericDequeBlock_Size(size_t ele_size, - CEL_NONNULL(size_t*) block_size) { - *block_size = - ((ele_size < - ((4096 - _cel_align_up(sizeof(_cel_GenericDequeBlock), cel_kMaxAlign)) / - 16)) - ? (4096 - - _cel_align_up(sizeof(_cel_GenericDequeBlock), cel_kMaxAlign)) / - ele_size * ele_size - : (16 * ele_size)) + - _cel_align_up(sizeof(_cel_GenericDequeBlock), cel_kMaxAlign); -} - -static void _cel_GenericDequeBlock_Annotate(CEL_NONNULL(_cel_GenericDequeBlock*) - block, - size_t old_begin, size_t old_end, - size_t new_begin, size_t new_end, - size_t ele_size) { - const size_t size = block->cap * ele_size; - CEL_NONNULL(char*) addr = ((CEL_NONNULL(char*))block); - addr += _cel_align_up(sizeof(_cel_GenericDequeBlock), cel_kMaxAlign); - _cel_sanitizer_annotate_double_ended_contiguous_container( - addr, addr + size, addr + (old_begin * ele_size), - addr + (old_end * ele_size), addr + (new_begin * ele_size), - addr + (new_end * ele_size)); -} - -static void _cel_GenericDequeBlock_AnnotateNew( - CEL_NONNULL(_cel_GenericDequeBlock*) block, size_t ele_size) { - _cel_GenericDequeBlock_Annotate(block, /*old_begin=*/0, - /*old_end=*/block->cap, /*new_begin=*/0, - /*new_end=*/0, ele_size); -} - -static void _cel_GenericDequeBlock_AnnotateDelete( - CEL_NONNULL(_cel_GenericDequeBlock*) block, size_t ele_size) { - _cel_GenericDequeBlock_Annotate(block, /*old_begin=*/0, - /*old_end=*/0, /*new_begin=*/0, - /*new_end=*/block->cap, ele_size); -} - -static CEL_NULLABLE(_cel_GenericDequeBlock*) - _cel_GenericDequeBlock_NewAllocator(CEL_NONNULL(cel_Allocator*) alloc, - size_t ele_size) { - size_t block_size; - _cel_GenericDequeBlock_Size(ele_size, &block_size); - size_t actual_block_size; - CEL_NULLABLE(void*) - addr = cel_Allocator_Malloc(alloc, block_size, &actual_block_size); - if (CEL_UNLIKELY(addr == cel_nullptr)) { - return cel_nullptr; - } - const size_t cap = - (actual_block_size - - _cel_align_up(sizeof(_cel_GenericDequeBlock), cel_kMaxAlign)) / - ele_size; - CEL_NONNULL(_cel_GenericDequeBlock*) block; - block = addr; - block->prev = block->next = cel_nullptr; - block->cap = cap; - return block; -} - -static void _cel_GenericDequeBlock_DeleteAllocator( - CEL_NONNULL(_cel_GenericDequeBlock*) block, - CEL_NONNULL(cel_Allocator*) alloc, size_t ele_size) { - const size_t size = block->cap * ele_size; - CEL_NONNULL(void*) addr; - addr = block; - cel_Allocator_FreeSized( - alloc, addr, - size + _cel_align_up(sizeof(_cel_GenericDequeBlock), cel_kMaxAlign)); -} - -static CEL_NULLABLE(_cel_GenericDequeBlock*) - _cel_GenericDequeBlock_NewArena(CEL_NONNULL(cel_Arena*) arena, - size_t ele_size) { - size_t block_size; - _cel_GenericDequeBlock_Size(ele_size, &block_size); - CEL_NULLABLE(void*) - addr = cel_Arena_Malloc(arena, block_size, cel_nullptr); - if (CEL_UNLIKELY(addr == cel_nullptr)) { - return cel_nullptr; - } - const size_t cap = (block_size - _cel_align_up(sizeof(_cel_GenericDequeBlock), - cel_kMaxAlign)) / - ele_size; - CEL_NONNULL(_cel_GenericDequeBlock*) block; - block = addr; - block->prev = block->next = cel_nullptr; - block->cap = cap; - return block; -} - -static CEL_NONNULL(const char*) - _cel_GenericDequeBlock_At(CEL_NONNULL(const _cel_GenericDequeBlock*) block, - size_t index, size_t ele_size) { - return ((CEL_NONNULL(const char*))block) + - _cel_align_up(sizeof(_cel_GenericDequeBlock), cel_kMaxAlign) + - (index * ele_size); -} - -static CEL_NONNULL(char*) - _cel_GenericDequeBlock_MutableAt(CEL_NONNULL(_cel_GenericDequeBlock*) block, - size_t index, size_t ele_size) { - return (CEL_NONNULL(char*))_cel_GenericDequeBlock_At(block, index, ele_size); -} - -static CEL_NONNULL(_cel_GenericDequeBlock*) - _cel_GenericDequeBlock_LinkBefore(CEL_NONNULL(_cel_GenericDequeBlock*) - new_block, - CEL_NULLABLE(_cel_GenericDequeBlock*) - before_block) { - CEL_NULLABLE(_cel_GenericDequeBlock*) prev; - if (before_block != cel_nullptr) { - prev = before_block->prev; - } else { - prev = cel_nullptr; - } - if (prev != cel_nullptr) { - prev->next = new_block; - } - new_block->prev = prev; - new_block->next = before_block; - if (before_block != cel_nullptr) { - before_block->prev = new_block; - } - return new_block; -} - -static CEL_NONNULL(_cel_GenericDequeBlock*) - _cel_GenericDequeBlock_LinkAfter(CEL_NONNULL(_cel_GenericDequeBlock*) - new_block, - CEL_NONNULL(_cel_GenericDequeBlock*) - after_block) { - CEL_NULLABLE(_cel_GenericDequeBlock*) next; - if (after_block != cel_nullptr) { - next = after_block->next; - } else { - next = cel_nullptr; - } - if (next != cel_nullptr) { - next->prev = new_block; - } - new_block->prev = after_block; - new_block->next = next; - if (after_block != cel_nullptr) { - after_block->next = new_block; - } - return new_block; -} - -static void _cel_GenericDequeBlock_Unlink(CEL_NONNULL(_cel_GenericDequeBlock*) - block) { - CEL_NULLABLE(_cel_GenericDequeBlock*) prev = block->prev; - CEL_NULLABLE(_cel_GenericDequeBlock*) next = block->next; - if (prev != cel_nullptr) { - prev->next = next; - block->prev = cel_nullptr; - } - if (next != cel_nullptr) { - next->prev = prev; - block->next = cel_nullptr; - } -} - -static void _cel_GenericDequeBlock_DeleteChainAllocator( - CEL_NULLABLE(_cel_GenericDequeBlock*) block, - CEL_NONNULL(cel_Allocator*) alloc, size_t ele_size) { - while (block != cel_nullptr) { - CEL_NULLABLE(_cel_GenericDequeBlock*) next = block->next; - _cel_GenericDequeBlock_DeleteAllocator(block, alloc, ele_size); - block = next; - } -} - -static bool _cel_GenericDeque_NewBlockAllocator( - CEL_NONNULL(_cel_GenericDeque*) deq, int which, - CEL_NONNULL(cel_Allocator*) alloc, size_t ele_size) { - CEL_ASSERT(which == -1 || which == 0 || which == 1); - - // First insertion. There may be a single block we can use at deq->cache, - // otherwise we need to allocate one. - - CEL_NULLABLE(_cel_GenericDequeBlock*) - new_block = deq->cache; - if (new_block != cel_nullptr) { - // allocator-based deque should only cache a single block. - CEL_ASSERT_NULL(new_block->prev); - CEL_ASSERT_NULL(new_block->next); - deq->cache = cel_nullptr; - // No need to update ASan annotation. Blocks in the cache are already - // poisoned fully. - } else { - new_block = _cel_GenericDequeBlock_NewAllocator(alloc, ele_size); - if (CEL_UNLIKELY(new_block == cel_nullptr)) { - return false; - } - _cel_GenericDequeBlock_AnnotateNew(new_block, ele_size); - } - CEL_ASSUME(which == -1 || which == 0 || which == 1); - switch (which) { - case -1: - deq->head = _cel_GenericDequeBlock_LinkBefore(new_block, deq->head); - deq->head_pos = new_block->cap; - break; - case 0: - deq->head = deq->tail = new_block; - deq->tail_pos = deq->head_pos = new_block->cap / 2; - break; - case 1: - deq->tail = _cel_GenericDequeBlock_LinkAfter(new_block, deq->tail); - deq->tail_pos = 0; - break; - default: - CEL_UNREACHABLE(); - } - return true; -} - -static bool _cel_GenericDeque_NewHeadBlockAllocator( - CEL_NONNULL(_cel_GenericDeque*) deq, CEL_NONNULL(cel_Allocator*) alloc, - size_t ele_size) { - CEL_ASSERT_EQ(deq->head_pos, 0); - - return _cel_GenericDeque_NewBlockAllocator( - deq, deq->head != cel_nullptr ? -1 : 0, alloc, ele_size); -} - -static bool _cel_GenericDeque_NewTailBlockAllocator( - CEL_NONNULL(_cel_GenericDeque*) deq, CEL_NONNULL(cel_Allocator*) alloc, - size_t ele_size) { - CEL_ASSERT(deq->tail == cel_nullptr || - deq->tail_pos == - ((CEL_NONNULL(_cel_GenericDequeBlock*))deq->tail)->cap); - - return _cel_GenericDeque_NewBlockAllocator( - deq, deq->tail != cel_nullptr ? 1 : 0, alloc, ele_size); -} - -static bool _cel_GenericDeque_NewBlockArena(CEL_NONNULL(_cel_GenericDeque*) deq, - int which, - CEL_NONNULL(cel_Arena*) arena, - size_t ele_size) { - CEL_ASSERT(which == -1 || which == 0 || which == 1); - - // First insertion. There may be a single block we can use at deq->cache, - // otherwise we need to allocate one. - - CEL_NULLABLE(_cel_GenericDequeBlock*) - new_block = deq->cache; - if (new_block != cel_nullptr) { - // allocator-based deque should only cache a single block. - deq->cache = new_block->next; - _cel_GenericDequeBlock_Unlink(new_block); - } else { - new_block = _cel_GenericDequeBlock_NewArena(arena, ele_size); - if (CEL_UNLIKELY(new_block == cel_nullptr)) { - return false; - } - } - CEL_ASSUME(which == -1 || which == 0 || which == 1); - switch (which) { - case -1: - deq->head = _cel_GenericDequeBlock_LinkBefore(new_block, deq->head); - deq->head_pos = new_block->cap; - break; - case 0: - deq->head = deq->tail = new_block; - deq->tail_pos = deq->head_pos = new_block->cap / 2; - break; - case 1: - deq->tail = _cel_GenericDequeBlock_LinkAfter(new_block, deq->tail); - deq->tail_pos = 0; - break; - default: - CEL_UNREACHABLE(); - } - return true; -} - -static bool _cel_GenericDeque_NewHeadBlockArena(CEL_NONNULL(_cel_GenericDeque*) - deq, - CEL_NONNULL(cel_Arena*) arena, - size_t ele_size) { - CEL_ASSERT_EQ(deq->head_pos, 0); - - return _cel_GenericDeque_NewBlockArena(deq, deq->head != cel_nullptr ? -1 : 0, - arena, ele_size); -} - -static bool _cel_GenericDeque_NewTailBlockArena(CEL_NONNULL(_cel_GenericDeque*) - deq, - CEL_NONNULL(cel_Arena*) arena, - size_t ele_size) { - CEL_ASSERT(deq->tail == cel_nullptr || - deq->tail_pos == - ((CEL_NONNULL(_cel_GenericDequeBlock*))deq->tail)->cap); - - return _cel_GenericDeque_NewBlockArena(deq, deq->tail != cel_nullptr ? 1 : 0, - arena, ele_size); -} - -void _cel_GenericDeque_Construct(CEL_NONNULL(_cel_GenericDeque*) deq) { - CEL_ASSERT_NOT_NULL(deq); - - memset(deq, '\0', sizeof(*deq)); -} - -void _cel_GenericDeque_DestructAllocator(CEL_NONNULL(_cel_GenericDeque*) deq, - CEL_NONNULL(cel_Allocator*) alloc, - size_t ele_size) { - CEL_ASSERT_NOT_NULL(deq); - CEL_ASSERT_NOT_NULL(alloc); - CEL_ASSERT_GT(ele_size, 0); - - _cel_GenericDequeBlock_DeleteChainAllocator(deq->head, alloc, ele_size); - _cel_GenericDequeBlock_DeleteChainAllocator(deq->cache, alloc, ele_size); -} - -CEL_NULLABLE(const void*) -_cel_GenericDeque_At(CEL_NONNULL(const _cel_GenericDeque*) deq, size_t idx, - size_t ele_size) { - CEL_ASSERT_NOT_NULL(deq); - CEL_ASSERT_LT(idx, _cel_GenericDeque_Size(deq)); - CEL_ASSERT_GT(ele_size, 0); - - // We scan forward is idx < half the size, backwards otherwise. - if (idx >= deq->len / 2) { - // Backward. - _cel_GenericDequeBlock* block = deq->tail; - if (block == deq->head) { - // Only one block, the element should be relative to head_pos. - return _cel_GenericDequeBlock_At(block, deq->head_pos + idx, ele_size); - } - size_t npos = deq->len - deq->tail_pos; - if (npos <= idx) { - return _cel_GenericDequeBlock_At(block, idx - npos, ele_size); - } - block = block->prev; - while (block != deq->head && npos - block->cap > idx) { - npos -= block->cap; - block = block->prev; - } - if (block == deq->head) { - // Only one block, the element should be relative to head_pos. - return _cel_GenericDequeBlock_At(block, deq->head_pos + idx, ele_size); - } - return _cel_GenericDequeBlock_At(block, idx - npos, ele_size); - } - - // Forward. - _cel_GenericDequeBlock* block = deq->head; - size_t block_size; - if (block == deq->tail || (block_size = (block->cap - deq->head_pos)) > idx) { - // Only one block or the element is in the head block, the element should be - // here relative to head_pos. - return _cel_GenericDequeBlock_At(block, deq->head_pos + idx, ele_size); - } - idx -= block_size; - block = block->next; - while (block != deq->tail && (block_size = block->cap) >= idx) { - idx -= block_size; - block = block->next; - } - // Must be in this block which is not head (could be in the middle or tail). - // So we always look relative to 0. deq->tail_pos is the upper bound, - // everything before it is occupied. - return _cel_GenericDequeBlock_At(block, idx, ele_size); -} - -CEL_NULLABLE(void*) -_cel_GenericDeque_PushFrontAllocator(CEL_NONNULL(_cel_GenericDeque*) deq, - CEL_NONNULL(cel_Allocator*) alloc, - size_t ele_size) { - CEL_ASSERT_NOT_NULL(deq); - CEL_ASSERT_NOT_NULL(alloc); - CEL_ASSERT_GT(ele_size, 0); - - CEL_NULLABLE(_cel_GenericDequeBlock*) head = deq->head; - if (CEL_UNLIKELY( - head == cel_nullptr || - (deq->head_pos == 0 && (head != deq->tail || deq->tail_pos != 0)))) { - if (!_cel_GenericDeque_NewHeadBlockAllocator(deq, alloc, ele_size)) { - return cel_nullptr; - } - head = deq->head; - } else if (head == deq->tail && deq->head_pos == deq->tail_pos) { - deq->head_pos = deq->tail_pos = head->cap / 2; - } - - CEL_ASSERT_NOT_NULL(head); - CEL_ASSERT_GT(deq->head_pos, 0); - - CEL_NONNULL(void*) - ele = _cel_GenericDequeBlock_MutableAt(head, deq->head_pos - 1, ele_size); - // Before updating fields and returning to the caller, update the ASan - // annotation to unpoison the storage for the newly appended element. Keep in - // mind that deq->tail may be the same as deq->head. - _cel_GenericDequeBlock_Annotate( - head, /*old_begin=*/deq->head_pos, - /*old_end=*/head != deq->tail - ? ((CEL_NONNULL(_cel_GenericDequeBlock*))deq->tail)->cap - : deq->tail_pos, - /*new_begin=*/deq->head_pos - 1, - /*new_end=*/head != deq->tail - ? ((CEL_NONNULL(_cel_GenericDequeBlock*))deq->tail)->cap - : deq->tail_pos, - ele_size); - --(deq->head_pos); - ++(deq->len); - return ele; -} - -CEL_NULLABLE(void*) -_cel_GenericDeque_PushFrontArena(CEL_NONNULL(_cel_GenericDeque*) deq, - CEL_NONNULL(cel_Arena*) arena, - size_t ele_size) { - CEL_ASSERT_NOT_NULL(deq); - CEL_ASSERT_NOT_NULL(arena); - CEL_ASSERT_GT(ele_size, 0); - - CEL_NULLABLE(_cel_GenericDequeBlock*) head = deq->head; - if (CEL_UNLIKELY( - head == cel_nullptr || - (deq->head_pos == 0 && (head != deq->tail || deq->tail_pos != 0)))) { - if (!_cel_GenericDeque_NewHeadBlockArena(deq, arena, ele_size)) { - return cel_nullptr; - } - head = deq->head; - } else if (head == deq->tail && deq->head_pos == deq->tail_pos) { - deq->head_pos = deq->tail_pos = head->cap / 2; - } - - CEL_ASSERT_NOT_NULL(head); - CEL_ASSERT_GT(deq->head_pos, 0); - - CEL_NONNULL(void*) - ele = _cel_GenericDequeBlock_MutableAt(head, deq->head_pos - 1, ele_size); - --(deq->head_pos); - ++(deq->len); - return ele; -} - -void _cel_GenericDeque_PopFrontAllocator(CEL_NONNULL(_cel_GenericDeque*) deq, - CEL_NONNULL(cel_Allocator*) alloc, - size_t ele_size) { - CEL_ASSERT_NOT_NULL(deq); - CEL_ASSERT_NOT(_cel_GenericDeque_Empty(deq)); - CEL_ASSERT_GT(ele_size, 0); - CEL_ASSERT_NOT_NULL(deq->tail); - - // Before updating fields, update the ASan annotation. Keep in - // mind that deq->tail may be the same as deq->head. - _cel_GenericDequeBlock_Annotate( - deq->head, /*old_begin=*/deq->head_pos, - /*old_end=*/deq->head != deq->tail ? deq->head->cap : deq->tail_pos, - /*new_begin=*/deq->head_pos + 1, - /*new_end=*/deq->head != deq->tail ? deq->head->cap : deq->tail_pos, - ele_size); - - ++(deq->head_pos); - --(deq->len); - if (deq->head != deq->tail && deq->head_pos == deq->head->cap) { - CEL_NONNULL(_cel_GenericDequeBlock*) old_head = deq->head; - CEL_NONNULL(_cel_GenericDequeBlock*) new_head = old_head->next; - deq->head = new_head; - deq->head_pos = 0; - _cel_GenericDequeBlock_Unlink(old_head); - if (deq->cache == cel_nullptr) { - deq->cache = old_head; - } else { - // Block already cached. Delete this one. - _cel_GenericDequeBlock_DeleteAllocator(old_head, alloc, ele_size); - } - } - if (deq->head == deq->tail && deq->head_pos == deq->tail_pos) { - if (deq->cache != cel_nullptr) { - _cel_GenericDequeBlock_AnnotateDelete(deq->cache, ele_size); - _cel_GenericDequeBlock_DeleteAllocator(deq->cache, alloc, ele_size); - deq->cache = cel_nullptr; - } - deq->head_pos = deq->tail_pos = deq->head->cap / 2; - } -} - -void _cel_GenericDeque_PopFrontArena(CEL_NONNULL(_cel_GenericDeque*) deq) { - CEL_ASSERT_NOT_NULL(deq); - CEL_ASSERT_NOT(_cel_GenericDeque_Empty(deq)); - CEL_ASSERT_NOT_NULL(deq->head); - - ++(deq->head_pos); - --(deq->len); - if (deq->head != deq->tail && deq->head_pos == deq->head->cap) { - CEL_NONNULL(_cel_GenericDequeBlock*) old_head = deq->head; - CEL_NONNULL(_cel_GenericDequeBlock*) new_head = old_head->next; - deq->head = new_head; - deq->head_pos = 0; - _cel_GenericDequeBlock_Unlink(old_head); - _cel_GenericDequeBlock_LinkBefore(old_head, deq->cache); - deq->cache = old_head; - } - if (deq->head == deq->tail && deq->head_pos == deq->tail_pos) { - deq->head_pos = deq->tail_pos = deq->head->cap / 2; - } -} - -CEL_NONNULL(const void*) -_cel_GenericDeque_PeekFront(CEL_NONNULL(const _cel_GenericDeque*) deq, - size_t ele_size) { - CEL_ASSERT_NOT_NULL(deq); - CEL_ASSERT_NOT(_cel_GenericDeque_Empty(deq)); - CEL_ASSERT_GT(ele_size, 0); - - CEL_ASSERT_NOT_NULL(deq->head); - CEL_ASSERT_GE(deq->head_pos, 0); - CEL_ASSERT_LT(deq->head_pos, deq->head->cap); - - return _cel_GenericDequeBlock_At(deq->head, deq->head_pos, ele_size); -} - -CEL_NULLABLE(void*) -_cel_GenericDeque_PushBackAllocator(CEL_NONNULL(_cel_GenericDeque*) deq, - CEL_NONNULL(cel_Allocator*) alloc, - size_t ele_size) { - CEL_ASSERT_NOT_NULL(deq); - CEL_ASSERT_NOT_NULL(alloc); - CEL_ASSERT_GT(ele_size, 0); - - CEL_NULLABLE(_cel_GenericDequeBlock*) tail = deq->tail; - if (CEL_UNLIKELY(tail == cel_nullptr || - (deq->tail_pos == tail->cap && - (tail != deq->head || deq->head_pos != deq->tail_pos)))) { - if (!_cel_GenericDeque_NewTailBlockAllocator(deq, alloc, ele_size)) { - return cel_nullptr; - } - tail = deq->tail; - } else if (tail == deq->head && deq->tail_pos == deq->head_pos) { - deq->head_pos = deq->tail_pos = tail->cap / 2; - } - - CEL_ASSERT_NOT_NULL(tail); - CEL_ASSERT_LT(deq->tail_pos, tail->cap); - - CEL_NONNULL(void*) - ele = _cel_GenericDequeBlock_MutableAt(tail, deq->tail_pos, ele_size); - // Before updating fields and returning to the caller, update the ASan - // annotation to unpoison the storage for the newly appended element. Keep in - // mind that deq->tail may be the same as deq->head. - _cel_GenericDequeBlock_Annotate( - tail, /*old_begin=*/tail != deq->head ? 0 : deq->head_pos, - /*old_end=*/deq->tail_pos, - /*new_begin=*/tail != deq->head ? 0 : deq->head_pos, - /*new_end=*/deq->tail_pos + 1, ele_size); - ++(deq->tail_pos); - ++(deq->len); - return ele; -} - -CEL_NULLABLE(void*) -_cel_GenericDeque_PushBackArena(CEL_NONNULL(_cel_GenericDeque*) deq, - CEL_NONNULL(cel_Arena*) arena, - size_t ele_size) { - CEL_ASSERT_NOT_NULL(deq); - CEL_ASSERT_NOT_NULL(arena); - CEL_ASSERT_GT(ele_size, 0); - - CEL_NULLABLE(_cel_GenericDequeBlock*) tail = deq->tail; - if (CEL_UNLIKELY(tail == cel_nullptr || - (deq->tail_pos == tail->cap && - (tail != deq->head || deq->head_pos != deq->tail_pos)))) { - if (!_cel_GenericDeque_NewTailBlockArena(deq, arena, ele_size)) { - return cel_nullptr; - } - tail = deq->tail; - } else if (tail == deq->head && deq->tail_pos == deq->head_pos) { - deq->head_pos = deq->tail_pos = tail->cap / 2; - } - - CEL_ASSERT_NOT_NULL(tail); - CEL_ASSERT_LT(deq->tail_pos, tail->cap); - - CEL_NONNULL(void*) - ele = _cel_GenericDequeBlock_MutableAt(tail, deq->tail_pos, ele_size); - ++(deq->tail_pos); - ++(deq->len); - return ele; -} - -void _cel_GenericDeque_PopBackAllocator(CEL_NONNULL(_cel_GenericDeque*) deq, - CEL_NONNULL(cel_Allocator*) alloc, - size_t ele_size) { - CEL_ASSERT_NOT_NULL(deq); - CEL_ASSERT_NOT(_cel_GenericDeque_Empty(deq)); - CEL_ASSERT_GT(ele_size, 0); - CEL_ASSERT_NOT_NULL(deq->tail); - - // Before updating fields, update the ASan annotation. Keep in - // mind that deq->tail may be the same as deq->head. - _cel_GenericDequeBlock_Annotate( - deq->tail, /*old_begin=*/deq->tail != deq->head ? 0 : deq->head_pos, - /*old_end=*/deq->tail_pos, - /*new_begin=*/deq->tail != deq->head ? 0 : deq->head_pos, - /*new_end=*/deq->tail_pos - 1, ele_size); - - --(deq->tail_pos); - --(deq->len); - if (deq->tail_pos == 0 && deq->head != deq->tail) { - CEL_NONNULL(_cel_GenericDequeBlock*) old_tail = deq->tail; - CEL_NONNULL(_cel_GenericDequeBlock*) new_tail = old_tail->prev; - deq->tail = new_tail; - deq->tail_pos = new_tail->cap; - _cel_GenericDequeBlock_Unlink(old_tail); - if (deq->cache == cel_nullptr) { - deq->cache = old_tail; - } else { - // Block already cached. Delete this one. - _cel_GenericDequeBlock_DeleteAllocator(old_tail, alloc, ele_size); - } - } - if (deq->head == deq->tail && deq->head_pos == deq->tail_pos) { - if (deq->cache != cel_nullptr) { - _cel_GenericDequeBlock_AnnotateDelete(deq->cache, ele_size); - _cel_GenericDequeBlock_DeleteAllocator(deq->cache, alloc, ele_size); - deq->cache = cel_nullptr; - } - deq->head_pos = deq->tail_pos = deq->head->cap / 2; - } -} - -void _cel_GenericDeque_PopBackArena(CEL_NONNULL(_cel_GenericDeque*) deq) { - CEL_ASSERT_NOT_NULL(deq); - CEL_ASSERT_NOT(_cel_GenericDeque_Empty(deq)); - CEL_ASSERT_NOT_NULL(deq->tail); - - --(deq->tail_pos); - --(deq->len); - if (deq->tail_pos == 0 && deq->head != deq->tail) { - CEL_NONNULL(_cel_GenericDequeBlock*) old_tail = deq->tail; - CEL_NONNULL(_cel_GenericDequeBlock*) new_tail = old_tail->prev; - deq->tail = new_tail; - deq->tail_pos = new_tail->cap; - _cel_GenericDequeBlock_Unlink(old_tail); - _cel_GenericDequeBlock_LinkBefore(old_tail, deq->cache); - deq->cache = old_tail; - } - if (deq->head == deq->tail && deq->head_pos == deq->tail_pos) { - deq->head_pos = deq->tail_pos = deq->head->cap / 2; - } -} - -CEL_NONNULL(const void*) -_cel_GenericDeque_PeekBack(CEL_NONNULL(const _cel_GenericDeque*) deq, - size_t ele_size) { - CEL_ASSERT_NOT_NULL(deq); - CEL_ASSERT_NOT(_cel_GenericDeque_Empty(deq)); - CEL_ASSERT_GT(ele_size, 0); - - CEL_ASSERT_NOT_NULL(deq->tail); - CEL_ASSERT_GT(deq->tail_pos, 0); - CEL_ASSERT_LE(deq->tail_pos, deq->tail->cap); - - return _cel_GenericDequeBlock_At(deq->tail, deq->tail_pos - 1, ele_size); -} - -void _cel_GenericDeque_ResetAllocator(CEL_NONNULL(_cel_GenericDeque*) deq, - CEL_NONNULL(cel_Allocator*) alloc, - size_t ele_size) { - _cel_GenericDeque_DestructAllocator(deq, alloc, ele_size); - _cel_GenericDeque_Construct(deq); -} - -void _cel_GenericDeque_ClearAllocator(CEL_NONNULL(_cel_GenericDeque*) deq, - CEL_NONNULL(cel_Allocator*) alloc, - size_t ele_size) { - CEL_ASSERT_NOT_NULL(deq); - CEL_ASSERT_NOT_NULL(alloc); - CEL_ASSERT_GT(ele_size, 0); - - if (deq->len == 0) { - return; - } - deq->len = 0; - - CEL_NULLABLE(_cel_GenericDequeBlock*) head = deq->head; - if (head != cel_nullptr) { - CEL_ASSERT_NOT_NULL(deq->tail); - - // Add a block to the cache, if necessary. For malloc-based deque, we only - // cache a single block. - if (deq->cache == cel_nullptr) { - CEL_NULLABLE(_cel_GenericDequeBlock*) new_head = head->next; - _cel_GenericDequeBlock_Unlink(head); - if (head == deq->tail) { - deq->tail = new_head; - } - deq->head = new_head; - deq->cache = head; - head = new_head; - } - - // Delete the rest of the blocks. - _cel_GenericDequeBlock_DeleteChainAllocator(head, alloc, ele_size); - deq->head = deq->tail = cel_nullptr; - deq->head_pos = deq->tail_pos = 0; - } else { - CEL_ASSERT_NULL(deq->tail); - CEL_ASSERT_EQ(deq->head_pos, 0); - CEL_ASSERT_EQ(deq->tail_pos, 0); - } -} - -void _cel_GenericDeque_ClearArena(CEL_NONNULL(_cel_GenericDeque*) deq) { - // For arena-based dequeue, we do not return memory to the arena as there is - // currently no way to do that. So we move all the allocated blocks to the - // cache list for re-use. - - CEL_ASSERT_NOT_NULL(deq); - - if (deq->len == 0) { - return; - } - deq->len = 0; - - if (deq->head != cel_nullptr) { - CEL_ASSERT_NOT_NULL(deq->tail); - deq->cache = _cel_GenericDequeBlock_LinkBefore(deq->head, deq->cache); - deq->head = deq->tail = cel_nullptr; - deq->head_pos = deq->tail_pos = 0; - } else { - CEL_ASSERT_NULL(deq->tail); - CEL_ASSERT_EQ(deq->head_pos, 0); - CEL_ASSERT_EQ(deq->tail_pos, 0); - } -} diff --git a/cel-c/src/generic_flat_hash.c b/cel-c/src/generic_flat_hash.c deleted file mode 100644 index 2a904ad..0000000 --- a/cel-c/src/generic_flat_hash.c +++ /dev/null @@ -1,505 +0,0 @@ -// Copyright 2025 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "cel-c/src/generic_flat_hash.h" - -#include -#include // IWYU pragma: keep -#include // IWYU pragma: keep -#include -#include -#include - -#include "cel-c/alloc.h" -#include "cel-c/arena.h" -#include "cel-c/assert.h" -#include "cel-c/config.h" -#include "cel-c/src/align.h" -#include "cel-c/src/bit.h" -#include "cel-c/src/bitset.h" - -CEL_ATTRIBUTE_NODISCARD -static size_t _cel_GenericFlatHash_Rehash( - CEL_NONNULL(const _cel_GenericFlatHash *) fh, - CEL_NONNULL(_cel_BitSetWord *) new_ctrl, CEL_NONNULL(char *) new_ents, - size_t old_slot, size_t new_cap, size_t ent_size) { - size_t new_slot = SIZE_MAX; - if (fh->len != 0) { - CEL_ASSERT_GT(new_cap, fh->cap); - - const size_t new_mask = new_cap - 1; - CEL_NONNULL(const _cel_BitSetWord *) const old_ctrl = fh->ctrl; - const size_t old_cap = fh->cap; - CEL_NONNULL(const char *) - const old_ents = fh->ents; - size_t bit = _cel_BitSet_kBegin; - while (_cel_BitSet_Next(old_ctrl, old_cap, &bit)) { - CEL_NONNULL(const char *) old_ent = old_ents + (ent_size * bit); - size_t slot = ((*fh->h)(old_ent)) & new_mask; - while (_cel_BitSet_Test(new_ctrl, new_cap, slot)) { - slot = (slot + 1) & new_mask; - } - _cel_BitSet_Set(new_ctrl, new_cap, slot); - CEL_NONNULL(char *) new_ent = new_ents + (slot * ent_size); - memcpy(new_ent, old_ent, ent_size); - if (bit == old_slot) { - new_slot = slot; - } - } - } - CEL_ASSERT(old_slot == SIZE_MAX || new_slot != SIZE_MAX); - return new_slot; -} - -CEL_ATTRIBUTE_NODISCARD -static bool _cel_GenericFlatHash_PreInsertAllocator( - CEL_NONNULL(_cel_GenericFlatHash *) fh, CEL_NONNULL(cel_Allocator *) alloc, - size_t ent_size) { - CEL_ASSERT_EQ(fh->cap, 0); - - size_t size = - _cel_align_up(_cel_BitSet_WordsForBits(16) * sizeof(_cel_BitSetWord), - cel_kMaxAlign) + - (ent_size * 16); - CEL_NULLABLE(char *) - data = cel_Allocator_Malloc(alloc, size, cel_nullptr); - if (CEL_UNLIKELY(data == cel_nullptr)) { - return false; - } - CEL_NONNULL(_cel_BitSetWord *) ctrl = (CEL_NONNULL(_cel_BitSetWord *))data; - CEL_NONNULL(char *) - ents = data + - _cel_align_up(_cel_BitSet_WordsForBits(16) * sizeof(_cel_BitSetWord), - cel_kMaxAlign); - _cel_BitSet_Reset(ctrl, 16); - fh->ctrl = ctrl; - fh->ents = ents; - fh->cap = 16; - fh->thr = 10; - return true; -} - -CEL_ATTRIBUTE_NODISCARD -static bool _cel_GenericFlatHash_GrowAllocator( - CEL_NONNULL(_cel_GenericFlatHash *) fh, CEL_NONNULL(cel_Allocator *) alloc, - size_t new_cap, CEL_NONNULL(size_t *) slot, size_t ent_size) { - CEL_ASSERT(_cel_has_single_bit(new_cap)); - CEL_ASSERT_GT(new_cap, fh->cap); - - size_t size = - _cel_align_up(_cel_BitSet_WordsForBits(new_cap) * sizeof(_cel_BitSetWord), - cel_kMaxAlign) + - (ent_size * new_cap); - CEL_NULLABLE(char *) - data = cel_Allocator_Malloc(alloc, size, cel_nullptr); - if (CEL_UNLIKELY(data == cel_nullptr)) { - return false; - } - CEL_NONNULL(_cel_BitSetWord *) ctrl = (CEL_NONNULL(_cel_BitSetWord *))data; - CEL_NONNULL(char *) - ents = data + _cel_align_up( - _cel_BitSet_WordsForBits(new_cap) * sizeof(_cel_BitSetWord), - cel_kMaxAlign); - _cel_BitSet_Reset(ctrl, new_cap); - - *slot = _cel_GenericFlatHash_Rehash(fh, ctrl, ents, *slot, new_cap, ent_size); - - size_t old_size = - _cel_align_up(_cel_BitSet_WordsForBits(fh->cap) * sizeof(_cel_BitSetWord), - cel_kMaxAlign) + - (fh->cap * ent_size); - CEL_NONNULL(void *) old_data = fh->ctrl; - cel_Allocator_FreeSized(alloc, old_data, old_size); - - fh->ctrl = ctrl; - fh->ents = ents; - fh->cap = new_cap; - fh->thr = (new_cap * 2) / 3; - return true; -} - -CEL_ATTRIBUTE_NODISCARD -static bool _cel_GenericFlatHash_PostInsertAllocator( - CEL_NONNULL(_cel_GenericFlatHash *) fh, CEL_NONNULL(cel_Allocator *) alloc, - CEL_NONNULL(size_t *) slot, size_t ent_size) { - CEL_ASSERT_GT(fh->len, fh->thr); - - return _cel_GenericFlatHash_GrowAllocator(fh, alloc, fh->cap << 1, slot, - ent_size); -} - -CEL_ATTRIBUTE_NODISCARD -static bool _cel_GenericFlatHash_PreInsertArena( - CEL_NONNULL(_cel_GenericFlatHash *) fh, CEL_NONNULL(cel_Arena *) arena, - size_t ent_size) { - CEL_ASSERT_EQ(fh->cap, 0); - - size_t size = - _cel_align_up(_cel_BitSet_WordsForBits(16) * sizeof(_cel_BitSetWord), - cel_kMaxAlign) + - (ent_size * 16); - CEL_NULLABLE(char *) - data = cel_Arena_Malloc(arena, size, cel_nullptr); - if (CEL_UNLIKELY(data == cel_nullptr)) { - return false; - } - CEL_NONNULL(_cel_BitSetWord *) ctrl = (CEL_NONNULL(_cel_BitSetWord *))data; - CEL_NONNULL(char *) - ents = data + - _cel_align_up(_cel_BitSet_WordsForBits(16) * sizeof(_cel_BitSetWord), - cel_kMaxAlign); - _cel_BitSet_Reset(ctrl, 16); - fh->ctrl = ctrl; - fh->ents = ents; - fh->cap = 16; - fh->thr = 10; - return true; -} - -CEL_ATTRIBUTE_NODISCARD -static bool _cel_GenericFlatHash_GrowArena( - CEL_NONNULL(_cel_GenericFlatHash *) fh, CEL_NONNULL(cel_Arena *) arena, - size_t new_cap, CEL_NONNULL(size_t *) slot, size_t ent_size) { - CEL_ASSERT(_cel_has_single_bit(new_cap)); - CEL_ASSERT_GT(new_cap, fh->cap); - - size_t size = - _cel_align_up(_cel_BitSet_WordsForBits(new_cap) * sizeof(_cel_BitSetWord), - cel_kMaxAlign) + - (ent_size * new_cap); - CEL_NULLABLE(char *) - data = cel_Arena_Malloc(arena, size, cel_nullptr); - if (CEL_UNLIKELY(data == cel_nullptr)) { - return false; - } - CEL_NONNULL(_cel_BitSetWord *) ctrl = (CEL_NONNULL(_cel_BitSetWord *))data; - CEL_NONNULL(char *) - ents = data + _cel_align_up( - _cel_BitSet_WordsForBits(new_cap) * sizeof(_cel_BitSetWord), - cel_kMaxAlign); - _cel_BitSet_Reset(ctrl, new_cap); - - *slot = _cel_GenericFlatHash_Rehash(fh, ctrl, ents, *slot, new_cap, ent_size); - - fh->ctrl = ctrl; - fh->ents = ents; - fh->cap = new_cap; - fh->thr = (new_cap * 2) / 3; - return true; -} - -CEL_ATTRIBUTE_NODISCARD -static bool _cel_GenericFlatHash_PostInsertArena( - CEL_NONNULL(_cel_GenericFlatHash *) fh, CEL_NONNULL(cel_Arena *) arena, - CEL_NONNULL(size_t *) slot, size_t ent_size) { - CEL_ASSERT_GT(fh->len, fh->thr); - - return _cel_GenericFlatHash_GrowArena(fh, arena, fh->cap << 1, slot, - ent_size); -} - -void _cel_GenericFlatHash_Construct(CEL_NONNULL(_cel_GenericFlatHash *) fh, - CEL_NONNULL(_cel_GenericFlatHashHasher) - hasher, - CEL_NONNULL(_cel_GenericFlatHashEqualer) - equaler) { - CEL_ASSERT_NOT_NULL(fh); - CEL_ASSERT_NOT_NULL(hasher); - CEL_ASSERT_NOT_NULL(equaler); - - memset(fh, '\0', sizeof(*fh)); - fh->eq = equaler; - fh->h = hasher; -} - -void _cel_GenericFlatHash_DestructAllocator(CEL_NONNULL(_cel_GenericFlatHash *) - fh, - CEL_NONNULL(cel_Allocator *) alloc, - size_t ent_size) { - CEL_ASSERT_NOT_NULL(fh); - CEL_ASSERT_NOT_NULL(alloc); - CEL_ASSERT_GT(ent_size, 0); - - if (fh->cap != 0) { - size_t size = _cel_align_up(_cel_BitSet_WordsForBits(fh->cap) * - sizeof(_cel_BitSetWord), - cel_kMaxAlign) + - (fh->cap * ent_size); - CEL_NONNULL(void *) data = fh->ctrl; - cel_Allocator_FreeSized(alloc, data, size); - } -} - -bool _cel_GenericFlatHash_ReserveAllocator(CEL_NONNULL(_cel_GenericFlatHash *) - fh, - CEL_NONNULL(cel_Allocator *) alloc, - size_t new_cap, size_t ent_size) { - CEL_ASSERT_NOT_NULL(fh); - CEL_ASSERT_NOT_NULL(alloc); - CEL_ASSERT_GT(ent_size, 0); - - if (new_cap <= fh->cap) { - return true; - } - - new_cap = ((size_t)1) << ((sizeof(size_t) * CHAR_BIT) - - _cel_leading_zeros(new_cap)); - size_t unused_slot = SIZE_MAX; - return _cel_GenericFlatHash_GrowAllocator(fh, alloc, new_cap, &unused_slot, - ent_size); -} - -bool _cel_GenericFlatHash_ReserveArena(CEL_NONNULL(_cel_GenericFlatHash *) fh, - CEL_NONNULL(cel_Arena *) arena, - size_t new_cap, size_t ent_size) { - CEL_ASSERT_NOT_NULL(fh); - CEL_ASSERT_NOT_NULL(arena); - CEL_ASSERT_GT(ent_size, 0); - - if (new_cap <= fh->cap) { - return true; - } - - new_cap = ((size_t)1) << ((sizeof(size_t) * CHAR_BIT) - - _cel_leading_zeros(new_cap)); - size_t unused_slot = SIZE_MAX; - return _cel_GenericFlatHash_GrowArena(fh, arena, new_cap, &unused_slot, - ent_size); -} - -void _cel_GenericFlatHash_ClearAllocator(CEL_NONNULL(_cel_GenericFlatHash *) - fh) { - CEL_ASSERT_NOT_NULL(fh); - - if (fh->ctrl != cel_nullptr && fh->len != 0) { - _cel_BitSet_Reset(fh->ctrl, _cel_BitSet_WordsForBits(fh->cap)); - fh->len = 0; - } -} - -void _cel_GenericFlatHash_ClearArena(CEL_NONNULL(_cel_GenericFlatHash *) fh) { - CEL_ASSERT_NOT_NULL(fh); - - if (fh->ctrl != cel_nullptr && fh->len != 0) { - _cel_BitSet_Reset(fh->ctrl, _cel_BitSet_WordsForBits(fh->cap)); - fh->len = 0; - } -} - -void _cel_GenericFlatHash_ResetAllocator(CEL_NONNULL(_cel_GenericFlatHash *) fh, - CEL_NONNULL(cel_Allocator *) alloc, - size_t ent_size) { - CEL_ASSERT_NOT_NULL(fh); - CEL_ASSERT_NOT_NULL(alloc); - CEL_ASSERT_GT(ent_size, 0); - - CEL_NONNULL(_cel_GenericFlatHashHasher) - hasher = fh->h; - CEL_NONNULL(_cel_GenericFlatHashEqualer) - equaler = fh->eq; - _cel_GenericFlatHash_DestructAllocator(fh, alloc, ent_size); - _cel_GenericFlatHash_Construct(fh, hasher, equaler); -} - -CEL_NULLABLE(const void *) -_cel_GenericFlatHash_Find(CEL_NONNULL(const _cel_GenericFlatHash *) fh, - CEL_NONNULL(const void *) key, size_t ent_size) { - CEL_ASSERT_NOT_NULL(fh); - CEL_ASSERT_NOT_NULL(key); - CEL_ASSERT_GT(ent_size, 0); - - if (fh->len == 0) { - return cel_nullptr; - } - size_t hash = (*fh->h)(key); - size_t mask = fh->cap - 1; - size_t slot = hash & mask; - if (_cel_BitSet_Test(fh->ctrl, fh->cap, slot)) { - CEL_NONNULL(const char *) - ents = fh->ents; - do { - if ((*fh->eq)(ents + (ent_size * slot), key)) { - return ents + (ent_size * slot); - } - slot = (slot + 1) & mask; - } while (_cel_BitSet_Test(fh->ctrl, fh->cap, slot)); - } - return cel_nullptr; -} - -void _cel_GenericFlatHash_Erase(CEL_NONNULL(_cel_GenericFlatHash *) fh, - CEL_NONNULL(const void *) ent, - size_t ent_size) { - CEL_ASSERT_NOT_NULL(fh); - CEL_ASSERT_NOT_NULL(ent); - CEL_ASSERT_GT(ent_size, 0); - - CEL_NONNULL(char *) - ents = fh->ents; - - CEL_ASSERT_GE((CEL_NONNULL(const char *))ent, ents); - CEL_ASSERT_LT((CEL_NONNULL(const char *))ent, ents + (fh->cap * ent_size)); - - size_t slot = ((size_t)(((CEL_NONNULL(const char *))ent) - ents)) / ent_size; - CEL_ASSERT(_cel_BitSet_Test(fh->ctrl, fh->cap, slot)); - _cel_BitSet_Clear(fh->ctrl, fh->cap, slot); - --(fh->len); - - size_t mask = fh->cap - 1; - size_t i = slot; - size_t j = slot; - while (true) { - j = (j + 1) & mask; - if (!_cel_BitSet_Test(fh->ctrl, fh->cap, j)) { - break; - } - const size_t k = (*fh->h)(ents + (j * ent_size)) & mask; - if (i <= j) { - if (i < k && k <= j) { - continue; - } - } else { - if (k <= j || i < k) { - continue; - } - } - _cel_BitSet_Set(fh->ctrl, fh->cap, i); - memcpy(ents + (i * ent_size), ents + (j * ent_size), ent_size); - _cel_BitSet_Clear(fh->ctrl, fh->cap, j); - i = j; - } -} - -bool _cel_GenericFlatHash_InsertAllocator( - CEL_NONNULL(_cel_GenericFlatHash *) fh, CEL_NONNULL(cel_Allocator *) alloc, - CEL_NONNULL(const void *) key, CEL_NONNULL(CEL_NULLABLE(void *) *) ent, - size_t ent_size, size_t key_size) { - CEL_ASSERT_NOT_NULL(fh); - CEL_ASSERT_NOT_NULL(alloc); - CEL_ASSERT_NOT_NULL(key); - CEL_ASSERT_NOT_NULL(ent); - CEL_ASSERT_GT(ent_size, 0); - - if (CEL_UNLIKELY(fh->cap == 0 && !_cel_GenericFlatHash_PreInsertAllocator( - fh, alloc, ent_size))) { - *ent = cel_nullptr; - return false; - } - - size_t hash = (*fh->h)(key); - size_t mask = fh->cap - 1; - size_t slot = hash & mask; - CEL_NONNULL(char *) - ents = fh->ents; - while (_cel_BitSet_Test(fh->ctrl, fh->cap, slot)) { - if ((*fh->eq)(ents + (ent_size * slot), key)) { - *ent = ents + (ent_size * slot); - return false; - } - slot = (slot + 1) & mask; - } - - memcpy(ents + (slot * ent_size), key, key_size); - _cel_BitSet_Set(fh->ctrl, fh->cap, slot); - ++(fh->len); - - if (CEL_UNLIKELY(fh->len > fh->thr)) { - if (CEL_UNLIKELY(!_cel_GenericFlatHash_PostInsertAllocator(fh, alloc, &slot, - ent_size))) { - _cel_BitSet_Clear(fh->ctrl, fh->cap, slot); - --(fh->len); - *ent = cel_nullptr; - return false; - } - ents = fh->ents; - } - - *ent = ents + (ent_size * slot); - - return true; -} - -bool _cel_GenericFlatHash_InsertArena(CEL_NONNULL(_cel_GenericFlatHash *) fh, - CEL_NONNULL(cel_Arena *) arena, - CEL_NONNULL(const void *) key, - CEL_NONNULL(CEL_NULLABLE(void *) *) ent, - size_t ent_size, size_t key_size) { - CEL_ASSERT_NOT_NULL(fh); - CEL_ASSERT_NOT_NULL(arena); - CEL_ASSERT_NOT_NULL(key); - CEL_ASSERT_NOT_NULL(ent); - CEL_ASSERT_GT(ent_size, 0); - - if (CEL_UNLIKELY(fh->cap == 0 && - !_cel_GenericFlatHash_PreInsertArena(fh, arena, ent_size))) { - *ent = cel_nullptr; - return false; - } - - size_t hash = (*fh->h)(key); - size_t mask = fh->cap - 1; - size_t slot = hash & mask; - CEL_NONNULL(char *) - ents = fh->ents; - while (_cel_BitSet_Test(fh->ctrl, fh->cap, slot)) { - if ((*fh->eq)(ents + (ent_size * slot), key)) { - *ent = ents + (ent_size * slot); - return false; - } - slot = (slot + 1) & mask; - } - - memcpy(ents + (slot * ent_size), key, key_size); - _cel_BitSet_Set(fh->ctrl, fh->cap, slot); - ++(fh->len); - - if (CEL_UNLIKELY(fh->len > fh->thr)) { - if (CEL_UNLIKELY(!_cel_GenericFlatHash_PostInsertArena(fh, arena, &slot, - ent_size))) { - _cel_BitSet_Clear(fh->ctrl, fh->cap, slot); - --(fh->len); - *ent = cel_nullptr; - return false; - } - ents = fh->ents; - } - - *ent = ents + (ent_size * slot); - - return true; -} - -bool _cel_GenericFlatHash_Next(CEL_NONNULL(const _cel_GenericFlatHash *) fh, - CEL_NONNULL(CEL_NULLABLE(const void *) *) ent, - size_t ent_size) { - CEL_ASSERT_NOT_NULL(fh); - CEL_ASSERT_NOT_NULL(ent); - CEL_ASSERT_GT(ent_size, 0); - - CEL_NULLABLE(const char *) - ents = fh->ents; - - size_t i; - if (*ent == _cel_GenericFlatHash_kBegin) { - i = _cel_BitSet_kBegin; - } else { - CEL_ASSERT_GE((CEL_NONNULL(const char *)) * ent, ents); - CEL_ASSERT_LT((CEL_NONNULL(const char *)) * ent, - ents + (fh->cap * ent_size)); - i = (((size_t)(((CEL_NONNULL(const char *)) * ent) - ents)) / ent_size); - } - const bool next = _cel_BitSet_Next(fh->ctrl, fh->cap, &i); - *ent = ents + (ent_size * i); - return next; -} diff --git a/cel-c/src/generic_string.c b/cel-c/src/generic_string.c deleted file mode 100644 index 89e5264..0000000 --- a/cel-c/src/generic_string.c +++ /dev/null @@ -1,939 +0,0 @@ -// Copyright 2025 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "cel-c/src/generic_string.h" - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "cel-c/alloc.h" -#include "cel-c/arena.h" -#include "cel-c/assert.h" -#include "cel-c/config.h" -#include "cel-c/string_view.h" -#include "cel-c/src/asan.h" -#include "cel-c/src/ckdint.h" - -static void _cel_GenericString_AnnotateNew(CEL_NONNULL(char*) str, size_t len, - size_t cap) { - _cel_sanitizer_annotate_contiguous_container(str, str + cap + 1, - str + cap + 1, str + len + 1); -} - -static void _cel_GenericString_Annotate(CEL_NONNULL(char*) str, size_t old_len, - size_t new_len, size_t cap) { - _cel_sanitizer_annotate_contiguous_container( - str, str + cap + 1, str + old_len + 1, str + new_len + 1); -} - -static void _cel_GenericString_AnnotateDelete(CEL_NONNULL(char*) str, - size_t len, size_t cap) { - _cel_sanitizer_annotate_contiguous_container(str, str + cap + 1, - str + len + 1, str + cap + 1); -} - -static void _cel_GenericString_AnnotateLargeNew(CEL_NONNULL(char*) str, - size_t len, size_t cap) { - _cel_GenericString_AnnotateNew(str, len, cap); -} - -static void _cel_GenericString_AnnotateLarge(CEL_NONNULL(char*) str, - size_t old_len, size_t new_len, - size_t cap) { - _cel_GenericString_Annotate(str, old_len, new_len, cap); -} - -static void _cel_GenericString_AnnotateLargeDelete(CEL_NONNULL(char*) str, - size_t len, size_t cap) { - _cel_GenericString_AnnotateDelete(str, len, cap); -} - -void _cel_GenericString_Construct(CEL_NONNULL(_cel_GenericString*) str) { - CEL_ASSERT_NOT_NULL(str); - - str->small.data[0] = '\0'; - str->small.len = 0; - str->small.is_large = 0; -} - -void _cel_GenericString_DestructAllocator(CEL_NONNULL(_cel_GenericString*) str, - CEL_NONNULL(cel_Allocator*) alloc) { - CEL_ASSERT_NOT_NULL(str); - CEL_ASSERT_NOT_NULL(alloc); - - if (str->large.is_large) { - _cel_GenericString_AnnotateLargeDelete(str->large.data, str->large.len, - str->large.cap); - cel_Allocator_FreeSized(alloc, str->large.data, str->large.cap + 1); - } -} - -void _cel_GenericString_Clear(CEL_NONNULL(_cel_GenericString*) str) { - CEL_ASSERT_NOT_NULL(str); - - if (str->large.is_large) { - // Avoid the likely cache miss if we do not actually need to write '\0'. - if (str->large.len > 0) { - _cel_GenericString_AnnotateLarge(str->large.data, str->large.len, 0, - str->large.cap); - str->large.data[0] = '\0'; - str->large.len = 0; - } - } else { - str->small.data[0] = '\0'; - str->small.len = 0; - } -} - -void _cel_GenericString_ResetAllocator(CEL_NONNULL(_cel_GenericString*) str, - CEL_NONNULL(cel_Allocator*) alloc) { - _cel_GenericString_DestructAllocator(str, alloc); - _cel_GenericString_Construct(str); -} - -bool _cel_GenericString_ShrinkToFitAllocator(CEL_NONNULL(_cel_GenericString*) - str, - CEL_NONNULL(cel_Allocator*) - alloc) { - CEL_ASSERT_NOT_NULL(str); - CEL_ASSERT_NOT_NULL(alloc); - - if (str->large.is_large && str->large.cap > str->large.len) { - if (str->large.len <= _cel_GenericStringSmall_kCapacity) { - CEL_NONNULL(char*) data = str->large.data; - size_t len = str->large.len; - size_t cap = str->large.cap; - memcpy(str->small.data, data, len + 1); - str->small.len = len; - str->small.is_large = 0; - _cel_GenericString_AnnotateLargeDelete(data, len, cap); - cel_Allocator_FreeSized(alloc, data, cap + 1); - return true; - } - size_t new_cap = str->large.cap; - size_t actual_new_cap; - CEL_NULLABLE(char*) - data = cel_Allocator_Malloc(alloc, new_cap + 1, &actual_new_cap); - if (CEL_UNLIKELY(data == cel_nullptr)) { - return false; - } - --actual_new_cap; - if (actual_new_cap >= str->large.cap) { - cel_Allocator_FreeSized(alloc, data, actual_new_cap + 1); - return true; - } - _cel_GenericString_AnnotateLargeNew(data, str->large.len, actual_new_cap); - memcpy(data, str->large.data, str->large.len + 1); - _cel_GenericString_AnnotateLargeDelete(str->large.data, str->large.len, - str->large.cap); - cel_Allocator_FreeSized(alloc, str->large.data, str->large.cap + 1); - str->large.data = data; - str->large.cap = actual_new_cap; - } - - return true; -} - -bool _cel_GenericString_AssignAllocator(CEL_NONNULL(_cel_GenericString*) str, - CEL_NONNULL(cel_Allocator*) alloc, - cel_StringView val) { - CEL_ASSERT_NOT_NULL(str); - CEL_ASSERT_NOT_NULL(alloc); - - size_t new_len = cel_StringView_Size(val); - - if (new_len == 0) { - _cel_GenericString_Clear(str); - return true; - } - - if (str->large.is_large) { - if (new_len > str->large.cap) { - size_t new_cap = new_len; - size_t actual_new_cap; - CEL_NULLABLE(char*) - data = cel_Allocator_Malloc(alloc, new_cap + 1, &actual_new_cap); - if (CEL_UNLIKELY(data == cel_nullptr)) { - _cel_GenericString_AnnotateLargeNew(str->large.data, str->large.len, - str->large.cap); - str->large.data[str->large.len] = '\0'; - return false; - } - --actual_new_cap; - _cel_GenericString_AnnotateLargeNew(data, new_len, actual_new_cap); - _cel_GenericString_AnnotateLargeDelete(str->large.data, str->large.len, - str->large.cap); - cel_Allocator_FreeSized(alloc, str->large.data, str->large.cap + 1); - str->large.data = data; - str->large.cap = actual_new_cap; - } - } else { - if (new_len <= _cel_GenericStringSmall_kCapacity) { - memcpy(str->small.data, cel_StringView_Data(val), new_len); - str->small.data[new_len] = '\0'; - str->small.len = new_len; - return true; - } - size_t new_cap = new_len; - size_t actual_new_cap; - CEL_NULLABLE(char*) - data = cel_Allocator_Malloc(alloc, new_cap + 1, &actual_new_cap); - if (CEL_UNLIKELY(data == cel_nullptr)) { - str->small.data[str->small.len] = '\0'; - return false; - } - --actual_new_cap; - _cel_GenericString_AnnotateLargeNew(data, new_len, actual_new_cap); - str->large.data = data; - str->large.cap = actual_new_cap; - str->large.is_large = 1; - } - - // If we got here, the string **must** be large. - memcpy(str->large.data, cel_StringView_Data(val), new_len); - str->large.data[new_len] = '\0'; - str->large.len = new_len; - return true; -} - -bool _cel_GenericString_AssignArena(CEL_NONNULL(_cel_GenericString*) str, - CEL_NONNULL(cel_Arena*) arena, - cel_StringView val) { - CEL_ASSERT_NOT_NULL(str); - CEL_ASSERT_NOT_NULL(arena); - - size_t new_len = cel_StringView_Size(val); - - if (new_len == 0) { - _cel_GenericString_Clear(str); - return true; - } - - if (str->large.is_large) { - if (new_len > str->large.cap) { - size_t new_cap = new_len; - CEL_NULLABLE(char*) - data = cel_Arena_Malloc(arena, new_cap + 1, cel_nullptr); - if (CEL_UNLIKELY(data == cel_nullptr)) { - _cel_GenericString_AnnotateLargeNew(str->large.data, str->large.len, - str->large.cap); - str->large.data[str->large.len] = '\0'; - return false; - } - _cel_GenericString_AnnotateLargeNew(data, new_len, new_cap); - _cel_GenericString_AnnotateLargeDelete(str->large.data, str->large.len, - str->large.cap); - cel_Arena_FreeSized(arena, str->large.data, str->large.cap + 1); - str->large.data = data; - str->large.cap = new_cap; - } - } else { - if (new_len <= _cel_GenericStringSmall_kCapacity) { - memcpy(str->small.data, cel_StringView_Data(val), new_len); - str->small.data[new_len] = '\0'; - str->small.len = new_len; - return true; - } - size_t new_cap = new_len; - CEL_NULLABLE(char*) - data = cel_Arena_Malloc(arena, new_cap + 1, cel_nullptr); - if (CEL_UNLIKELY(data == cel_nullptr)) { - str->small.data[str->small.len] = '\0'; - return false; - } - _cel_GenericString_AnnotateLargeNew(data, new_len, new_cap); - str->large.data = data; - str->large.cap = new_cap; - str->large.is_large = 1; - } - - // If we got here, the string **must** be large. - memcpy(str->large.data, cel_StringView_Data(val), new_len); - str->large.data[new_len] = '\0'; - str->large.len = new_len; - return true; -} - -ptrdiff_t _cel_GenericString_VAppendFAllocator( - CEL_NONNULL(_cel_GenericString*) str, CEL_NONNULL(cel_Allocator*) alloc, - CEL_NONNULL(const char*) fmt, va_list args) { - CEL_ASSERT_NOT_NULL(str); - CEL_ASSERT_NOT_NULL(alloc); - CEL_ASSERT_NOT_NULL(fmt); - - int n; - { - va_list args_copy; - va_copy(args_copy, args); - if (str->large.is_large) { - // We need to use the remaining capacity. Unpoison it all. - _cel_GenericString_AnnotateLargeDelete(str->large.data, str->large.len, - str->large.cap); - n = vsnprintf(str->large.data + str->large.len, - (str->large.cap - str->large.len) + 1, fmt, args_copy); - } else { - n = vsnprintf(str->small.data + str->small.len, - (_cel_GenericStringSmall_kCapacity - str->small.len) + 1, - fmt, args_copy); - } - va_end(args_copy); - } - - if (n <= 0) { - // Repoison and trust no one, re-terminate the string with NIL. - if (str->large.is_large) { - _cel_GenericString_AnnotateLargeNew(str->large.data, str->large.len, - str->large.cap); - str->large.data[str->large.len] = '\0'; - } else { - str->small.data[str->small.len] = '\0'; - } - return n; - } - - if (str->large.is_large) { - if ((size_t)n < (str->large.cap - str->large.len) + 1) { - // Fit in the remaining capacity. - size_t new_len = str->large.len + (size_t)n; - _cel_GenericString_AnnotateLargeNew(str->large.data, new_len, - str->large.cap); - str->large.data[new_len] = '\0'; - str->large.len = new_len; - return n; - } - size_t new_cap = str->large.len + (size_t)n; - size_t actual_new_cap; - CEL_NULLABLE(char*) - data = cel_Allocator_Malloc(alloc, new_cap + 1, &actual_new_cap); - if (CEL_UNLIKELY(data == cel_nullptr)) { - _cel_GenericString_AnnotateLargeNew(str->large.data, str->large.len, - str->large.cap); - str->large.data[str->large.len] = '\0'; - return -1; - } - --actual_new_cap; - _cel_GenericString_AnnotateLargeNew(data, new_cap, actual_new_cap); - memcpy(data, str->large.data, str->large.len); - _cel_GenericString_AnnotateLargeDelete(str->large.data, str->large.len, - str->large.cap); - cel_Allocator_FreeSized(alloc, str->large.data, str->large.cap + 1); - str->large.data = data; - str->large.cap = actual_new_cap; - } else { - if ((size_t)n < (_cel_GenericStringSmall_kCapacity - str->small.len) + 1) { - size_t new_len = str->small.len + (size_t)n; - // Fit in the remaining capacity. - str->small.data[new_len] = '\0'; - str->small.len = new_len; - return n; - } - size_t len = str->small.len; - size_t new_cap = len + (size_t)n; - size_t actual_new_cap; - CEL_NULLABLE(char*) - data = cel_Allocator_Malloc(alloc, new_cap + 1, &actual_new_cap); - if (CEL_UNLIKELY(data == cel_nullptr)) { - str->small.data[len] = '\0'; - return -1; - } - --actual_new_cap; - _cel_GenericString_AnnotateLargeNew(data, new_cap, actual_new_cap); - memcpy(data, str->small.data, len); - str->large.data = data; - str->large.len = len; - str->large.cap = actual_new_cap; - str->large.is_large = 1; - } - - // If we got here, the string **must** be large. - CEL_ASSERT(str->large.is_large); - const int n2 = vsnprintf(str->large.data + str->large.len, - (str->large.cap - str->large.len) + 1, fmt, args); - CEL_ASSERT_EQ(n2, n); - n = n2; - size_t new_len = str->large.len + (size_t)n; - CEL_ASSERT((size_t)n < (str->large.cap - str->large.len) + 1); - str->large.data[new_len] = '\0'; - str->large.len = new_len; - return n; -} - -ptrdiff_t _cel_GenericString_VAppendFArena(CEL_NONNULL(_cel_GenericString*) str, - CEL_NONNULL(cel_Arena*) arena, - CEL_NONNULL(const char*) fmt, - va_list args) { - CEL_ASSERT_NOT_NULL(str); - CEL_ASSERT_NOT_NULL(arena); - CEL_ASSERT_NOT_NULL(fmt); - - int n; - { - va_list args_copy; - va_copy(args_copy, args); - if (str->large.is_large) { - // We need to use the remaining capacity. Unpoison it all. - _cel_GenericString_AnnotateLargeDelete(str->large.data, str->large.len, - str->large.cap); - n = vsnprintf(str->large.data + str->large.len, - (str->large.cap - str->large.len) + 1, fmt, args_copy); - } else { - n = vsnprintf(str->small.data + str->small.len, - (_cel_GenericStringSmall_kCapacity - str->small.len) + 1, - fmt, args_copy); - } - va_end(args_copy); - } - - if (n <= 0) { - // Repoison and trust no one, re-terminate the string with NIL. - if (str->large.is_large) { - _cel_GenericString_AnnotateLargeNew(str->large.data, str->large.len, - str->large.cap); - str->large.data[str->large.len] = '\0'; - } else { - str->small.data[str->small.len] = '\0'; - } - return n; - } - - if (str->large.is_large) { - if ((size_t)n < (str->large.cap - str->large.len) + 1) { - // Fit in the remaining capacity. - size_t new_len = str->large.len + (size_t)n; - _cel_GenericString_AnnotateLargeNew(str->large.data, new_len, - str->large.cap); - str->large.data[new_len] = '\0'; - str->large.len = new_len; - return n; - } - size_t new_cap = str->large.len + (size_t)n; - CEL_NULLABLE(char*) - data = cel_Arena_Malloc(arena, new_cap + 1, cel_nullptr); - if (CEL_UNLIKELY(data == cel_nullptr)) { - _cel_GenericString_AnnotateLargeNew(str->large.data, str->large.len, - str->large.cap); - str->large.data[str->large.len] = '\0'; - return -1; - } - _cel_GenericString_AnnotateLargeNew(data, new_cap, new_cap); - memcpy(data, str->large.data, str->large.len); - _cel_GenericString_AnnotateLargeDelete(str->large.data, str->large.len, - str->large.cap); - cel_Arena_FreeSized(arena, str->large.data, str->large.cap + 1); - str->large.data = data; - str->large.cap = new_cap; - } else { - if ((size_t)n < (_cel_GenericStringSmall_kCapacity - str->small.len) + 1) { - size_t new_len = str->small.len + (size_t)n; - // Fit in the remaining capacity. - str->small.data[new_len] = '\0'; - str->small.len = new_len; - return n; - } - size_t len = str->small.len; - size_t new_cap = len + (size_t)n; - CEL_NULLABLE(char*) - data = cel_Arena_Malloc(arena, new_cap + 1, cel_nullptr); - if (CEL_UNLIKELY(data == cel_nullptr)) { - str->small.data[len] = '\0'; - return -1; - } - _cel_GenericString_AnnotateLargeNew(data, new_cap, new_cap); - memcpy(data, str->small.data, len); - str->large.data = data; - str->large.len = len; - str->large.cap = new_cap; - str->large.is_large = 1; - } - - // If we got here, the string **must** be large. - CEL_ASSERT(str->large.is_large); - const int n2 = vsnprintf(str->large.data + str->large.len, - (str->large.cap - str->large.len) + 1, fmt, args); - CEL_ASSERT_EQ(n2, n); - n = n2; - size_t new_len = str->large.len + (size_t)n; - CEL_ASSERT((size_t)n < (str->large.cap - str->large.len) + 1); - str->large.data[new_len] = '\0'; - str->large.len = new_len; - return n; -} - -bool _cel_GenericString_StabilizeAllocator(CEL_NONNULL(_cel_GenericString*) str, - CEL_NONNULL(cel_Allocator*) alloc) { - CEL_ASSERT_NOT_NULL(str); - CEL_ASSERT_NOT_NULL(alloc); - - if (str->large.is_large) { - return true; - } - size_t len = str->small.len; - size_t actual_new_cap; - CEL_NULLABLE(char*) - data = cel_Allocator_Malloc(alloc, len + 1, &actual_new_cap); - if (CEL_UNLIKELY(data == cel_nullptr)) { - return false; - } - --actual_new_cap; - _cel_GenericString_AnnotateLargeNew(data, len, actual_new_cap); - memcpy(data, str->small.data, str->small.len + 1); - str->large.is_large = 1; - str->large.len = len; - str->large.cap = actual_new_cap; - str->large.data = data; - return true; -} - -bool _cel_GenericString_StabilizeArena(CEL_NONNULL(_cel_GenericString*) str, - CEL_NONNULL(cel_Arena*) arena) { - CEL_ASSERT_NOT_NULL(str); - CEL_ASSERT_NOT_NULL(arena); - - if (str->large.is_large) { - return true; - } - size_t len = str->small.len; - size_t actual_new_cap; - CEL_NULLABLE(char*) - data = cel_Arena_Malloc(arena, len + 1, &actual_new_cap); - if (CEL_UNLIKELY(data == cel_nullptr)) { - return false; - } - --actual_new_cap; - _cel_GenericString_AnnotateLargeNew(data, len, actual_new_cap); - memcpy(data, str->small.data, str->small.len + 1); - str->large.is_large = 1; - str->large.len = len; - str->large.cap = actual_new_cap; - str->large.data = data; - return true; -} - -void _cel_GenericString_DestabilizeAllocator(CEL_NONNULL(_cel_GenericString*) - str, - CEL_NONNULL(cel_Allocator*) - alloc) { - CEL_ASSERT_NOT_NULL(str); - CEL_ASSERT_NOT_NULL(alloc); - - if (str->large.is_large && - str->large.len <= _cel_GenericStringSmall_kCapacity) { - char* data = str->large.data; - size_t len = str->large.len; - size_t cap = str->large.cap; - str->small.is_large = 0; - str->small.len = (uint8_t)len; - memcpy(str->small.data, data, len + 1); - _cel_GenericString_AnnotateLargeDelete(data, len, cap); - cel_Allocator_FreeSized(alloc, data, cap + 1); - } -} - -void _cel_GenericString_DestabilizeArena(CEL_NONNULL(_cel_GenericString*) str, - CEL_NONNULL(cel_Arena*) arena) { - CEL_ASSERT_NOT_NULL(str); - CEL_ASSERT_NOT_NULL(arena); - - if (str->large.is_large && - str->large.len <= _cel_GenericStringSmall_kCapacity) { - char* data = str->large.data; - size_t len = str->large.len; - size_t cap = str->large.cap; - str->small.is_large = 0; - str->small.len = (uint8_t)len; - memcpy(str->small.data, data, len + 1); - _cel_GenericString_AnnotateLargeDelete(data, len, cap); - cel_Arena_FreeSized(arena, data, cap + 1); - } -} - -CEL_ATTRIBUTE_NODISCARD -static bool _cel_GenericString_PrepareToAppendAllocator( - CEL_NONNULL(_cel_GenericString*) str, CEL_NONNULL(cel_Allocator*) alloc, - size_t size) { - CEL_ASSERT_NOT_NULL(str); - CEL_ASSERT_NOT_NULL(alloc); - - if (str->large.is_large) { - size_t capacity; - if (CEL_UNLIKELY(_cel_ckd_add(&capacity, size, (size_t)str->large.len))) { - return false; - } - if (CEL_LIKELY(str->large.cap >= capacity)) { - return true; - } - size_t min_cap = capacity; - size_t max_cap = _cel_GenericString_kMaxSize; - if (min_cap > max_cap) { - return false; - } - size_t new_cap = str->large.cap; - while (new_cap < min_cap) { - if (_cel_ckd_mul(&new_cap, new_cap, (size_t)2) || new_cap > max_cap) { - new_cap = max_cap; - break; - } - } - size_t actual_cap; - char* data = (char*)cel_Allocator_Malloc(alloc, new_cap + 1, &actual_cap); - if (CEL_UNLIKELY(data == cel_nullptr)) { - return false; - } - --actual_cap; - _cel_GenericString_AnnotateNew(data, str->large.len, actual_cap); - memcpy(data, str->large.data, str->large.len + 1); - _cel_GenericString_AnnotateDelete(str->large.data, str->large.len, - str->large.cap); - cel_Allocator_FreeSized(alloc, str->large.data, str->large.cap + 1); - str->large.data = data; - str->large.cap = actual_cap; - } else { - size_t capacity; - if (CEL_UNLIKELY(_cel_ckd_add(&capacity, size, (size_t)str->small.len))) { - return false; - } - if (_cel_GenericStringSmall_kCapacity >= capacity) { - return true; - } - size_t min_cap = capacity; - size_t max_cap = _cel_GenericString_kMaxSize; - if (min_cap > max_cap) { - return false; - } - size_t new_cap = _cel_GenericStringSmall_kCapacity; - while (new_cap < min_cap) { - if (_cel_ckd_mul(&new_cap, new_cap, (size_t)2) || new_cap > max_cap) { - new_cap = max_cap; - break; - } - } - size_t actual_cap; - char* data = (char*)cel_Allocator_Malloc(alloc, new_cap + 1, &actual_cap); - if (CEL_UNLIKELY(data == cel_nullptr)) { - return false; - } - --actual_cap; - _cel_GenericString_AnnotateNew(data, str->small.len, actual_cap); - memcpy(data, str->small.data, str->small.len + 1); - size_t len = str->small.len; - str->large.is_large = 1; - str->large.len = len; - str->large.data = data; - str->large.cap = actual_cap; - } - return true; -} - -CEL_ATTRIBUTE_NODISCARD -static bool _cel_GenericString_PrepareToAppendArena( - CEL_NONNULL(_cel_GenericString*) str, CEL_NONNULL(cel_Arena*) arena, - size_t size) { - CEL_ASSERT_NOT_NULL(str); - CEL_ASSERT_NOT_NULL(arena); - - if (str->large.is_large) { - size_t capacity; - if (CEL_UNLIKELY(_cel_ckd_add(&capacity, size, (size_t)str->large.len))) { - return false; - } - if (CEL_LIKELY(str->large.cap >= capacity)) { - return true; - } - size_t min_cap = capacity; - size_t max_cap = _cel_GenericString_kMaxSize; - if (min_cap > max_cap) { - return false; - } - size_t new_cap = str->large.cap; - while (new_cap < min_cap) { - if (_cel_ckd_mul(&new_cap, new_cap, (size_t)2) || new_cap > max_cap) { - new_cap = max_cap; - break; - } - } - size_t actual_cap; - char* data = (char*)cel_Arena_Malloc(arena, new_cap + 1, &actual_cap); - if (CEL_UNLIKELY(data == cel_nullptr)) { - return false; - } - --actual_cap; - _cel_GenericString_AnnotateNew(data, str->large.len, actual_cap); - memcpy(data, str->large.data, str->large.len + 1); - _cel_GenericString_AnnotateDelete(str->large.data, str->large.len, - str->large.cap); - cel_Arena_FreeSized(arena, str->large.data, str->large.cap + 1); - str->large.data = data; - str->large.cap = actual_cap; - } else { - size_t capacity; - if (CEL_UNLIKELY(_cel_ckd_add(&capacity, size, (size_t)str->small.len))) { - return false; - } - if (_cel_GenericStringSmall_kCapacity >= capacity) { - return true; - } - size_t min_cap = capacity; - size_t max_cap = _cel_GenericString_kMaxSize; - if (min_cap > max_cap) { - return false; - } - size_t new_cap = _cel_GenericStringSmall_kCapacity; - while (new_cap < min_cap) { - if (_cel_ckd_mul(&new_cap, new_cap, (size_t)2) || new_cap > max_cap) { - new_cap = max_cap; - break; - } - } - size_t actual_cap; - char* data = (char*)cel_Arena_Malloc(arena, new_cap + 1, &actual_cap); - if (CEL_UNLIKELY(data == cel_nullptr)) { - return false; - } - --actual_cap; - _cel_GenericString_AnnotateNew(data, str->small.len, actual_cap); - memcpy(data, str->small.data, str->small.len + 1); - size_t len = str->small.len; - str->large.is_large = 1; - str->large.len = len; - str->large.data = data; - str->large.cap = actual_cap; - } - return true; -} - -bool _cel_GenericString_AppendAllocator(CEL_NONNULL(_cel_GenericString*) str, - CEL_NONNULL(cel_Allocator*) alloc, - cel_StringView val) { - CEL_ASSERT_NOT_NULL(str); - CEL_ASSERT_NOT_NULL(alloc); - - size_t val_len = cel_StringView_Size(val); - if (val_len > 0) { - if (CEL_UNLIKELY(!_cel_GenericString_PrepareToAppendAllocator(str, alloc, - val_len))) { - return false; - } - if (str->large.is_large) { - size_t new_len = str->large.len + val_len; - _cel_GenericString_AnnotateLarge(str->large.data, str->large.len, new_len, - str->large.cap); - memcpy(str->large.data + str->large.len, cel_StringView_Data(val), - val_len); - str->large.data[new_len] = '\0'; - str->large.len = new_len; - } else { - uint8_t new_len = str->small.len + (uint8_t)val_len; - memcpy(str->small.data + str->small.len, cel_StringView_Data(val), - val_len); - str->small.data[new_len] = '\0'; - str->small.len = new_len; - } - } - return true; -} - -bool _cel_GenericString_AppendArena(CEL_NONNULL(_cel_GenericString*) str, - CEL_NONNULL(cel_Arena*) arena, - cel_StringView val) { - CEL_ASSERT_NOT_NULL(str); - CEL_ASSERT_NOT_NULL(arena); - - size_t val_len = cel_StringView_Size(val); - if (val_len > 0) { - if (CEL_UNLIKELY( - !_cel_GenericString_PrepareToAppendArena(str, arena, val_len))) { - return false; - } - if (str->large.is_large) { - size_t new_len = str->large.len + val_len; - _cel_GenericString_AnnotateLarge(str->large.data, str->large.len, new_len, - str->large.cap); - memcpy(str->large.data + str->large.len, cel_StringView_Data(val), - val_len); - str->large.data[new_len] = '\0'; - str->large.len = new_len; - } else { - uint8_t new_len = str->small.len + (uint8_t)val_len; - memcpy(str->small.data + str->small.len, cel_StringView_Data(val), - val_len); - str->small.data[new_len] = '\0'; - str->small.len = new_len; - } - } - return true; -} - -bool _cel_GenericString_PushBackAllocator(CEL_NONNULL(_cel_GenericString*) str, - CEL_NONNULL(cel_Allocator*) alloc, - char val) { - CEL_ASSERT_NOT_NULL(str); - CEL_ASSERT_NOT_NULL(alloc); - - if (CEL_UNLIKELY( - !_cel_GenericString_PrepareToAppendAllocator(str, alloc, 1))) { - return false; - } - if (str->large.is_large) { - size_t new_len = str->large.len + 1; - _cel_GenericString_AnnotateLarge(str->large.data, str->large.len, new_len, - str->large.cap); - str->large.data[new_len - 1] = val; - str->large.data[new_len] = '\0'; - str->large.len = new_len; - } else { - uint8_t new_len = str->small.len + (uint8_t)1; - str->small.data[new_len - 1] = val; - str->small.data[new_len] = '\0'; - str->small.len = new_len; - } - return true; -} - -bool _cel_GenericString_PushBackArena(CEL_NONNULL(_cel_GenericString*) str, - CEL_NONNULL(cel_Arena*) arena, char val) { - CEL_ASSERT_NOT_NULL(str); - CEL_ASSERT_NOT_NULL(arena); - - if (CEL_UNLIKELY(!_cel_GenericString_PrepareToAppendArena(str, arena, 1))) { - return false; - } - if (str->large.is_large) { - size_t new_len = str->large.len + 1; - _cel_GenericString_AnnotateLarge(str->large.data, str->large.len, new_len, - str->large.cap); - str->large.data[new_len - 1] = val; - str->large.data[new_len] = '\0'; - str->large.len = new_len; - } else { - uint8_t new_len = str->small.len + (uint8_t)1; - str->small.data[new_len - 1] = val; - str->small.data[new_len] = '\0'; - str->small.len = new_len; - } - return true; -} - -bool _cel_GenericString_ReserveAllocator(CEL_NONNULL(_cel_GenericString*) str, - CEL_NONNULL(cel_Allocator*) alloc, - size_t capacity) { - CEL_ASSERT_NOT_NULL(str); - CEL_ASSERT_NOT_NULL(alloc); - - if (str->large.is_large) { - if (str->large.cap >= capacity) { - return true; - } - size_t min_cap = capacity; - size_t max_cap = _cel_GenericString_kMaxSize; - if (min_cap > max_cap) { - return false; - } - size_t actual_cap; - char* data = (char*)cel_Allocator_Malloc(alloc, min_cap + 1, &actual_cap); - if (CEL_UNLIKELY(data == cel_nullptr)) { - return false; - } - --actual_cap; - _cel_GenericString_AnnotateNew(data, str->large.len, actual_cap); - memcpy(data, str->large.data, str->large.len + 1); - _cel_GenericString_AnnotateDelete(str->large.data, str->large.len, - str->large.cap); - cel_Allocator_FreeSized(alloc, str->large.data, str->large.cap + 1); - str->large.data = data; - str->large.cap = actual_cap; - } else { - if (_cel_GenericStringSmall_kCapacity >= capacity) { - return true; - } - size_t min_cap = capacity; - size_t max_cap = _cel_GenericString_kMaxSize; - if (min_cap > max_cap) { - return false; - } - size_t actual_cap; - char* data = (char*)cel_Allocator_Malloc(alloc, min_cap + 1, &actual_cap); - if (CEL_UNLIKELY(data == cel_nullptr)) { - return false; - } - --actual_cap; - _cel_GenericString_AnnotateNew(data, str->small.len, actual_cap); - memcpy(data, str->small.data, str->small.len + 1); - size_t len = str->small.len; - str->large.is_large = 1; - str->large.len = len; - str->large.data = data; - str->large.cap = actual_cap; - } - return true; -} - -bool _cel_GenericString_ReserveArena(CEL_NONNULL(_cel_GenericString*) str, - CEL_NONNULL(cel_Arena*) arena, - size_t capacity) { - CEL_ASSERT_NOT_NULL(str); - CEL_ASSERT_NOT_NULL(arena); - - if (str->large.is_large) { - if (str->large.cap >= capacity) { - return true; - } - size_t min_cap = capacity; - size_t max_cap = _cel_GenericString_kMaxSize; - if (min_cap > max_cap) { - return false; - } - size_t actual_cap; - char* data = (char*)cel_Arena_Malloc(arena, min_cap + 1, &actual_cap); - if (CEL_UNLIKELY(data == cel_nullptr)) { - return false; - } - --actual_cap; - _cel_GenericString_AnnotateNew(data, str->large.len, actual_cap); - memcpy(data, str->large.data, str->large.len + 1); - _cel_GenericString_AnnotateDelete(str->large.data, str->large.len, - str->large.cap); - cel_Arena_FreeSized(arena, str->large.data, str->large.cap + 1); - str->large.data = data; - str->large.cap = actual_cap; - } else { - if (_cel_GenericStringSmall_kCapacity >= capacity) { - return true; - } - size_t min_cap = capacity; - size_t max_cap = _cel_GenericString_kMaxSize; - if (min_cap > max_cap) { - return false; - } - size_t actual_cap; - char* data = (char*)cel_Arena_Malloc(arena, min_cap + 1, &actual_cap); - if (CEL_UNLIKELY(data == cel_nullptr)) { - return false; - } - --actual_cap; - _cel_GenericString_AnnotateNew(data, str->small.len, actual_cap); - memcpy(data, str->small.data, str->small.len + 1); - size_t len = str->small.len; - str->large.is_large = 1; - str->large.len = len; - str->large.data = data; - str->large.cap = actual_cap; - } - return true; -} diff --git a/cel-c/src/list_value.c b/cel-c/src/list_value.c deleted file mode 100644 index 71bdf4c..0000000 --- a/cel-c/src/list_value.c +++ /dev/null @@ -1,154 +0,0 @@ -// Copyright 2025 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include -#include -#include -#include - -#include "cel-c/assert.h" -#include "cel-c/config.h" -#include "cel-c/status.h" -#include "cel-c/value.h" - -bool cel_ListValue_Equals(const cel_ListValue* cel_nonnull list_value, - const cel_ValueContext* cel_nonnull context, - const cel_ListValue* cel_nonnull other, - cel_Value* cel_nonnull result, - cel_Status* cel_nonnull status) { - CEL_ASSERT_NOT_NULL(list_value); - CEL_ASSERT_NOT_NULL(context); - CEL_ASSERT_NOT_NULL(other); - CEL_ASSERT_NOT_NULL(result); - CEL_ASSERT_NOT_NULL(status); - - if (CEL_UNLIKELY(!cel_Status_Ok(status))) { - return false; - } - - if (list_value->vtable->Equals != cel_nullptr) { - if ((*list_value->vtable->Equals)(list_value->vtable, list_value->content, - context, other, result, status)) { - return true; - } - if (CEL_UNLIKELY(!cel_Status_Ok(status))) { - return false; - } - } - if (other->vtable->Equals != cel_nullptr && - other->vtable->Equals != list_value->vtable->Equals) { - if ((*other->vtable->Equals)(other->vtable, other->content, context, - list_value, result, status)) { - return true; - } - if (CEL_UNLIKELY(!cel_Status_Ok(status))) { - return false; - } - } - if (list_value->vtable->FastSize != cel_nullptr && - other->vtable->FastSize != cel_nullptr) { - size_t lhs_size; - size_t rhs_size; - if ((*list_value->vtable->FastSize)(list_value->vtable, list_value->content, - &lhs_size) && - (*other->vtable->FastSize)(other->vtable, other->content, &rhs_size)) { - if (lhs_size != rhs_size) { - cel_Value_SetFalse(result); - return true; - } - if (lhs_size == 0) { - cel_Value_SetTrue(result); - return true; - } - } - } - cel_ListValueIterator* lhs_iter = - cel_ListValue_NewIterator(list_value, context, status); - if (CEL_UNLIKELY(lhs_iter == cel_nullptr)) { - CEL_ASSERT(!cel_Status_Ok(status)); - return false; - } - CEL_ASSERT(cel_Status_Ok(status)); - cel_ListValueIterator* rhs_iter = - cel_ListValue_NewIterator(other, context, status); - if (CEL_UNLIKELY(lhs_iter == cel_nullptr)) { - cel_ListValueIterator_Delete(lhs_iter); - CEL_ASSERT(!cel_Status_Ok(status)); - return false; - } - size_t lhs_size; - size_t rhs_size; - bool lhs_has_size; - bool rhs_has_size; - lhs_has_size = cel_ListValueIterator_Remaining(lhs_iter, &lhs_size); - rhs_has_size = cel_ListValueIterator_Remaining(rhs_iter, &rhs_size); - if (lhs_has_size && rhs_has_size) { - if (lhs_size != rhs_size) { - cel_ListValueIterator_Delete(rhs_iter); - cel_ListValueIterator_Delete(lhs_iter); - cel_Value_SetFalse(result); - return true; - } - if (lhs_size == 0) { - cel_ListValueIterator_Delete(rhs_iter); - cel_ListValueIterator_Delete(lhs_iter); - cel_Value_SetTrue(result); - return true; - } - } - CEL_ASSERT(cel_Status_Ok(status)); - bool ok; - while (true) { - cel_Value lhs_ele; - cel_Value rhs_ele; - bool lhs_has_ele; - bool rhs_has_ele; - if (!(lhs_has_ele = cel_ListValueIterator_Next1(lhs_iter, context, &lhs_ele, - status))) { - if (!cel_Status_Ok(status)) { - ok = false; - break; - } - } - CEL_ASSERT(cel_Status_Ok(status)); - if (!(rhs_has_ele = cel_ListValueIterator_Next1(rhs_iter, context, &rhs_ele, - status))) { - if (!cel_Status_Ok(status)) { - ok = false; - break; - } - } - CEL_ASSERT(cel_Status_Ok(status)); - if (lhs_has_ele != rhs_has_ele) { - cel_Value_SetFalse(result); - ok = true; - break; - } - if (!lhs_has_ele) { - cel_Value_SetTrue(result); - ok = true; - break; - } - if (!cel_Value_Equals(&lhs_ele, context, &rhs_ele, result, status)) { - if (!cel_Status_Ok(status)) { - ok = false; - break; - } - } - CEL_ASSERT(cel_Status_Ok(status)); - } - cel_ListValueIterator_Delete(rhs_iter); - cel_ListValueIterator_Delete(lhs_iter); - return ok; -} diff --git a/cel-c/src/malloc.c b/cel-c/src/malloc.c deleted file mode 100644 index 528270c..0000000 --- a/cel-c/src/malloc.c +++ /dev/null @@ -1,159 +0,0 @@ -// Copyright 2024 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "cel-c/src/malloc.h" - -#if defined(__APPLE__) -#include -#endif - -#if defined(__FreeBSD__) -#include -#endif - -#include -#include -#include -#include -#include -#include -#include - -#include "cel-c/assert.h" -#include "cel-c/src/bit.h" -#include "cel-c/src/ckdint.h" -#include "cel-c/src/config.h" - -#ifdef _CEL_HAVE_SANITIZER -#include -#endif - -#if _CEL_HAVE_ATTRIBUTE_WEAK && !defined(__FreeBSD__) && \ - !defined(__APPLE__) && !defined(_CEL_HAVE_SANITIZER) -_CEL_ATTRIBUTE_WEAK CEL_EXTERN size_t nallocx(size_t size, int opts) { - CEL_USED(opts); - return size; -} -#ifndef MALLOCX_LG_ALIGN -#define MALLOCX_LG_ALIGN(la) ((int)(la)) -#endif -#ifndef MALLOCX_ALIGN -#define MALLOCX_ALIGN(a) MALLOCX_LG_ALIGN(_cel_ffs(a) - 1) -#endif -#endif - -CEL_ATTRIBUTE_NODISCARD -static CEL_INLINE size_t _cel_MallocGoodSize(size_t size) { -#if defined(_CEL_HAVE_SANITIZER) - return __sanitizer_get_estimated_allocated_size(size); -#elif defined(__APPLE__) - return malloc_good_size(size); -#elif defined(__FreeBSD__) || _CEL_HAVE_ATTRIBUTE_WEAK - return nallocx(size, MALLOCX_ALIGN(alignof(max_align_t))); -#else - return size; -#endif -} - -CEL_NULLABLE(void*) -_cel_Malloc(size_t size, CEL_NULLABLE(size_t*) actual_size) { - if (CEL_UNLIKELY(size == 0)) { - if (actual_size != cel_nullptr) { - *actual_size = 0; - } - return cel_nullptr; - } - if (CEL_UNLIKELY(size > (size_t)PTRDIFF_MAX)) { - if (actual_size != cel_nullptr) { - *actual_size = 0; - } - errno = ENOMEM; - return cel_nullptr; - } - if (actual_size != cel_nullptr) { - size = _cel_MallocGoodSize(size); - } - void* p = malloc(size); - if (actual_size != cel_nullptr) { - *actual_size = p != cel_nullptr ? size : 0; - } - if (CEL_UNLIKELY(p == cel_nullptr)) { - errno = ENOMEM; - } - return p; -} - -CEL_NULLABLE(void*) -_cel_Calloc(size_t num, size_t size, CEL_NULLABLE(size_t*) actual_num) { - if (CEL_UNLIKELY(num == 0 || size == 0)) { - if (actual_num != cel_nullptr) { - *actual_num = 0; - } - return cel_nullptr; - } - size_t total_size; - if (CEL_UNLIKELY(_cel_ckd_mul(&total_size, num, size) || - total_size > (size_t)PTRDIFF_MAX)) { - if (actual_num != cel_nullptr) { - *actual_num = 0; - } - errno = ENOMEM; - return cel_nullptr; - } - void* addr = _cel_Malloc(total_size, actual_num); - if (CEL_LIKELY(addr != cel_nullptr)) { - memset(addr, 0, actual_num != cel_nullptr ? *actual_num : total_size); - } - if (actual_num != cel_nullptr) { - *actual_num /= size; - } - return addr; -} - -CEL_NULLABLE(void*) -_cel_Realloc(CEL_NULLABLE(void*) addr, size_t old_size, size_t new_size, - CEL_NULLABLE(size_t*) actual_size) { - if (old_size == 0) { - CEL_ASSERT_NULL(addr); - return _cel_Malloc(new_size, actual_size); - } - if (new_size == 0) { - _cel_FreeSized(addr, old_size); - if (actual_size != cel_nullptr) { - *actual_size = 0; - } - return cel_nullptr; - } - if (actual_size == cel_nullptr) { - return realloc(addr, new_size); - } - void* new_addr = _cel_Malloc(new_size, actual_size); - if (CEL_LIKELY(new_addr != cel_nullptr)) { - memcpy(new_addr, addr, old_size < new_size ? old_size : new_size); - _cel_FreeSized(addr, old_size); - } - return new_addr; -} - -void _cel_Free(CEL_NULLABLE(void*) addr) { free(addr); } - -void _cel_FreeSized(CEL_NULLABLE(void*) addr, size_t size) { - CEL_ASSERT((addr == cel_nullptr && size == 0) || size != 0); - - // Because we may be using `nallocx`/`malloc_good_size` above, the passed in - // `size` may not be in the acceptable range for `free_sized`. So fallback to - // `free`. - CEL_USED(size); - free(addr); -} diff --git a/cel-c/src/map_value.c b/cel-c/src/map_value.c deleted file mode 100644 index dcd8aaa..0000000 --- a/cel-c/src/map_value.c +++ /dev/null @@ -1,396 +0,0 @@ -// Copyright 2025 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "cel-c/src/map_value.h" - -#include -#include -#include -#include - -#include "cel-c/assert.h" -#include "cel-c/config.h" -#include "cel-c/status.h" -#include "cel-c/value.h" -#include "cel-c/value_kind.h" -#include "cel-c/src/array.h" -#include "cel-c/src/sort.h" - -static void _cel_MapValueKey_SetValue(cel_MapValueKey* cel_nonnull - map_value_key, - const cel_Value* cel_nonnull value) { - switch (cel_Value_Kind(value)) { - case cel_ValueKind_kBool: - cel_MapValueKey_SetBool(map_value_key, cel_Value_GetBool(value)); - return; - case cel_ValueKind_kInt: - cel_MapValueKey_SetInt(map_value_key, cel_Value_GetInt(value)); - return; - case cel_ValueKind_kUint: - cel_MapValueKey_SetUint(map_value_key, cel_Value_GetUint(value)); - return; - case cel_ValueKind_kString: - cel_MapValueKey_SetString(map_value_key, cel_Value_GetString(value)); - return; - default: - CEL_UNREACHABLE(); - } -} - -typedef struct { - cel_MapValueKey key; - cel_Value value; -} _cel_MapValueEntry; - -static int _cel_MapValueEntry_Compare(const void* cel_nullability_unknown lhs, - const void* cel_nullability_unknown rhs) { - return _cel_MapValueKey_Compare(&((const _cel_MapValueEntry*)lhs)->key, - &((const _cel_MapValueEntry*)rhs)->key); -} - -static bool _cel_MapValue_EqualsFast( - const cel_MapValue* cel_nonnull lhs, size_t lhs_size, - const cel_ValueContext* cel_nonnull context, - const cel_MapValue* cel_nonnull rhs, size_t rhs_size, - cel_Value* cel_nonnull result, cel_Status* cel_nonnull status) { - if (lhs_size != rhs_size) { - cel_Value_SetFalse(result); - return true; - } - if (lhs_size == 0) { - cel_Value_SetTrue(result); - return true; - } - // Both have size. We can iterate through one and check if the other has the - // same key and value. - cel_MapValueIterator* lhs_iter = - cel_MapValue_NewIterator(lhs, context, status); - if (CEL_UNLIKELY(lhs_iter == cel_nullptr)) { - CEL_ASSERT(!cel_Status_Ok(status)); - return false; - } - bool ok = true; - while (true) { - cel_Value lhs_key; - cel_Value lhs_value; - cel_MapValueKey rhs_key; - cel_Value rhs_value; - if (!cel_MapValueIterator_Next2(lhs_iter, context, &lhs_key, &lhs_value, - status)) { - if (!cel_Status_Ok(status)) { - ok = false; - break; - } - cel_Value_SetTrue(result); - break; - } - if (cel_Value_IsError(&lhs_key) || cel_Value_IsError(&lhs_value)) { - cel_Value_SetFalse(result); - ok = false; - break; - } - _cel_MapValueKey_SetValue(&rhs_key, &lhs_key); - if (cel_MapValue_Find(rhs, context, &rhs_key, &rhs_value, status)) { - if (!cel_Value_Equals(&lhs_value, context, &rhs_value, result, status)) { - ok = cel_Status_Ok(status); - if (ok) { - cel_Value_SetFalse(result); - } - break; - } - } else { - ok = cel_Status_Ok(status); - if (ok) { - cel_Value_SetFalse(result); - } - break; - } - } - cel_MapValueIterator_Delete(lhs_iter); - return ok; -} - -static bool _cel_MapValue_EqualsSlowWithSize( - const cel_MapValue* cel_nonnull lhs, size_t lhs_size, - const cel_ValueContext* cel_nonnull context, - const cel_MapValue* cel_nonnull rhs, cel_Value* cel_nonnull result, - cel_Status* cel_nonnull status) { - cel_MapValueIterator* rhs_iter = - cel_MapValue_NewIterator(rhs, context, status); - if (CEL_UNLIKELY(rhs_iter == cel_nullptr)) { - CEL_ASSERT(!cel_Status_Ok(status)); - return false; - } - size_t rhs_size; - if (cel_MapValueIterator_Remaining(rhs_iter, &rhs_size)) { - if (rhs_size != lhs_size) { - cel_Value_SetFalse(result); - cel_MapValueIterator_Delete(rhs_iter); - return true; - } - if (rhs_size == 0) { - cel_Value_SetTrue(result); - cel_MapValueIterator_Delete(rhs_iter); - return true; - } - } - rhs_size = 0; - bool ok = true; - while (true) { - cel_Value rhs_key; - cel_Value rhs_value; - cel_MapValueKey lhs_key; - cel_Value lhs_value; - if (!cel_MapValueIterator_Next2(rhs_iter, context, &rhs_key, &rhs_value, - status)) { - if (!cel_Status_Ok(status)) { - ok = false; - break; - } - cel_Value_SetBool(result, rhs_size == lhs_size); - break; - } - ++rhs_size; - if (cel_Value_IsError(&rhs_key) || cel_Value_IsError(&rhs_value)) { - cel_Value_SetFalse(result); - ok = false; - break; - } - _cel_MapValueKey_SetValue(&lhs_key, &rhs_key); - if (cel_MapValue_Find(lhs, context, &lhs_key, &lhs_value, status)) { - if (!cel_Value_Equals(&rhs_value, context, &lhs_value, result, status)) { - ok = cel_Status_Ok(status); - if (ok) { - cel_Value_SetFalse(result); - } - break; - } - } else { - ok = cel_Status_Ok(status); - if (ok) { - cel_Value_SetFalse(result); - } - break; - } - } - cel_MapValueIterator_Delete(rhs_iter); - return ok; -} - -static bool _cel_MapValue_EqualsSlow( - const cel_MapValue* cel_nonnull lhs, - const cel_ValueContext* cel_nonnull context, - const cel_MapValue* cel_nonnull rhs, cel_Value* cel_nonnull result, - cel_Status* cel_nonnull status) { - cel_MapValueIterator* lhs_iter = - cel_MapValue_NewIterator(lhs, context, status); - if (CEL_UNLIKELY(lhs_iter == cel_nullptr)) { - CEL_ASSERT(!cel_Status_Ok(status)); - return false; - } - cel_MapValueIterator* rhs_iter = - cel_MapValue_NewIterator(rhs, context, status); - if (CEL_UNLIKELY(rhs_iter == cel_nullptr)) { - CEL_ASSERT(!cel_Status_Ok(status)); - cel_MapValueIterator_Delete(lhs_iter); - return false; - } - size_t lhs_size; - size_t rhs_size; - bool lhs_has_size; - bool rhs_has_size; - lhs_has_size = cel_MapValueIterator_Remaining(lhs_iter, &lhs_size); - rhs_has_size = cel_MapValueIterator_Remaining(rhs_iter, &rhs_size); - if (lhs_has_size && rhs_has_size) { - if (lhs_size != rhs_size) { - cel_Value_SetFalse(result); - cel_MapValueIterator_Delete(rhs_iter); - cel_MapValueIterator_Delete(lhs_iter); - return true; - } - if (lhs_size == 0) { - cel_Value_SetTrue(result); - cel_MapValueIterator_Delete(rhs_iter); - cel_MapValueIterator_Delete(lhs_iter); - return true; - } - } - _cel_Array(_cel_MapValueEntry) lhs_entries; - _cel_Array(_cel_MapValueEntry) rhs_entries; - _cel_Array_Construct(&lhs_entries); - if (lhs_has_size) { - _cel_Array_Reserve(&lhs_entries, context->alloc, lhs_size); - } - _cel_Array_Construct(&rhs_entries); - if (rhs_has_size) { - _cel_Array_Reserve(&rhs_entries, context->alloc, rhs_size); - } - bool ok = true; - bool lhs_next = true; - bool rhs_next = true; - while (true) { - if (lhs_next) { - _cel_MapValueEntry lhs_entry; - lhs_next = cel_MapValueIterator_Next(lhs_iter, context, &lhs_entry.key, - &lhs_entry.value, status); - if (!lhs_next && !cel_Status_Ok(status)) { - ok = false; - break; - } - if (lhs_next) { - _cel_MapValueEntry* lhs_entry_ptr = - _cel_Array_Push(&lhs_entries, context->alloc); - if (CEL_UNLIKELY(lhs_entry_ptr == cel_nullptr)) { - cel_OutOfMemoryStatus(status); - ok = false; - break; - } - *lhs_entry_ptr = lhs_entry; - } - } - if (rhs_next) { - _cel_MapValueEntry rhs_entry; - rhs_next = cel_MapValueIterator_Next(rhs_iter, context, &rhs_entry.key, - &rhs_entry.value, status); - if (!rhs_next && !cel_Status_Ok(status)) { - ok = false; - break; - } - if (rhs_next) { - _cel_MapValueEntry* rhs_entry_ptr = - _cel_Array_Push(&rhs_entries, context->alloc); - if (CEL_UNLIKELY(rhs_entry_ptr == cel_nullptr)) { - cel_OutOfMemoryStatus(status); - ok = false; - break; - } - *rhs_entry_ptr = rhs_entry; - } - } - if (!lhs_next || !rhs_next) { - break; - } - } - if (ok) { - if (lhs_next || rhs_next) { - cel_Value_SetFalse(result); - } else { - const size_t lhs_entries_size = _cel_Array_Size(&lhs_entries); - const size_t rhs_entries_size = _cel_Array_Size(&rhs_entries); - if (lhs_entries_size != rhs_entries_size) { - cel_Value_SetFalse(result); - } else { - _cel_MapValueEntry* lhs_entries_data = - _cel_Array_MutableData(&lhs_entries); - _cel_MapValueEntry* rhs_entries_data = - _cel_Array_MutableData(&rhs_entries); - _cel_Sort(lhs_entries_data, lhs_entries_size, - sizeof(_cel_MapValueEntry), &_cel_MapValueEntry_Compare); - _cel_Sort(rhs_entries_data, rhs_entries_size, - sizeof(_cel_MapValueEntry), &_cel_MapValueEntry_Compare); - for (size_t i = 0; i < lhs_entries_size; ++i) { - if (!_cel_MapValueKey_Equals(&lhs_entries_data[i].key, - &rhs_entries_data[i].key)) { - cel_Value_SetFalse(result); - goto done; - } - if (!cel_Value_Equals(&lhs_entries_data[i].value, context, - &rhs_entries_data[i].value, result, status)) { - ok = false; - goto done; - } - if (!cel_Value_IsTrue(result)) { - cel_Value_SetFalse(result); - goto done; - } - } - cel_Value_SetTrue(result); - } - } - } -done: - _cel_Array_Destruct(&rhs_entries, context->alloc); - _cel_Array_Destruct(&lhs_entries, context->alloc); - cel_MapValueIterator_Delete(rhs_iter); - cel_MapValueIterator_Delete(lhs_iter); - return ok; -} - -bool cel_MapValue_Equals(const cel_MapValue* cel_nonnull map_value, - const cel_ValueContext* cel_nonnull context, - const cel_MapValue* cel_nonnull other, - cel_Value* cel_nonnull result, - cel_Status* cel_nonnull status) { - CEL_ASSERT_NOT_NULL(map_value); - CEL_ASSERT_NOT_NULL(context); - CEL_ASSERT_NOT_NULL(other); - CEL_ASSERT_NOT_NULL(result); - CEL_ASSERT_NOT_NULL(status); - - if (CEL_UNLIKELY(!cel_Status_Ok(status))) { - return false; - } - - if (map_value->vtable->Equals != cel_nullptr) { - if ((*map_value->vtable->Equals)(map_value->vtable, map_value->content, - context, other, result, status)) { - return true; - } - if (CEL_UNLIKELY(!cel_Status_Ok(status))) { - return false; - } - } - if (other->vtable->Equals != cel_nullptr && - other->vtable->Equals != map_value->vtable->Equals) { - if ((*other->vtable->Equals)(other->vtable, other->content, context, - map_value, result, status)) { - return true; - } - if (CEL_UNLIKELY(!cel_Status_Ok(status))) { - return false; - } - } - size_t lhs_size; - size_t rhs_size; - bool lhs_has_size; - bool rhs_has_size; - if (map_value->vtable->FastSize != cel_nullptr) { - lhs_has_size = (*map_value->vtable->FastSize)( - map_value->vtable, map_value->content, &lhs_size); - } else { - lhs_has_size = false; - } - if (other->vtable->FastSize != cel_nullptr) { - rhs_has_size = - (*other->vtable->FastSize)(other->vtable, other->content, &rhs_size); - } else { - rhs_has_size = false; - } - if (lhs_has_size && rhs_has_size) { - return _cel_MapValue_EqualsFast(map_value, lhs_size, context, other, - rhs_size, result, status); - } - // Unfortunately one or both of the map values does not know its size in - // constant time. We have no choice but to collect the key value pairs into - // arrays, sort, and then compare. - if (lhs_has_size) { - return _cel_MapValue_EqualsSlowWithSize(map_value, lhs_size, context, other, - result, status); - } - if (rhs_has_size) { - return _cel_MapValue_EqualsSlowWithSize(other, rhs_size, context, map_value, - result, status); - } - return _cel_MapValue_EqualsSlow(map_value, context, other, result, status); -} diff --git a/cel-c/src/memory.c b/cel-c/src/memory.c deleted file mode 100644 index 8ef4c74..0000000 --- a/cel-c/src/memory.c +++ /dev/null @@ -1,169 +0,0 @@ -// Copyright 2024 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "cel-c/src/memory.h" - -#include // IWYU pragma: keep -#include -#include - -#include "cel-c/assert.h" -#include "cel-c/src/config.h" - -// It is hard to exhaustively detect the presence of `memrchr` as it's a GNU -// extension which has been implemented on more than just GNU/Linux, such as -// FreeBSD. Instead we define a implementation of memrchr ourselves. On -// platforms that have weak symbols, we mark our implementation as weak so if -// the platform libc has `memrchr` the linker will select the one from libc. On -// other platforms, we mark are implementation static inline so it is private. -#if _CEL_HAVE_ATTRIBUTE_WEAK -_CEL_ATTRIBUTE_WEAK CEL_EXTERN -#else -static inline -#endif - void* - memrchr(const void* b, int c, size_t len) { - if (len > 0) { - const unsigned char* p = ((const unsigned char*)b) + len; - do { - --p; - if (*p == (unsigned char)c) { - return (void*)p; - } - --len; - } while (len > 0); - } - return cel_nullptr; -} - -bool _cel_Memory_Equals(CEL_NULLABLE(const void*) lhs_data, size_t lhs_size, - CEL_NULLABLE(const void*) rhs_data, size_t rhs_size) { - CEL_ASSERT(lhs_size == 0 || lhs_data != cel_nullptr); - CEL_ASSERT(rhs_size == 0 || rhs_data != cel_nullptr); - return lhs_size == rhs_size && (lhs_size == 0 || lhs_data == rhs_data || - memcmp(lhs_data, rhs_data, lhs_size) == 0); -} - -int _cel_Memory_Compare(CEL_NULLABLE(const void*) lhs_data, size_t lhs_size, - CEL_NULLABLE(const void*) rhs_data, size_t rhs_size) { - CEL_ASSERT(lhs_size == 0 || lhs_data != cel_nullptr); - CEL_ASSERT(rhs_size == 0 || rhs_data != cel_nullptr); - int cmp = lhs_data != rhs_data - ? memcmp(lhs_data, rhs_data, - lhs_size < rhs_size ? lhs_size : rhs_size) - : 0; - if (cmp == 0) { - cmp = lhs_size < rhs_size ? -1 : lhs_size > rhs_size ? 1 : 0; - } - return cmp; -} - -bool _cel_Memory_StartsWith(CEL_NULLABLE(const void*) hay_data, size_t hay_size, - CEL_NULLABLE(const void*) ndl_data, - size_t ndl_size) { - CEL_ASSERT(hay_size == 0 || hay_data != cel_nullptr); - CEL_ASSERT(ndl_size == 0 || ndl_data != cel_nullptr); - return hay_size >= ndl_size && memcmp(hay_data, ndl_data, ndl_size) == 0; -} - -bool _cel_Memory_EndsWith(CEL_NULLABLE(const void*) hay_data, size_t hay_size, - CEL_NULLABLE(const void*) ndl_data, size_t ndl_size) { - CEL_ASSERT(hay_size == 0 || hay_data != cel_nullptr); - CEL_ASSERT(ndl_size == 0 || ndl_data != cel_nullptr); - return hay_size >= ndl_size && - memcmp(((CEL_NULLABLE(const char*))hay_data) + (hay_size - ndl_size), - ndl_data, ndl_size) == 0; -} - -CEL_NULLABLE(void*) -_cel_Memory_FindFirst(CEL_NULLABLE(const void*) hay_data, size_t hay_size, - CEL_NULLABLE(const void*) ndl_data, size_t ndl_size) { - CEL_ASSERT(hay_size == 0 || hay_data != cel_nullptr); - CEL_ASSERT(ndl_size == 0 || ndl_data != cel_nullptr); - if (CEL_UNLIKELY(ndl_size == 0)) { - return (CEL_NULLABLE(void*))hay_data; - } - if (ndl_size > hay_size) { - return cel_nullptr; - } - if (CEL_UNLIKELY(hay_data == ndl_data)) { - CEL_ASSERT_GE(hay_size, ndl_size); - return (CEL_NULLABLE(void*))hay_data; - } - if (hay_size > ndl_size) { - const unsigned char ndl_front = - *((CEL_NONNULL(const unsigned char*))ndl_data); - do { - CEL_NULLABLE(char*) - hay_next = (CEL_NULLABLE(char*))memchr(hay_data, ndl_front, - (hay_size - ndl_size) + 1); - if (hay_next == cel_nullptr) { - return cel_nullptr; - } - if (memcmp(hay_next + 1, ((CEL_NONNULL(char*))ndl_data) + 1, - ndl_size - 1) == 0) { - return hay_next; - } - size_t skip = (hay_next - ((CEL_NONNULL(const char*))hay_data)) + 1; - hay_data = ((CEL_NONNULL(const char*))hay_data) + skip; - hay_size -= skip; - } while (hay_size > ndl_size); - } - CEL_ASSERT_LE(hay_size, ndl_size); - if (hay_size == ndl_size) { - return memcmp(hay_data, ndl_data, ndl_size) == 0 - ? (CEL_NULLABLE(void*))hay_data - : (CEL_NULLABLE(void*))cel_nullptr; - } - return cel_nullptr; -} - -CEL_NULLABLE(void*) -_cel_Memory_FindLast(CEL_NULLABLE(const void*) hay_data, size_t hay_size, - CEL_NULLABLE(const void*) ndl_data, size_t ndl_size) { - CEL_ASSERT(hay_size == 0 || hay_data != cel_nullptr); - CEL_ASSERT(ndl_size == 0 || ndl_data != cel_nullptr); - if (CEL_UNLIKELY(ndl_size == 0)) { - return (CEL_NULLABLE(void*))(((CEL_NULLABLE(const char*))hay_data)); - } - if (ndl_size > hay_size) { - return cel_nullptr; - } - if (hay_size > ndl_size) { - const unsigned char ndl_front = - *((CEL_NONNULL(const unsigned char*))ndl_data); - do { - const size_t hay_lim = (hay_size - ndl_size) + 1; - CEL_NULLABLE(char*) - hay_prev = (CEL_NULLABLE(char*))memrchr(hay_data, ndl_front, hay_lim); - if (hay_prev == cel_nullptr) { - return cel_nullptr; - } - if (memcmp(hay_prev + 1, ((CEL_NONNULL(char*))ndl_data) + 1, - ndl_size - 1) == 0) { - return hay_prev; - } - size_t skip = - ((((CEL_NULLABLE(const char*))hay_data) + hay_lim) - hay_prev) + 1; - hay_size -= skip; - } while (hay_size > ndl_size); - } - CEL_ASSERT_LE(hay_size, ndl_size); - if (hay_size == ndl_size) { - return memcmp(hay_data, ndl_data, ndl_size) == 0 - ? (CEL_NULLABLE(void*))hay_data - : (CEL_NULLABLE(void*))cel_nullptr; - } - return cel_nullptr; -} diff --git a/cel-c/src/message_equality.c b/cel-c/src/message_equality.c deleted file mode 100644 index 9c391f1..0000000 --- a/cel-c/src/message_equality.c +++ /dev/null @@ -1,1342 +0,0 @@ -// Copyright 2025 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "cel-c/src/message_equality.h" - -#include -#include -#include - -#include "cel-c/alloc.h" -#include "cel-c/arena.h" -#include "cel-c/assert.h" -#include "cel-c/config.h" -#include "cel-c/string_view.h" -#include "cel-c/well_known_types.h" -#include "cel-c/src/any.h" -#include "cel-c/src/number.h" -#include "cel-c/src/setjmp.h" -#include "upb/base/descriptor_constants.h" -#include "upb/base/string_view.h" -#include "upb/message/array.h" -#include "upb/message/map.h" -#include "upb/message/message.h" -#include "upb/reflection/def.h" -#include "upb/reflection/message.h" -#include "upb/wire/eps_copy_input_stream.h" -#include "upb/wire/reader.h" -#include "upb/wire/types.h" - -typedef struct _cel_UnknownField _cel_UnknownField; -typedef struct _cel_UnknownFields _cel_UnknownFields; - -struct _cel_UnknownFields { - _cel_UnknownField* cel_nullable head; - _cel_UnknownField* cel_nullable tail; - _cel_UnknownField* cel_nullable mid; - uint32_t size; - int32_t balance; -}; - -struct _cel_UnknownField { - _cel_UnknownField* cel_nullable prev; - _cel_UnknownField* cel_nullable next; -#ifdef _MSC_VER -#pragma pack(push, 4) -#endif - union CEL_ATTRIBUTE_PACKED(4) { - uint64_t varint; - uint64_t fixed64; - uint32_t fixed32; - struct CEL_ATTRIBUTE_PACKED(4) { - const char* cel_nullability_unknown data; - uint32_t size; - } delimited; - _cel_UnknownFields* cel_nullable group; - } data; -#ifdef _MSC_VER -#pragma pack(pop) -#endif - uint32_t field_num : 29; - uint8_t wire_type : 3; -}; - -typedef struct { - const upb_DefPool* const cel_nonnull def_pool; - const cel_WellKnownTypes* const cel_nonnull wkts; - cel_Allocator* const cel_nonnull alloc; - cel_Arena* cel_nullable arena; - upb_EpsCopyInputStream stream; - _cel_MessageEquality result; - int depth; - _cel_jmp_buf jmp; -} _cel_MessageEqualityState; - -CEL_ATTRIBUTE_NORETURN -static void _cel_MessageEqualityState_Throw( - _cel_MessageEqualityState* cel_nonnull state, _cel_MessageEquality result) { - CEL_ASSERT_NE(result, _cel_MessageEquality_kEqual); - CEL_ASSERT_NE(result, _cel_MessageEquality_kNotEqual); - - state->result = result; - _cel_longjmp(state->jmp); -} - -CEL_ATTRIBUTE_NODISCARD -static cel_Arena* cel_nonnull -_cel_MessageEqualityState_Arena(_cel_MessageEqualityState* cel_nonnull state) { - cel_Arena* arena = state->arena; - if (arena == cel_nullptr) { - arena = state->arena = cel_Arena_New(state->alloc); - if (CEL_UNLIKELY(arena == cel_nullptr)) { - _cel_MessageEqualityState_Throw(state, _cel_MessageEquality_kOutOfMemory); - } - } - return arena; -} - -CEL_ATTRIBUTE_NODISCARD -static _cel_UnknownFields* cel_nonnull -_cel_UnknownFields_New(_cel_MessageEqualityState* cel_nonnull state) { - _cel_UnknownFields* fields = - cel_Arena_Malloc(_cel_MessageEqualityState_Arena(state), - sizeof(_cel_UnknownFields), cel_nullptr); - if (CEL_UNLIKELY(fields == cel_nullptr)) { - _cel_MessageEqualityState_Throw(state, _cel_MessageEquality_kOutOfMemory); - } - fields->head = cel_nullptr; - fields->tail = cel_nullptr; - fields->mid = cel_nullptr; - fields->size = 0; - fields->balance = 0; - return fields; -} - -CEL_ATTRIBUTE_NODISCARD -static _cel_UnknownField* cel_nonnull _cel_UnknownField_New( - _cel_MessageEqualityState* cel_nonnull state, uint32_t tag) { - _cel_UnknownField* field = - cel_Arena_Malloc(_cel_MessageEqualityState_Arena(state), - sizeof(_cel_UnknownField), cel_nullptr); - if (CEL_UNLIKELY(field == cel_nullptr)) { - _cel_MessageEqualityState_Throw(state, _cel_MessageEquality_kOutOfMemory); - } - field->prev = cel_nullptr; - field->next = cel_nullptr; - field->field_num = upb_WireReader_GetFieldNumber(tag); - field->wire_type = upb_WireReader_GetWireType(tag); - return field; -} - -CEL_ATTRIBUTE_NODISCARD -static int _cel_UnknownField_Compare(const _cel_UnknownField* cel_nonnull lhs, - const _cel_UnknownField* cel_nonnull rhs) { - const uint32_t lhs_field_num = lhs->field_num; - const uint32_t rhs_field_num = rhs->field_num; - if (lhs_field_num < rhs_field_num) { - return -1; - } - if (lhs_field_num > rhs_field_num) { - return 1; - } - const uint8_t lhs_wire_type = lhs->wire_type; - const uint8_t rhs_wire_type = rhs->wire_type; - return lhs_wire_type < rhs_wire_type ? -1 - : lhs_wire_type > rhs_wire_type ? 1 - : 0; -} - -static void _cel_UnknownFields_Add(_cel_UnknownFields* cel_nonnull fields, - _cel_UnknownField* cel_nonnull field) { - if (fields->tail != cel_nullptr) { - _cel_UnknownField* tail = fields->tail; - if (_cel_UnknownField_Compare(field, tail) >= 0) { - // Fast path. Fields are in order already. - field->prev = tail; - tail->next = field; - fields->tail = field; - ++fields->balance; - } else { - // Slow path. - _cel_UnknownField* node = fields->mid; - CEL_ASSERT_NOT_NULL(node); - while (_cel_UnknownField_Compare(field, node) < 0) { - node = node->prev; - if (node == cel_nullptr) { - field->next = fields->head; - fields->head->prev = field; - fields->head = field; - goto inserted; - } - CEL_ASSERT_NOT_NULL(node); - } - CEL_ASSERT_NOT_NULL(node); - while (_cel_UnknownField_Compare(field, node) >= 0) { - node = node->next; - CEL_ASSERT_NOT_NULL(node); - } - field->next = node; - field->prev = node->prev; - if (node->prev != cel_nullptr) { - node->prev->next = field; - node->prev = field; - } else { - fields->head = field; - } - } - inserted: - fields->balance += _cel_UnknownField_Compare(field, fields->mid); - } else { - fields->head = fields->mid = fields->tail = field; - } - ++fields->size; - if (fields->size > 2 && (fields->size & 1) == 1) { - if (fields->balance < 0) { - fields->mid = fields->mid->prev; - } else if (fields->balance > 0) { - fields->mid = fields->mid->next; - } - fields->balance = 0; - } -} - -CEL_ATTRIBUTE_NODISCARD -static _cel_UnknownFields* cel_nullable -_cel_UnknownFields_Read(_cel_MessageEqualityState* cel_nonnull state, - _cel_UnknownFields* fields, const char** buf) { - const char* ptr = *buf; - while (!upb_EpsCopyInputStream_IsDone(&state->stream, &ptr)) { - uint32_t tag; - ptr = upb_WireReader_ReadTag(ptr, &tag, &state->stream); - uint8_t wire_type = upb_WireReader_GetWireType(tag); - if (wire_type == kUpb_WireType_EndGroup) { - break; - } - if (CEL_UNLIKELY(fields == cel_nullptr)) { - fields = _cel_UnknownFields_New(state); - } - _cel_UnknownField* field = _cel_UnknownField_New(state, tag); - switch (wire_type) { - case kUpb_WireType_Varint: - ptr = - upb_WireReader_ReadVarint(ptr, &field->data.varint, &state->stream); - break; - case kUpb_WireType_64Bit: - ptr = upb_WireReader_ReadFixed64(ptr, &field->data.fixed64, - &state->stream); - break; - case kUpb_WireType_32Bit: - ptr = upb_WireReader_ReadFixed32(ptr, &field->data.fixed32, - &state->stream); - break; - case kUpb_WireType_Delimited: { - int size; - upb_StringView sv; - ptr = upb_WireReader_ReadSize(ptr, &size, &state->stream); - ptr = upb_EpsCopyInputStream_ReadStringAlwaysAlias( - &state->stream, ptr, size, &sv); - field->data.delimited.data = sv.data; - field->data.delimited.size = sv.size; - } break; - case kUpb_WireType_StartGroup: - CEL_ASSERT_GT(state->depth, 0); - if (--state->depth == 0) { - _cel_MessageEqualityState_Throw( - state, _cel_MessageEquality_kMaxDepthExceeded); - } - field->data.group = _cel_UnknownFields_Read(state, cel_nullptr, &ptr); - ++state->depth; - break; - default: - CEL_UNREACHABLE(); - } - _cel_UnknownFields_Add(fields, field); - } - *buf = ptr; - return fields; -} - -CEL_ATTRIBUTE_NODISCARD -static _cel_UnknownFields* cel_nullable -_cel_UnknownFields_FromMessage(_cel_MessageEqualityState* cel_nonnull state, - const upb_Message* cel_nonnull msg) { - _cel_UnknownFields* fields = cel_nullptr; - cel_StringView unknown; - uintptr_t iter = kUpb_Message_UnknownBegin; - while (upb_Message_NextUnknown(msg, &unknown, &iter)) { - upb_EpsCopyInputStream_Init(&state->stream, &unknown.data, - cel_StringView_Size(unknown)); - fields = _cel_UnknownFields_Read(state, fields, &unknown.data); - CEL_ASSERT(upb_EpsCopyInputStream_IsDone(&state->stream, &unknown.data) && - !upb_EpsCopyInputStream_IsError(&state->stream)); - } - return fields; -} - -CEL_ATTRIBUTE_NODISCARD -static bool _cel_UnknownFields_Equals( - _cel_MessageEqualityState* cel_nonnull state, - const _cel_UnknownFields* cel_nullable lhs_fields, - const _cel_UnknownFields* cel_nullable rhs_fields) { - const size_t lhs_fields_size = - lhs_fields != cel_nullptr ? lhs_fields->size : 0; - const size_t rhs_fields_size = - rhs_fields != cel_nullptr ? rhs_fields->size : 0; - if (lhs_fields_size != rhs_fields_size) { - return false; - } - if (lhs_fields_size == 0) { - return true; - } - - const _cel_UnknownField* lhs_field = lhs_fields->head; - const _cel_UnknownField* rhs_field = rhs_fields->head; - for (size_t i = 0; i < lhs_fields_size; - ++i, lhs_field = lhs_field->next, rhs_field = rhs_field->next) { - if (lhs_field->field_num != rhs_field->field_num || - lhs_field->wire_type != rhs_field->wire_type) { - return false; - } - switch (lhs_field->wire_type) { - case kUpb_WireType_Varint: - if (lhs_field->data.varint != rhs_field->data.varint) { - return false; - } - break; - case kUpb_WireType_64Bit: - if (lhs_field->data.fixed64 != rhs_field->data.fixed64) { - return false; - } - break; - case kUpb_WireType_32Bit: - if (lhs_field->data.fixed32 != rhs_field->data.fixed32) { - return false; - } - break; - case kUpb_WireType_Delimited: - if (!cel_StringView_Equals( - cel_StringView_FromArray(lhs_field->data.delimited.data, - lhs_field->data.delimited.size), - cel_StringView_FromArray(rhs_field->data.delimited.data, - rhs_field->data.delimited.size))) { - return false; - } - break; - case kUpb_WireType_StartGroup: - if (!_cel_UnknownFields_Equals(state, lhs_field->data.group, - rhs_field->data.group)) { - return false; - } - break; - default: - CEL_UNREACHABLE(); - } - } - return true; -} - -CEL_ATTRIBUTE_NODISCARD -static bool _cel_MessageEqualityState_UnknownEquals( - _cel_MessageEqualityState* cel_nonnull state, - const upb_Message* cel_nonnull lhs, const upb_Message* cel_nonnull rhs) { - const bool lhs_has_unknown = upb_Message_HasUnknown(lhs); - const bool rhs_has_unknown = upb_Message_HasUnknown(rhs); - if (!lhs_has_unknown && !rhs_has_unknown) { - return true; - } - if (!(lhs_has_unknown && rhs_has_unknown)) { - return false; - } - - _cel_UnknownFields* lhs_fields = _cel_UnknownFields_FromMessage(state, lhs); - _cel_UnknownFields* rhs_fields = _cel_UnknownFields_FromMessage(state, rhs); - return _cel_UnknownFields_Equals(state, lhs_fields, rhs_fields); -} - -CEL_ATTRIBUTE_NODISCARD -static bool _cel_MessageEqualityState_FieldHomoEquals( - _cel_MessageEqualityState* cel_nonnull state, upb_MessageValue lhs_val, - upb_MessageValue rhs_val, const upb_FieldDef* cel_nonnull val_def); - -CEL_ATTRIBUTE_NODISCARD -static bool _cel_MessageEqualityState_HomoEquals( - _cel_MessageEqualityState* cel_nonnull state, - const upb_Message* cel_nonnull lhs_val, - const upb_Message* cel_nonnull rhs_val, - const upb_MessageDef* cel_nonnull val_def) { - if (lhs_val == rhs_val) { - return true; - } - - const upb_FieldDef* lhs_field_def; - const upb_FieldDef* rhs_field_def; - upb_MessageValue lhs_field_val; - upb_MessageValue rhs_field_val; - size_t lhs_iter = kUpb_Message_Begin; - size_t rhs_iter = kUpb_Message_Begin; - while (true) { - bool lhs_has_next = - upb_Message_Next(lhs_val, val_def, state->def_pool, &lhs_field_def, - &lhs_field_val, &lhs_iter); - bool rhs_has_next = - upb_Message_Next(rhs_val, val_def, state->def_pool, &rhs_field_def, - &rhs_field_val, &rhs_iter); - if (lhs_has_next != rhs_has_next) { - return false; - } - if (!lhs_has_next) { - break; - } - if (lhs_field_def != rhs_field_def) { - return false; - } - if (!_cel_MessageEqualityState_FieldHomoEquals( - state, lhs_field_val, rhs_field_val, rhs_field_def)) { - return false; - } - } - - return _cel_MessageEqualityState_UnknownEquals(state, lhs_val, rhs_val); -} - -CEL_ATTRIBUTE_NODISCARD -static bool _cel_MessageEqualityState_SingularFieldHomoEquals( - _cel_MessageEqualityState* cel_nonnull state, upb_MessageValue lhs_val, - upb_MessageValue rhs_val, const upb_FieldDef* cel_nonnull val_def) { - CEL_ASSERT_NOT(upb_FieldDef_IsMap(val_def)); - - switch (upb_FieldDef_CType(val_def)) { - case kUpb_CType_Bool: - return lhs_val.bool_val == rhs_val.bool_val; - case kUpb_CType_Float: - return lhs_val.float_val == rhs_val.float_val; - case kUpb_CType_Enum: - CEL_ATTRIBUTE_FALLTHROUGH; - case kUpb_CType_Int32: - return lhs_val.int32_val == rhs_val.int32_val; - case kUpb_CType_UInt32: - return lhs_val.uint32_val == rhs_val.uint32_val; - case kUpb_CType_Message: - return _cel_MessageEqualityState_HomoEquals( - state, lhs_val.msg_val, rhs_val.msg_val, - upb_FieldDef_MessageSubDef(val_def)); - case kUpb_CType_Double: - return lhs_val.double_val == rhs_val.double_val; - case kUpb_CType_Int64: - return lhs_val.int64_val == rhs_val.int64_val; - case kUpb_CType_UInt64: - return lhs_val.uint64_val == rhs_val.uint64_val; - case kUpb_CType_String: - CEL_ATTRIBUTE_FALLTHROUGH; - case kUpb_CType_Bytes: - return cel_StringView_Equals(lhs_val.str_val, rhs_val.str_val); - default: - CEL_UNREACHABLE(); - } -} - -CEL_ATTRIBUTE_NODISCARD -static bool _cel_MessageEqualityState_MapFieldHomoEquals( - _cel_MessageEqualityState* cel_nonnull state, - const upb_Map* cel_nullable lhs_val, const upb_Map* cel_nullable rhs_val, - const upb_FieldDef* cel_nonnull val_def) { - const size_t lhs_val_size = - lhs_val != cel_nullptr ? upb_Map_Size(lhs_val) : 0; - const size_t rhs_val_size = - rhs_val != cel_nullptr ? upb_Map_Size(rhs_val) : 0; - - if (lhs_val_size != rhs_val_size) { - return false; - } - - if (lhs_val_size == 0) { - return true; - } - - const upb_MessageDef* val_entry_def = upb_FieldDef_MessageSubDef(val_def); - const upb_FieldDef* val_value_def = upb_MessageDef_FindFieldByNumber( - val_entry_def, kUpb_MapEntry_ValueFieldNumber); - - size_t lhs_iter = kUpb_Map_Begin; - upb_MessageValue lhs_val_key; - upb_MessageValue lhs_val_value; - while (upb_Map_Next(lhs_val, &lhs_val_key, &lhs_val_value, &lhs_iter)) { - upb_MessageValue rhs_val_value; - if (!upb_Map_Get(rhs_val, lhs_val_key, &rhs_val_value)) { - return false; - } - if (!_cel_MessageEqualityState_SingularFieldHomoEquals( - state, lhs_val_value, rhs_val_value, val_value_def)) { - return false; - } - } - return true; -} - -CEL_ATTRIBUTE_NODISCARD -static bool _cel_MessageEqualityState_RepeatedFieldHomoEquals( - _cel_MessageEqualityState* cel_nonnull state, - const upb_Array* cel_nullable lhs_val, - const upb_Array* cel_nullable rhs_val, - const upb_FieldDef* cel_nonnull val_def) { - const size_t lhs_val_size = - lhs_val != cel_nullptr ? upb_Array_Size(lhs_val) : 0; - const size_t rhs_val_size = - rhs_val != cel_nullptr ? upb_Array_Size(rhs_val) : 0; - - if (lhs_val_size != rhs_val_size) { - return false; - } - - if (lhs_val_size == 0) { - return true; - } - - for (size_t i = 0; i < lhs_val_size; ++i) { - if (!_cel_MessageEqualityState_SingularFieldHomoEquals( - state, upb_Array_Get(lhs_val, i), upb_Array_Get(rhs_val, i), - val_def)) { - return false; - } - } - return true; -} - -CEL_ATTRIBUTE_NODISCARD -static bool _cel_MessageEqualityState_FieldHomoEquals( - _cel_MessageEqualityState* cel_nonnull state, upb_MessageValue lhs_val, - upb_MessageValue rhs_val, const upb_FieldDef* cel_nonnull val_def) { - if (upb_FieldDef_IsMap(val_def)) { - return _cel_MessageEqualityState_MapFieldHomoEquals( - state, lhs_val.map_val, rhs_val.map_val, val_def); - } - if (upb_FieldDef_IsRepeated(val_def)) { - return _cel_MessageEqualityState_RepeatedFieldHomoEquals( - state, lhs_val.array_val, rhs_val.array_val, val_def); - } - return _cel_MessageEqualityState_SingularFieldHomoEquals(state, lhs_val, - rhs_val, val_def); -} - -typedef enum CEL_ATTRIBUTE_CLOSED_ENUM { - _cel_MessageEqualityFieldKind_kScalar = 1, - _cel_MessageEqualityFieldKind_kMessage, - _cel_MessageEqualityFieldKind_kNullValue, - _cel_MessageEqualityFieldKind_kRepeated, - _cel_MessageEqualityFieldKind_kMap, -} _cel_MessageEqualityFieldKind; - -typedef enum CEL_ATTRIBUTE_CLOSED_ENUM { - _cel_MessageEqualityScalarFieldKind_kBool = 1, - _cel_MessageEqualityScalarFieldKind_kNumber, - _cel_MessageEqualityScalarFieldKind_kString, - _cel_MessageEqualityScalarFieldKind_kBytes, -} _cel_MessageEqualityScalarFieldKind; - -typedef struct { - struct { - union { - _cel_MessageEqualityScalarFieldKind scalar_def; - const upb_MessageDef* message_def; - const upb_FieldDef* field_def; - } def; - union { - bool bool_val; - _cel_Number num_val; - cel_StringView str_val; - const upb_Array* array_val; - const upb_Map* map_val; - const upb_Message* msg_val; - } val; - } data; - _cel_MessageEqualityFieldKind kind; -} _cel_MessageEqualityField; - -static void _cel_MessageEqualityState_Field( - _cel_MessageEqualityState* cel_nonnull state, upb_MessageValue in_val, - const upb_FieldDef* cel_nonnull in_def, bool single, - _cel_MessageEqualityField* cel_nonnull out) { - if (!single) { - if (upb_FieldDef_IsMap(in_def)) { - out->data.val.map_val = in_val.map_val; - out->data.def.field_def = in_def; - out->kind = _cel_MessageEqualityFieldKind_kMap; - return; - } - if (upb_FieldDef_IsRepeated(in_def)) { - out->data.val.array_val = in_val.array_val; - out->data.def.field_def = in_def; - out->kind = _cel_MessageEqualityFieldKind_kRepeated; - return; - } - } - switch (upb_FieldDef_CType(in_def)) { - case kUpb_CType_Bool: - out->data.def.scalar_def = _cel_MessageEqualityScalarFieldKind_kBool; - out->data.val.bool_val = in_val.bool_val; - out->kind = _cel_MessageEqualityFieldKind_kScalar; - break; - case kUpb_CType_Float: - out->data.def.scalar_def = _cel_MessageEqualityScalarFieldKind_kNumber; - out->data.val.num_val = _cel_DoubleNumber(in_val.float_val); - out->kind = _cel_MessageEqualityFieldKind_kScalar; - break; - case kUpb_CType_Int32: - out->data.def.scalar_def = _cel_MessageEqualityScalarFieldKind_kNumber; - out->data.val.num_val = _cel_IntNumber(in_val.int32_val); - out->kind = _cel_MessageEqualityFieldKind_kScalar; - break; - case kUpb_CType_UInt32: - out->data.def.scalar_def = _cel_MessageEqualityScalarFieldKind_kNumber; - out->data.val.num_val = _cel_UintNumber(in_val.uint32_val); - out->kind = _cel_MessageEqualityFieldKind_kScalar; - break; - case kUpb_CType_Enum: { - const upb_EnumDef* enum_def = upb_FieldDef_EnumSubDef(in_def); - const char* enum_def_name = upb_EnumDef_FullName(enum_def); - if (enum_def_name != cel_nullptr && - strcmp(enum_def_name, "google.protobuf.NullValue") == 0) { - out->kind = _cel_MessageEqualityFieldKind_kNullValue; - } else { - out->data.def.scalar_def = _cel_MessageEqualityScalarFieldKind_kNumber; - out->data.val.num_val = _cel_IntNumber(in_val.int32_val); - out->kind = _cel_MessageEqualityFieldKind_kScalar; - } - } break; - case kUpb_CType_Message: { - const upb_MessageDef* message_def = upb_FieldDef_MessageSubDef(in_def); - upb_WellKnown well_known = upb_MessageDef_WellKnownType(message_def); - if (well_known == kUpb_WellKnown_Any) { - CEL_ASSERT_EQ(message_def, state->wkts->any.def); - upb_Message* out_message; - const upb_MessageDef* out_message_def; - cel_Arena* arena = _cel_MessageEqualityState_Arena(state); - switch (_cel_AnyUnpack(in_val.msg_val, state->def_pool, - &state->wkts->any, arena, &out_message, - &out_message_def)) { - case _cel_AnyUnpackResult_kOk: - in_val.msg_val = out_message; - message_def = out_message_def; - well_known = upb_MessageDef_WellKnownType(message_def); - break; - case _cel_AnyUnpackResult_kOutOfMemory: - _cel_MessageEqualityState_Throw(state, - _cel_MessageEquality_kOutOfMemory); - default: - message_def = - out_message_def != cel_nullptr ? out_message_def : message_def; - in_val.msg_val = - out_message != cel_nullptr ? out_message : in_val.msg_val; - well_known = upb_MessageDef_WellKnownType(message_def); - break; - } - } - switch (well_known) { - case kUpb_WellKnown_DoubleValue: - CEL_ASSERT_EQ(message_def, state->wkts->double_value.def); - out->data.def.scalar_def = - _cel_MessageEqualityScalarFieldKind_kNumber; - out->data.val.num_val = _cel_DoubleNumber( - upb_Message_GetFieldByDef(in_val.msg_val, - state->wkts->double_value.value_def) - .double_val); - out->kind = _cel_MessageEqualityFieldKind_kScalar; - break; - case kUpb_WellKnown_FloatValue: - CEL_ASSERT_EQ(message_def, state->wkts->float_value.def); - out->data.def.scalar_def = - _cel_MessageEqualityScalarFieldKind_kNumber; - out->data.val.num_val = _cel_DoubleNumber( - upb_Message_GetFieldByDef(in_val.msg_val, - state->wkts->float_value.value_def) - .float_val); - out->kind = _cel_MessageEqualityFieldKind_kScalar; - break; - case kUpb_WellKnown_Int64Value: - CEL_ASSERT_EQ(message_def, state->wkts->int64_value.def); - out->data.def.scalar_def = - _cel_MessageEqualityScalarFieldKind_kNumber; - out->data.val.num_val = _cel_IntNumber( - upb_Message_GetFieldByDef(in_val.msg_val, - state->wkts->int64_value.value_def) - .int64_val); - out->kind = _cel_MessageEqualityFieldKind_kScalar; - break; - case kUpb_WellKnown_UInt64Value: - CEL_ASSERT_EQ(message_def, state->wkts->uint64_value.def); - out->data.def.scalar_def = - _cel_MessageEqualityScalarFieldKind_kNumber; - out->data.val.num_val = _cel_UintNumber( - upb_Message_GetFieldByDef(in_val.msg_val, - state->wkts->uint64_value.value_def) - .uint64_val); - out->kind = _cel_MessageEqualityFieldKind_kScalar; - break; - case kUpb_WellKnown_Int32Value: - CEL_ASSERT_EQ(message_def, state->wkts->int32_value.def); - out->data.def.scalar_def = - _cel_MessageEqualityScalarFieldKind_kNumber; - out->data.val.num_val = _cel_IntNumber( - upb_Message_GetFieldByDef(in_val.msg_val, - state->wkts->int32_value.value_def) - .int32_val); - out->kind = _cel_MessageEqualityFieldKind_kScalar; - break; - case kUpb_WellKnown_UInt32Value: - CEL_ASSERT_EQ(message_def, state->wkts->uint32_value.def); - out->data.def.scalar_def = - _cel_MessageEqualityScalarFieldKind_kNumber; - out->data.val.num_val = _cel_UintNumber( - upb_Message_GetFieldByDef(in_val.msg_val, - state->wkts->uint32_value.value_def) - .uint32_val); - out->kind = _cel_MessageEqualityFieldKind_kScalar; - break; - case kUpb_WellKnown_StringValue: - CEL_ASSERT_EQ(message_def, state->wkts->string_value.def); - out->data.def.scalar_def = - _cel_MessageEqualityScalarFieldKind_kString; - out->data.val.str_val = - upb_Message_GetFieldByDef(in_val.msg_val, - state->wkts->string_value.value_def) - .str_val; - out->kind = _cel_MessageEqualityFieldKind_kScalar; - break; - case kUpb_WellKnown_BytesValue: - CEL_ASSERT_EQ(message_def, state->wkts->bytes_value.def); - out->data.def.scalar_def = _cel_MessageEqualityScalarFieldKind_kBytes; - out->data.val.str_val = - upb_Message_GetFieldByDef(in_val.msg_val, - state->wkts->bytes_value.value_def) - .str_val; - out->kind = _cel_MessageEqualityFieldKind_kScalar; - break; - case kUpb_WellKnown_BoolValue: - CEL_ASSERT_EQ(message_def, state->wkts->bool_value.def); - out->data.def.scalar_def = _cel_MessageEqualityScalarFieldKind_kBool; - out->data.val.bool_val = - upb_Message_GetFieldByDef(in_val.msg_val, - state->wkts->bool_value.value_def) - .bool_val; - out->kind = _cel_MessageEqualityFieldKind_kScalar; - break; - case kUpb_WellKnown_Value: { - CEL_ASSERT_EQ(message_def, state->wkts->value.def); - const upb_FieldDef* field_def = upb_Message_WhichOneofByDef( - in_val.msg_val, state->wkts->value.kind_def); - if (field_def == cel_nullptr) { - out->kind = _cel_MessageEqualityFieldKind_kNullValue; - } else { - switch (upb_FieldDef_Number(field_def)) { - case 1: // null_value - out->kind = _cel_MessageEqualityFieldKind_kNullValue; - break; - case 2: // number_value - out->data.def.scalar_def = - _cel_MessageEqualityScalarFieldKind_kNumber; - out->data.val.num_val = _cel_DoubleNumber( - upb_Message_GetFieldByDef(in_val.msg_val, field_def) - .double_val); - out->kind = _cel_MessageEqualityFieldKind_kScalar; - break; - case 3: // string_value - out->data.def.scalar_def = - _cel_MessageEqualityScalarFieldKind_kString; - out->data.val.str_val = - upb_Message_GetFieldByDef(in_val.msg_val, field_def) - .str_val; - out->kind = _cel_MessageEqualityFieldKind_kScalar; - break; - case 4: // bool_value - out->data.def.scalar_def = - _cel_MessageEqualityScalarFieldKind_kBool; - out->data.val.bool_val = - upb_Message_GetFieldByDef(in_val.msg_val, field_def) - .bool_val; - out->kind = _cel_MessageEqualityFieldKind_kScalar; - break; - case 5: // struct_value - out->data.val.map_val = - upb_Message_GetFieldByDef( - upb_Message_GetFieldByDef(in_val.msg_val, field_def) - .msg_val, - state->wkts->struct_value.fields_def) - .map_val; - out->data.def.field_def = state->wkts->struct_value.fields_def; - out->kind = _cel_MessageEqualityFieldKind_kMap; - break; - case 6: // list_value - out->data.val.array_val = - upb_Message_GetFieldByDef( - upb_Message_GetFieldByDef(in_val.msg_val, field_def) - .msg_val, - state->wkts->list_value.values_def) - .array_val; - out->data.def.field_def = state->wkts->list_value.values_def; - out->kind = _cel_MessageEqualityFieldKind_kRepeated; - break; - default: - CEL_UNREACHABLE(); - } - } - } break; - case kUpb_WellKnown_ListValue: - CEL_ASSERT_EQ(message_def, state->wkts->list_value.def); - out->data.val.array_val = - upb_Message_GetFieldByDef(in_val.msg_val, - state->wkts->list_value.values_def) - .array_val; - out->data.def.field_def = state->wkts->list_value.values_def; - out->kind = _cel_MessageEqualityFieldKind_kRepeated; - break; - case kUpb_WellKnown_Struct: - CEL_ASSERT_EQ(message_def, state->wkts->struct_value.def); - out->data.val.map_val = - upb_Message_GetFieldByDef(in_val.msg_val, - state->wkts->struct_value.fields_def) - .map_val; - out->data.def.field_def = state->wkts->struct_value.fields_def; - out->kind = _cel_MessageEqualityFieldKind_kMap; - break; - default: - out->data.def.message_def = message_def; - out->data.val.msg_val = in_val.msg_val; - out->kind = _cel_MessageEqualityFieldKind_kMessage; - break; - } - } break; - case kUpb_CType_Double: - out->data.def.scalar_def = _cel_MessageEqualityScalarFieldKind_kNumber; - out->data.val.num_val = _cel_DoubleNumber(in_val.double_val); - out->kind = _cel_MessageEqualityFieldKind_kScalar; - break; - case kUpb_CType_Int64: - out->data.def.scalar_def = _cel_MessageEqualityScalarFieldKind_kNumber; - out->data.val.num_val = _cel_IntNumber(in_val.int64_val); - out->kind = _cel_MessageEqualityFieldKind_kScalar; - break; - case kUpb_CType_UInt64: - out->data.def.scalar_def = _cel_MessageEqualityScalarFieldKind_kNumber; - out->data.val.num_val = _cel_UintNumber(in_val.uint64_val); - out->kind = _cel_MessageEqualityFieldKind_kScalar; - break; - case kUpb_CType_String: - out->data.def.scalar_def = _cel_MessageEqualityScalarFieldKind_kString; - out->data.val.str_val = in_val.str_val; - out->kind = _cel_MessageEqualityFieldKind_kScalar; - break; - case kUpb_CType_Bytes: - out->data.def.scalar_def = _cel_MessageEqualityScalarFieldKind_kBytes; - out->data.val.str_val = in_val.str_val; - out->kind = _cel_MessageEqualityFieldKind_kScalar; - break; - default: - CEL_UNREACHABLE(); - } -} - -CEL_ATTRIBUTE_NODISCARD -static bool _cel_MessageEqualityState_FieldHeteroEquals( - _cel_MessageEqualityState* cel_nonnull state, upb_MessageValue lhs_val, - const upb_FieldDef* cel_nonnull lhs_def, upb_MessageValue rhs_val, - const upb_FieldDef* cel_nonnull rhs_def, bool single); - -typedef bool _cel_MessageEqualityState_MapKeyCoalescer( - upb_MessageValue in, upb_MessageValue* cel_nonnull out); - -// T -> T -static bool _cel_MessageEqualityState_CoalesceMapKeyIdentity( - upb_MessageValue in, upb_MessageValue* cel_nonnull out) { - *out = in; - return true; -} - -// int32 -> int64 -static bool _cel_MessageEqualityState_CoalesceMapKeyInt32Int64( - upb_MessageValue in, upb_MessageValue* cel_nonnull out) { - out->int64_val = in.int32_val; - return true; -} - -// int32 -> uint32 -static bool _cel_MessageEqualityState_CoalesceMapKeyInt32UInt32( - upb_MessageValue in, upb_MessageValue* cel_nonnull out) { - if (in.int32_val < 0) { - return false; - } - out->uint32_val = (uint32_t)in.int32_val; - return true; -} - -// int32 -> uint64 -static bool _cel_MessageEqualityState_CoalesceMapKeyInt32UInt64( - upb_MessageValue in, upb_MessageValue* cel_nonnull out) { - if (in.int32_val < 0) { - return false; - } - out->uint64_val = (uint32_t)in.int32_val; - return true; -} - -// uint32 -> int32 -static bool _cel_MessageEqualityState_CoalesceMapKeyUInt32Int32( - upb_MessageValue in, upb_MessageValue* cel_nonnull out) { - if (in.uint32_val > (uint32_t)INT32_MAX) { - return false; - } - out->int32_val = (int32_t)in.uint32_val; - return true; -} - -// uint32 -> int64 -static bool _cel_MessageEqualityState_CoalesceMapKeyUInt32Int64( - upb_MessageValue in, upb_MessageValue* cel_nonnull out) { - out->int64_val = (int64_t)(uint64_t)in.uint32_val; - return true; -} - -// uint32 -> uint64 -static bool _cel_MessageEqualityState_CoalesceMapKeyUInt32UInt64( - upb_MessageValue in, upb_MessageValue* cel_nonnull out) { - out->uint64_val = in.uint32_val; - return true; -} - -// int64 -> int32 -static bool _cel_MessageEqualityState_CoalesceMapKeyInt64Int32( - upb_MessageValue in, upb_MessageValue* cel_nonnull out) { - if (in.int64_val < INT32_MIN || in.int64_val > INT32_MAX) { - return false; - } - out->int32_val = (int32_t)in.int64_val; - return true; -} - -// int64 -> uint32 -static bool _cel_MessageEqualityState_CoalesceMapKeyInt64UInt32( - upb_MessageValue in, upb_MessageValue* cel_nonnull out) { - if (in.int64_val < 0 || in.int64_val > (int64_t)(uint64_t)UINT32_MAX) { - return false; - } - out->uint32_val = (uint32_t)(int32_t)in.int64_val; - return true; -} - -// int64 -> uint64 -static bool _cel_MessageEqualityState_CoalesceMapKeyInt64UInt64( - upb_MessageValue in, upb_MessageValue* cel_nonnull out) { - if (in.int64_val < 0) { - return false; - } - out->uint64_val = (uint64_t)in.int64_val; - return true; -} - -// uint64 -> int32 -static bool _cel_MessageEqualityState_CoalesceMapKeyUInt64Int32( - upb_MessageValue in, upb_MessageValue* cel_nonnull out) { - if (in.uint64_val > (uint64_t)(uint32_t)INT32_MAX) { - return false; - } - out->int32_val = (uint64_t)(uint32_t)in.uint64_val; - return true; -} - -// uint64 -> int32 -static bool _cel_MessageEqualityState_CoalesceMapKeyUInt64Int64( - upb_MessageValue in, upb_MessageValue* cel_nonnull out) { - if (in.uint64_val > (uint64_t)INT64_MAX) { - return false; - } - out->int64_val = (int64_t)in.uint64_val; - return true; -} - -// uint64 -> uint32 -static bool _cel_MessageEqualityState_CoalesceMapKeyUInt64UInt32( - upb_MessageValue in, upb_MessageValue* cel_nonnull out) { - if (in.uint64_val > UINT32_MAX) { - return false; - } - out->uint32_val = (uint32_t)in.uint64_val; - return true; -} - -CEL_ATTRIBUTE_NODISCARD -static bool _cel_MessageEqualityState_MapFieldHeteroEquals( - _cel_MessageEqualityState* cel_nonnull state, - const upb_Map* cel_nullable lhs_val, - const upb_FieldDef* cel_nonnull lhs_def, - const upb_Map* cel_nullable rhs_val, - const upb_FieldDef* cel_nonnull rhs_def) { - CEL_ASSERT(upb_FieldDef_IsMap(lhs_def)); - CEL_ASSERT(upb_FieldDef_IsMap(rhs_def)); - - const size_t lhs_val_size = - lhs_val != cel_nullptr ? upb_Map_Size(lhs_val) : 0; - const size_t rhs_val_size = - rhs_val != cel_nullptr ? upb_Map_Size(rhs_val) : 0; - - if (lhs_val_size != rhs_val_size) { - return false; - } - - if (lhs_val_size == 0) { - return true; - } - - const upb_MessageDef* lhs_entry_def = upb_FieldDef_MessageSubDef(lhs_def); - const upb_FieldDef* lhs_key_def = upb_MessageDef_FindFieldByNumber( - lhs_entry_def, kUpb_MapEntry_KeyFieldNumber); - const upb_CType lhs_key_def_type = upb_FieldDef_CType(lhs_key_def); - - const upb_MessageDef* rhs_entry_def = upb_FieldDef_MessageSubDef(rhs_def); - const upb_FieldDef* rhs_key_def = upb_MessageDef_FindFieldByNumber( - rhs_entry_def, kUpb_MapEntry_KeyFieldNumber); - const upb_CType rhs_key_def_type = upb_FieldDef_CType(rhs_key_def); - - _cel_MessageEqualityState_MapKeyCoalescer* map_key_coalescer; - - switch (lhs_key_def_type) { - case kUpb_CType_Bool: - if (rhs_key_def_type != kUpb_CType_Bool) { - return false; - } - map_key_coalescer = &_cel_MessageEqualityState_CoalesceMapKeyIdentity; - break; - case kUpb_CType_Enum: { - if (strcmp(upb_EnumDef_FullName(upb_FieldDef_EnumSubDef(lhs_key_def)), - "google.protobuf.NullValue") == 0) { - if (rhs_key_def_type != kUpb_CType_Enum || - strcmp(upb_EnumDef_FullName(upb_FieldDef_EnumSubDef(rhs_key_def)), - "google.protobuf.NullValue") != 0) { - return false; - } - // Both null. - map_key_coalescer = &_cel_MessageEqualityState_CoalesceMapKeyIdentity; - break; - } - if (rhs_key_def_type == kUpb_CType_Enum && - strcmp(upb_EnumDef_FullName(upb_FieldDef_EnumSubDef(rhs_key_def)), - "google.protobuf.NullValue") == 0) { - return false; - } - // Neither null. - map_key_coalescer = &_cel_MessageEqualityState_CoalesceMapKeyIdentity; - break; - } - case kUpb_CType_Int32: - switch (rhs_key_def_type) { - case kUpb_CType_Enum: - if (strcmp(upb_EnumDef_FullName(upb_FieldDef_EnumSubDef(rhs_key_def)), - "google.protobuf.NullValue") == 0) { - return false; - } - CEL_ATTRIBUTE_FALLTHROUGH; - case kUpb_CType_Int32: - map_key_coalescer = &_cel_MessageEqualityState_CoalesceMapKeyIdentity; - break; - case kUpb_CType_Int64: - map_key_coalescer = - &_cel_MessageEqualityState_CoalesceMapKeyInt32Int64; - break; - case kUpb_CType_UInt32: - map_key_coalescer = - &_cel_MessageEqualityState_CoalesceMapKeyInt32UInt32; - break; - case kUpb_CType_UInt64: - map_key_coalescer = - &_cel_MessageEqualityState_CoalesceMapKeyInt32UInt64; - break; - default: - return false; - } - break; - case kUpb_CType_Int64: - switch (rhs_key_def_type) { - case kUpb_CType_Enum: - if (strcmp(upb_EnumDef_FullName(upb_FieldDef_EnumSubDef(rhs_key_def)), - "google.protobuf.NullValue") == 0) { - return false; - } - CEL_ATTRIBUTE_FALLTHROUGH; - case kUpb_CType_Int32: - map_key_coalescer = - &_cel_MessageEqualityState_CoalesceMapKeyInt64Int32; - break; - case kUpb_CType_Int64: - map_key_coalescer = &_cel_MessageEqualityState_CoalesceMapKeyIdentity; - break; - case kUpb_CType_UInt32: - map_key_coalescer = - &_cel_MessageEqualityState_CoalesceMapKeyInt64UInt32; - break; - case kUpb_CType_UInt64: - map_key_coalescer = - &_cel_MessageEqualityState_CoalesceMapKeyInt64UInt64; - break; - default: - return false; - } - break; - case kUpb_CType_UInt32: - switch (rhs_key_def_type) { - case kUpb_CType_Enum: - if (strcmp(upb_EnumDef_FullName(upb_FieldDef_EnumSubDef(rhs_key_def)), - "google.protobuf.NullValue") == 0) { - return false; - } - CEL_ATTRIBUTE_FALLTHROUGH; - case kUpb_CType_Int32: - map_key_coalescer = - &_cel_MessageEqualityState_CoalesceMapKeyUInt32Int32; - break; - case kUpb_CType_Int64: - map_key_coalescer = - &_cel_MessageEqualityState_CoalesceMapKeyUInt32Int64; - break; - case kUpb_CType_UInt32: - map_key_coalescer = &_cel_MessageEqualityState_CoalesceMapKeyIdentity; - break; - case kUpb_CType_UInt64: - map_key_coalescer = - &_cel_MessageEqualityState_CoalesceMapKeyUInt32UInt64; - break; - default: - return false; - } - break; - case kUpb_CType_UInt64: - switch (rhs_key_def_type) { - case kUpb_CType_Enum: - if (strcmp(upb_EnumDef_FullName(upb_FieldDef_EnumSubDef(rhs_key_def)), - "google.protobuf.NullValue") == 0) { - return false; - } - CEL_ATTRIBUTE_FALLTHROUGH; - case kUpb_CType_Int32: - map_key_coalescer = - &_cel_MessageEqualityState_CoalesceMapKeyUInt64Int32; - break; - case kUpb_CType_Int64: - map_key_coalescer = - &_cel_MessageEqualityState_CoalesceMapKeyUInt64Int64; - break; - case kUpb_CType_UInt32: - map_key_coalescer = - &_cel_MessageEqualityState_CoalesceMapKeyUInt64UInt32; - break; - case kUpb_CType_UInt64: - map_key_coalescer = &_cel_MessageEqualityState_CoalesceMapKeyIdentity; - break; - default: - return false; - } - break; - case kUpb_CType_String: - if (rhs_key_def_type != kUpb_CType_String) { - return false; - } - map_key_coalescer = &_cel_MessageEqualityState_CoalesceMapKeyIdentity; - break; - default: - CEL_UNREACHABLE(); - } - - const upb_FieldDef* lhs_value_def = upb_MessageDef_FindFieldByNumber( - lhs_entry_def, kUpb_MapEntry_ValueFieldNumber); - const upb_FieldDef* rhs_value_def = upb_MessageDef_FindFieldByNumber( - lhs_entry_def, kUpb_MapEntry_ValueFieldNumber); - - size_t lhs_iter = kUpb_Map_Begin; - upb_MessageValue lhs_key; - upb_MessageValue lhs_value; - while (upb_Map_Next(lhs_val, &lhs_key, &lhs_value, &lhs_iter)) { - upb_MessageValue rhs_key; - if (!(*map_key_coalescer)(lhs_key, &rhs_key)) { - return false; - } - upb_MessageValue rhs_value; - if (!upb_Map_Get(rhs_val, rhs_key, &rhs_value)) { - return false; - } - if (!_cel_MessageEqualityState_FieldHeteroEquals( - state, lhs_value, lhs_value_def, rhs_value, rhs_value_def, - /*single=*/true)) { - return false; - } - } - return true; -} - -CEL_ATTRIBUTE_NODISCARD -static bool _cel_MessageEqualityState_RepeatedFieldHeteroEquals( - _cel_MessageEqualityState* cel_nonnull state, - const upb_Array* cel_nullable lhs_val, - const upb_FieldDef* cel_nonnull lhs_def, - const upb_Array* cel_nullable rhs_val, - const upb_FieldDef* cel_nonnull rhs_def) { - const size_t lhs_val_size = - lhs_val != cel_nullptr ? upb_Array_Size(lhs_val) : 0; - const size_t rhs_val_size = - rhs_val != cel_nullptr ? upb_Array_Size(rhs_val) : 0; - - if (lhs_val_size != rhs_val_size) { - return false; - } - - if (lhs_val_size == 0) { - return true; - } - - for (size_t i = 0; i < lhs_val_size; ++i) { - if (!_cel_MessageEqualityState_FieldHeteroEquals( - state, upb_Array_Get(lhs_val, i), lhs_def, - upb_Array_Get(rhs_val, i), rhs_def, /*single=*/true)) { - return false; - } - } - return true; -} - -CEL_ATTRIBUTE_NODISCARD -static bool _cel_MessageEqualityState_FieldHeteroEquals( - _cel_MessageEqualityState* cel_nonnull state, upb_MessageValue lhs_val, - const upb_FieldDef* cel_nonnull lhs_def, upb_MessageValue rhs_val, - const upb_FieldDef* cel_nonnull rhs_def, bool single) { - _cel_MessageEqualityField lhs_field; - _cel_MessageEqualityField rhs_field; - - _cel_MessageEqualityState_Field(state, lhs_val, lhs_def, single, &lhs_field); - _cel_MessageEqualityState_Field(state, rhs_val, rhs_def, single, &rhs_field); - - switch (lhs_field.kind) { - case _cel_MessageEqualityFieldKind_kScalar: - if (lhs_field.kind != rhs_field.kind) { - return false; - } - if (lhs_field.data.def.scalar_def != rhs_field.data.def.scalar_def) { - return false; - } - switch (lhs_field.data.def.scalar_def) { - case _cel_MessageEqualityScalarFieldKind_kBool: - return lhs_field.data.val.bool_val == rhs_field.data.val.bool_val; - case _cel_MessageEqualityScalarFieldKind_kNumber: - return _cel_Number_Equals(lhs_field.data.val.num_val, - rhs_field.data.val.num_val); - case _cel_MessageEqualityScalarFieldKind_kString: - CEL_ATTRIBUTE_FALLTHROUGH; - case _cel_MessageEqualityScalarFieldKind_kBytes: - return cel_StringView_Equals(lhs_field.data.val.str_val, - rhs_field.data.val.str_val); - default: - CEL_UNREACHABLE(); - } - case _cel_MessageEqualityFieldKind_kMessage: - if (lhs_field.kind != rhs_field.kind || - lhs_field.data.def.message_def != rhs_field.data.def.message_def) { - return false; - } - return _cel_MessageEqualityState_HomoEquals( - state, lhs_field.data.val.msg_val, rhs_field.data.val.msg_val, - lhs_field.data.def.message_def); - case _cel_MessageEqualityFieldKind_kNullValue: - return lhs_field.kind == rhs_field.kind; - case _cel_MessageEqualityFieldKind_kRepeated: - if (lhs_field.kind != rhs_field.kind) { - return false; - } - return _cel_MessageEqualityState_RepeatedFieldHeteroEquals( - state, lhs_field.data.val.array_val, lhs_field.data.def.field_def, - rhs_field.data.val.array_val, rhs_field.data.def.field_def); - case _cel_MessageEqualityFieldKind_kMap: - if (lhs_field.kind != rhs_field.kind) { - return false; - } - return _cel_MessageEqualityState_MapFieldHeteroEquals( - state, lhs_field.data.val.map_val, lhs_field.data.def.field_def, - rhs_field.data.val.map_val, rhs_field.data.def.field_def); - default: - CEL_UNREACHABLE(); - } -} - -_cel_MessageEquality _cel_Message_Equals( - const upb_Message* cel_nonnull lhs_val, - const upb_Message* cel_nonnull rhs_val, - const upb_MessageDef* cel_nonnull val_def, - const upb_DefPool* cel_nonnull def_pool, - const cel_WellKnownTypes* cel_nonnull wkts, - cel_Allocator* cel_nonnull alloc) { - CEL_ASSERT_NOT_NULL(lhs_val); - CEL_ASSERT_NOT_NULL(rhs_val); - CEL_ASSERT_NOT_NULL(val_def); - CEL_ASSERT_NOT_NULL(def_pool); - CEL_ASSERT_NOT_NULL(wkts); - CEL_ASSERT_NOT_NULL(alloc); - - _cel_MessageEqualityState state = { - .def_pool = def_pool, - .wkts = wkts, - .alloc = alloc, - .arena = cel_nullptr, - .depth = 100, - }; - _cel_MessageEqualityState* volatile state_ptr = &state; - if (_cel_setjmp(state_ptr->jmp)) { - CEL_ASSERT_NE(state_ptr->result, _cel_MessageEquality_kEqual); - CEL_ASSERT_NE(state_ptr->result, _cel_MessageEquality_kNotEqual); - } else { - state_ptr->result = _cel_MessageEqualityState_HomoEquals(state_ptr, lhs_val, - rhs_val, val_def) - ? _cel_MessageEquality_kEqual - : _cel_MessageEquality_kNotEqual; - } - cel_Arena_Delete(state_ptr->arena); - return state_ptr->result; -} - -_cel_MessageEquality _cel_MessageField_Equals( - upb_MessageValue lhs_val, const upb_FieldDef* cel_nonnull lhs_def, - upb_MessageValue rhs_val, const upb_FieldDef* cel_nonnull rhs_def, - const upb_DefPool* cel_nonnull def_pool, - const cel_WellKnownTypes* cel_nonnull wkts, - cel_Allocator* cel_nonnull alloc) { - CEL_ASSERT_NOT_NULL(lhs_def); - CEL_ASSERT_NOT_NULL(rhs_def); - CEL_ASSERT_NOT_NULL(def_pool); - CEL_ASSERT_NOT_NULL(wkts); - CEL_ASSERT_NOT_NULL(alloc); - - _cel_MessageEqualityState state = { - .def_pool = def_pool, - .wkts = wkts, - .alloc = alloc, - .arena = cel_nullptr, - .depth = 100, - }; - _cel_MessageEqualityState* volatile state_ptr = &state; - if (_cel_setjmp(state_ptr->jmp)) { - CEL_ASSERT_NE(state_ptr->result, _cel_MessageEquality_kEqual); - CEL_ASSERT_NE(state_ptr->result, _cel_MessageEquality_kNotEqual); - } else { - state_ptr->result = - _cel_MessageEqualityState_FieldHeteroEquals( - state_ptr, lhs_val, lhs_def, rhs_val, rhs_def, /*single=*/false) - ? _cel_MessageEquality_kEqual - : _cel_MessageEquality_kNotEqual; - } - cel_Arena_Delete(state_ptr->arena); - return state_ptr->result; -} diff --git a/cel-c/src/mutable_list_value.c b/cel-c/src/mutable_list_value.c deleted file mode 100644 index 776482a..0000000 --- a/cel-c/src/mutable_list_value.c +++ /dev/null @@ -1,366 +0,0 @@ -// Copyright 2025 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "cel-c/src/mutable_list_value.h" - -#include -#include -#include -#include - -#include "cel-c/alloc.h" -#include "cel-c/arena.h" -#include "cel-c/assert.h" -#include "cel-c/config.h" -#include "cel-c/error.h" -#include "cel-c/error_code.h" -#include "cel-c/status.h" -#include "cel-c/string_view.h" -#include "cel-c/value.h" -#include "cel-c/src/ckdint.h" -#include "cel-c/src/empty_list_value.h" - -static const cel_ListValueIteratorVTable _cel_MutableListValueIteratorVTable; - -typedef struct { - union { - struct { - cel_Value* cel_nullable ptr; - uint32_t len; - uint32_t cap; - }; - cel_ValueContent super; - }; -} _cel_MutableListValueContent; - -typedef struct { - cel_ListValueIterator super; - cel_Allocator* cel_nonnull alloc; - cel_Value* cel_nonnull ptr; - uint32_t len; - uint32_t idx; -} _cel_MutableListValueIterator; - -#define _cel_MutableListValueContent_kPtrOffset 0 -#define _cel_MutableListValueContent_kLenOffset \ - (sizeof(void*) / sizeof(uint32_t)) -#define _cel_MutableListValueContent_kCapOffset \ - (_cel_MutableListValueContent_kLenOffset + 1) - -CEL_STATIC_ASSERT(sizeof(_cel_MutableListValueContent) <= - sizeof(cel_ValueContent)); -CEL_STATIC_ASSERT(alignof(_cel_MutableListValueContent) <= - alignof(cel_ValueContent)); - -static bool _cel_MutableListValue_FastSize( - const cel_ListValueVTable* cel_nonnull vtable, cel_ValueContent content, - size_t* cel_nonnull size) { - CEL_ASSERT_EQ(vtable, &_cel_MutableListValueVTable); - CEL_ASSERT_NOT_NULL(size); - - *size = content.u32[_cel_MutableListValueContent_kLenOffset]; - return true; -} - -static bool _cel_MutableListValue_SlowSize( - const cel_ListValueVTable* cel_nonnull vtable, cel_ValueContent content, - const cel_ValueContext* cel_nonnull context, cel_Value* cel_nonnull size, - cel_Status* cel_nonnull status) { - CEL_ASSERT_EQ(vtable, &_cel_MutableListValueVTable); - CEL_ASSERT_NOT_NULL(context); - CEL_ASSERT_NOT_NULL(size); - CEL_ASSERT_NOT_NULL(status); - - if (CEL_UNLIKELY(!cel_Status_Ok(status))) { - return false; - } - - cel_Value_SetInt(size, content.u32[_cel_MutableListValueContent_kLenOffset]); - return true; -} - -static bool _cel_MutableListValue_Get( - const cel_ListValueVTable* cel_nonnull vtable, cel_ValueContent content, - const cel_ValueContext* cel_nonnull context, size_t index, - cel_Value* cel_nonnull element, cel_Status* cel_nonnull status) { - CEL_ASSERT_EQ(vtable, &_cel_MutableListValueVTable); - CEL_ASSERT_NOT_NULL(context); - CEL_ASSERT_NOT_NULL(element); - CEL_ASSERT_NOT_NULL(status); - - if (CEL_UNLIKELY(!cel_Status_Ok(status))) { - return false; - } - - uint32_t len = content.u32[_cel_MutableListValueContent_kLenOffset]; - if (CEL_LIKELY(index < len)) { - const cel_Value* ptr = - (cel_Value*)content.ptr[_cel_MutableListValueContent_kPtrOffset]; - *element = ptr[index]; - return true; - } - - cel_Error* error = cel_Error_New(context->arena); - if (CEL_UNLIKELY(error == cel_nullptr)) { - cel_OutOfMemoryStatus(status); - return false; - } - cel_Error_SetCanonicalCode(error, cel_ErrorCode_kOutOfRange); - cel_Error_SetMessage(error, cel_StringView_From("index out of range")); - cel_Value_SetError(element, error); - return true; -} - -bool _cel_MutableListValue_Reserve(cel_ListValue* cel_nonnull list_value, - uint32_t size, - cel_Arena* cel_nonnull arena) { - CEL_ASSERT_NOT_NULL(list_value); - CEL_ASSERT(_cel_ListValue_IsMutable(list_value)); - CEL_ASSERT_NOT_NULL(arena); - - uint32_t cap = - list_value->content.u32[_cel_MutableListValueContent_kCapOffset]; - if (size <= cap) { - return true; - } - - if (size <= 8) { - size = 8; - } - cel_Value* ptr = - (cel_Value*) - list_value->content.ptr[_cel_MutableListValueContent_kPtrOffset]; - size_t new_cap_bytes; - if (_cel_ckd_mul(&new_cap_bytes, (size_t)size, sizeof(cel_Value))) { - return false; - } - cel_Value* new_ptr = (cel_Value*)cel_Arena_Realloc( - arena, ptr, (size_t)cap * sizeof(cel_Value), new_cap_bytes, cel_nullptr); - if (CEL_UNLIKELY(new_ptr == cel_nullptr)) { - return false; - } - list_value->content.ptr[_cel_MutableListValueContent_kPtrOffset] = new_ptr; - list_value->content.u32[_cel_MutableListValueContent_kCapOffset] = size; - return true; -} - -cel_Value* cel_nullable -_cel_MutableListValue_AddN(cel_ListValue* cel_nonnull list_value, uint32_t size, - cel_Arena* cel_nonnull arena) { - CEL_ASSERT_NOT_NULL(list_value); - CEL_ASSERT(_cel_ListValue_IsMutable(list_value)); - CEL_ASSERT_NOT_NULL(arena); - - uint32_t len = - list_value->content.u32[_cel_MutableListValueContent_kLenOffset]; - uint32_t cap = - list_value->content.u32[_cel_MutableListValueContent_kCapOffset]; - cel_Value* ptr = - (cel_Value*) - list_value->content.ptr[_cel_MutableListValueContent_kPtrOffset]; - if (CEL_UNLIKELY(size > len || len > cap - size)) { - if (cap == UINT32_MAX) { - return cel_nullptr; - } - uint32_t min_cap; - if (_cel_ckd_add(&min_cap, len, size)) { - return cel_nullptr; - } - uint32_t new_cap; - if (_cel_ckd_mul(&new_cap, cap, (uint32_t)2)) { - new_cap = UINT32_MAX; - } - if (new_cap < 8) { - new_cap = 8; - } - while (new_cap < min_cap) { - if (_cel_ckd_mul(&new_cap, new_cap, (uint32_t)2)) { - new_cap = UINT32_MAX; - break; - } - } - size_t new_cap_bytes; - if (_cel_ckd_mul(&new_cap_bytes, (size_t)new_cap, sizeof(cel_Value))) { - return cel_nullptr; - } - ptr = (cel_Value*)cel_Arena_Realloc(arena, ptr, - (size_t)cap * sizeof(cel_Value), - new_cap_bytes, cel_nullptr); - if (CEL_UNLIKELY(ptr == cel_nullptr)) { - return cel_nullptr; - } - list_value->content.ptr[_cel_MutableListValueContent_kPtrOffset] = ptr; - list_value->content.u32[_cel_MutableListValueContent_kCapOffset] = new_cap; - } - list_value->content.u32[_cel_MutableListValueContent_kLenOffset] = len + size; - return ptr + len; -} - -static cel_ListValueIterator* cel_nullable _cel_MutableListValue_NewIterator( - const cel_ListValueVTable* cel_nonnull vtable, cel_ValueContent content, - const cel_ValueContext* cel_nonnull context, - cel_Status* cel_nonnull status) { - CEL_ASSERT_EQ(vtable, &_cel_MutableListValueVTable); - CEL_ASSERT_NOT_NULL(context); - CEL_ASSERT_NOT_NULL(status); - - if (CEL_UNLIKELY(!cel_Status_Ok(status))) { - return cel_nullptr; - } - - uint32_t len = content.u32[_cel_MutableListValueContent_kLenOffset]; - if (len == 0) { - return &_cel_EmptyListValueIterator; - } - - _cel_MutableListValueIterator* iter = - (_cel_MutableListValueIterator*)cel_Allocator_Malloc( - context->alloc, sizeof(_cel_MutableListValueIterator), cel_nullptr); - if (CEL_UNLIKELY(iter == cel_nullptr)) { - cel_OutOfMemoryStatus(status); - return cel_nullptr; - } - iter->super.vtable = &_cel_MutableListValueIteratorVTable; - iter->alloc = context->alloc; - iter->ptr = (cel_Value*)content.ptr[_cel_MutableListValueContent_kPtrOffset]; - iter->len = len; - iter->idx = 0; - - return &iter->super; -} - -const cel_ListValueVTable _cel_MutableListValueVTable = { - .Equals = cel_nullptr, - .FastSize = &_cel_MutableListValue_FastSize, - .SlowSize = &_cel_MutableListValue_SlowSize, - .Get = &_cel_MutableListValue_Get, - .NewIterator = &_cel_MutableListValue_NewIterator, -}; - -static void _cel_MutableListValueIterator_Delete( - cel_ValueIterator* cel_nonnull iterator) { - CEL_ASSERT_NOT_NULL(iterator); - CEL_ASSERT_EQ( - iterator->vtable, - (const cel_ValueIteratorVTable*)&_cel_MutableListValueIteratorVTable); - - _cel_MutableListValueIterator* iter = - cel_containerof(iterator, _cel_MutableListValueIterator, super); - cel_Allocator_FreeSized(iter->alloc, iter, sizeof(*iter)); -} - -static bool _cel_MutableListValueIterator_Next1( - cel_ValueIterator* cel_nonnull iterator, - const cel_ValueContext* cel_nonnull context, - cel_Value* cel_nonnull key_or_value, cel_Status* cel_nonnull status) { - CEL_ASSERT_NOT_NULL(iterator); - CEL_ASSERT_EQ(iterator->vtable, &_cel_MutableListValueIteratorVTable.super); - CEL_ASSERT_NOT_NULL(context); - CEL_ASSERT_NOT_NULL(key_or_value); - CEL_ASSERT_NOT_NULL(status); - - if (CEL_UNLIKELY(!cel_Status_Ok(status))) { - return false; - } - - _cel_MutableListValueIterator* iter = - cel_containerof(iterator, _cel_MutableListValueIterator, super); - if (CEL_UNLIKELY(iter->idx >= iter->len)) { - return false; - } - - *key_or_value = iter->ptr[iter->idx]; - ++iter->idx; - return true; -} - -static bool _cel_MutableListValueIterator_Next2( - cel_ValueIterator* cel_nonnull iterator, - const cel_ValueContext* cel_nonnull context, cel_Value* cel_nonnull key, - cel_Value* cel_nonnull value, cel_Status* cel_nonnull status) { - CEL_ASSERT_NOT_NULL(iterator); - CEL_ASSERT_EQ(iterator->vtable, &_cel_MutableListValueIteratorVTable.super); - CEL_ASSERT_NOT_NULL(context); - CEL_ASSERT_NOT_NULL(key); - CEL_ASSERT_NOT_NULL(value); - CEL_ASSERT_NOT_NULL(status); - - if (CEL_UNLIKELY(!cel_Status_Ok(status))) { - return false; - } - - _cel_MutableListValueIterator* iter = - cel_containerof(iterator, _cel_MutableListValueIterator, super); - if (CEL_UNLIKELY(iter->idx >= iter->len)) { - return false; - } - - cel_Value_SetInt(key, iter->idx); - *value = iter->ptr[iter->idx]; - ++iter->idx; - return true; -} - -static bool _cel_MutableListValueIterator_Remaining( - const cel_ValueIterator* cel_nonnull iterator, - size_t* cel_nonnull remaining) { - CEL_ASSERT_NOT_NULL(iterator); - CEL_ASSERT_EQ(iterator->vtable, &_cel_MutableListValueIteratorVTable.super); - CEL_ASSERT_NOT_NULL(remaining); - - const _cel_MutableListValueIterator* iter = - cel_containerof(iterator, _cel_MutableListValueIterator, super); - - *remaining = iter->len - iter->idx; - return true; -} - -static bool _cel_MutableListValueIterator_Next( - cel_ListValueIterator* cel_nonnull iterator, - const cel_ValueContext* cel_nonnull context, size_t* cel_nullable index, - cel_Value* cel_nonnull value, cel_Status* cel_nonnull status) { - CEL_ASSERT_NOT_NULL(iterator); - CEL_ASSERT_EQ(iterator->vtable, &_cel_MutableListValueIteratorVTable); - CEL_ASSERT_NOT_NULL(context); - CEL_ASSERT_NOT_NULL(value); - CEL_ASSERT_NOT_NULL(status); - - if (CEL_UNLIKELY(!cel_Status_Ok(status))) { - return false; - } - - _cel_MutableListValueIterator* iter = - cel_containerof(iterator, _cel_MutableListValueIterator, super); - if (CEL_UNLIKELY(iter->idx >= iter->len)) { - return false; - } - - if (index != cel_nullptr) { - *index = iter->idx; - } - *value = iter->ptr[iter->idx]; - ++iter->idx; - return true; -} - -static const cel_ListValueIteratorVTable _cel_MutableListValueIteratorVTable = { - .super = - { - .Delete = &_cel_MutableListValueIterator_Delete, - .Next1 = &_cel_MutableListValueIterator_Next1, - .Next2 = &_cel_MutableListValueIterator_Next2, - .Remaining = &_cel_MutableListValueIterator_Remaining, - }, - .Next = &_cel_MutableListValueIterator_Next, -}; diff --git a/cel-c/src/mutable_map_value.c b/cel-c/src/mutable_map_value.c deleted file mode 100644 index 97c7498..0000000 --- a/cel-c/src/mutable_map_value.c +++ /dev/null @@ -1,561 +0,0 @@ -// Copyright 2025 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "cel-c/src/mutable_map_value.h" - -#include -#include -#include -#include -#include - -#include "cel-c/alloc.h" -#include "cel-c/arena.h" -#include "cel-c/assert.h" -#include "cel-c/config.h" -#include "cel-c/error.h" -#include "cel-c/error_code.h" -#include "cel-c/hash.h" -#include "cel-c/status.h" -#include "cel-c/string_view.h" -#include "cel-c/value.h" -#include "cel-c/src/bit.h" -#include "cel-c/src/empty_map_value.h" -#include "cel-c/src/map_value.h" - -static const cel_MapValueIteratorVTable _cel_MutableMapValueIteratorVTable; - -typedef struct { - cel_MapValueKey key; - cel_Value value; -} _cel_MutableMapValueEntry; - -typedef struct { - union { - struct { - // ptr points to a memory block which starts with a bitset and pointers to - // the entries immediately follow. - _cel_MutableMapValueEntry * cel_nullable * cel_nullable ptr; - uint32_t len; - // cap is always a power of 2 - uint32_t cap; - }; - cel_ValueContent super; - }; -} _cel_MutableMapValueContent; - -typedef struct { - cel_MapValueIterator super; - cel_Allocator* cel_nonnull alloc; - _cel_MutableMapValueEntry * cel_nullable * cel_nonnull ents; - uint32_t len; - uint32_t cap; - uint32_t bit; - uint32_t rem; -} _cel_MutableMapValueIterator; - -CEL_ATTRIBUTE_NODISCARD -static bool _cel_MutableMapValueIterator_Done( - const _cel_MutableMapValueIterator* cel_nonnull iter) { - return iter->rem == 0; -} - -static size_t _cel_MutableMapValueIterator_Advance( - const _cel_MutableMapValueIterator* cel_nonnull iter) { - CEL_ASSERT_NOT(_cel_MutableMapValueIterator_Done(iter)); - size_t bit; - for (bit = iter->bit + 1; iter->ents[bit] == cel_nullptr; ++bit) { - } - return bit; -} - -#define _cel_MutableMapValueContent_kPtrOffset 0 -#define _cel_MutableMapValueContent_kLenOffset \ - (sizeof(void*) / sizeof(uint32_t)) -#define _cel_MutableMapValueContent_kCapOffset \ - (_cel_MutableMapValueContent_kLenOffset + 1) - -CEL_STATIC_ASSERT(sizeof(_cel_MutableMapValueContent) <= - sizeof(cel_ValueContent)); -CEL_STATIC_ASSERT(alignof(_cel_MutableMapValueContent) <= - alignof(cel_ValueContent)); - -static bool _cel_MutableMapValue_FastSize( - const cel_MapValueVTable* cel_nonnull vtable, cel_ValueContent content, - size_t* cel_nonnull size) { - CEL_ASSERT_EQ(vtable, &_cel_MutableMapValueVTable); - CEL_ASSERT_NOT_NULL(size); - - *size = content.u32[_cel_MutableMapValueContent_kLenOffset]; - return true; -} - -static bool _cel_MutableMapValue_SlowSize( - const cel_MapValueVTable* cel_nonnull vtable, cel_ValueContent content, - const cel_ValueContext* cel_nonnull context, cel_Value* cel_nonnull size, - cel_Status* cel_nonnull status) { - CEL_ASSERT_EQ(vtable, &_cel_MutableMapValueVTable); - CEL_ASSERT_NOT_NULL(context); - CEL_ASSERT_NOT_NULL(size); - CEL_ASSERT_NOT_NULL(status); - - if (CEL_UNLIKELY(!cel_Status_Ok(status))) { - return false; - } - - cel_Value_SetInt(size, content.u32[_cel_MutableMapValueContent_kLenOffset]); - return true; -} - -static bool _cel_MutableMapValue_Get( - const cel_MapValueVTable* cel_nonnull vtable, cel_ValueContent content, - const cel_ValueContext* cel_nonnull context, - const cel_MapValueKey* cel_nonnull key, cel_Value* cel_nonnull value, - cel_Status* cel_nonnull status) { - CEL_ASSERT_EQ(vtable, &_cel_MutableMapValueVTable); - CEL_ASSERT_NOT_NULL(context); - CEL_ASSERT_NOT_NULL(key); - CEL_ASSERT_NOT_NULL(value); - CEL_ASSERT_NOT_NULL(status); - - if (CEL_UNLIKELY(!cel_Status_Ok(status))) { - return false; - } - - uint32_t len = content.u32[_cel_MutableMapValueContent_kLenOffset]; - if (len != 0) { - _cel_MutableMapValueEntry** ents = - (_cel_MutableMapValueEntry**) - content.ptr[_cel_MutableMapValueContent_kPtrOffset]; - const size_t mask = - (size_t)content.u32[_cel_MutableMapValueContent_kCapOffset] - 1; - size_t bit = cel_HashState_Finalize( - _cel_MapValueKey_Hash(key, cel_HashState_Initialize())) & - mask; - _cel_MutableMapValueEntry* ent; - for (ent = ents[bit]; ent != cel_nullptr; ent = ents[(++bit) & mask]) { - if (_cel_MapValueKey_Equals(&ent->key, key)) { - *value = ent->value; - return true; - } - } - } - - cel_Error* error = cel_Error_New(context->arena); - if (CEL_UNLIKELY(error == cel_nullptr)) { - cel_OutOfMemoryStatus(status); - return false; - } - cel_Error_SetCanonicalCode(error, cel_ErrorCode_kNotFound); - cel_Error_SetMessage(error, cel_StringView_From("no such key")); - cel_Value_SetError(value, error); - return true; -} - -static bool _cel_MutableMapValue_Find( - const cel_MapValueVTable* cel_nonnull vtable, cel_ValueContent content, - const cel_ValueContext* cel_nonnull context, - const cel_MapValueKey* cel_nonnull key, cel_Value* cel_nonnull value, - cel_Status* cel_nonnull status) { - CEL_ASSERT_EQ(vtable, &_cel_MutableMapValueVTable); - CEL_ASSERT_NOT_NULL(context); - CEL_ASSERT_NOT_NULL(key); - CEL_ASSERT_NOT_NULL(value); - CEL_ASSERT_NOT_NULL(status); - - if (CEL_UNLIKELY(!cel_Status_Ok(status))) { - return false; - } - - uint32_t len = content.u32[_cel_MutableMapValueContent_kLenOffset]; - if (len != 0) { - _cel_MutableMapValueEntry** ents = - (_cel_MutableMapValueEntry**) - content.ptr[_cel_MutableMapValueContent_kPtrOffset]; - const size_t mask = - (size_t)content.u32[_cel_MutableMapValueContent_kCapOffset] - 1; - size_t bit = cel_HashState_Finalize( - _cel_MapValueKey_Hash(key, cel_HashState_Initialize())) & - mask; - _cel_MutableMapValueEntry* ent; - for (ent = ents[bit]; ent != cel_nullptr; ent = ents[(++bit) & mask]) { - if (_cel_MapValueKey_Equals(&ent->key, key)) { - *value = ent->value; - return true; - } - } - } - - return false; -} - -static bool _cel_MutableMapValue_Has( - const cel_MapValueVTable* cel_nonnull vtable, cel_ValueContent content, - const cel_ValueContext* cel_nonnull context, - const cel_MapValueKey* cel_nonnull key, cel_Value* cel_nonnull result, - cel_Status* cel_nonnull status) { - CEL_ASSERT_EQ(vtable, &_cel_MutableMapValueVTable); - CEL_ASSERT_NOT_NULL(context); - CEL_ASSERT_NOT_NULL(key); - CEL_ASSERT_NOT_NULL(result); - CEL_ASSERT_NOT_NULL(status); - - if (CEL_UNLIKELY(!cel_Status_Ok(status))) { - return false; - } - - uint32_t len = content.u32[_cel_MutableMapValueContent_kLenOffset]; - if (len != 0) { - _cel_MutableMapValueEntry** ents = - (_cel_MutableMapValueEntry**) - content.ptr[_cel_MutableMapValueContent_kPtrOffset]; - const size_t mask = - (size_t)content.u32[_cel_MutableMapValueContent_kCapOffset] - 1; - size_t bit = cel_HashState_Finalize( - _cel_MapValueKey_Hash(key, cel_HashState_Initialize())) & - mask; - _cel_MutableMapValueEntry* ent; - for (ent = ents[bit]; ent != cel_nullptr; ent = ents[(++bit) & mask]) { - if (_cel_MapValueKey_Equals(&ent->key, key)) { - cel_Value_SetTrue(result); - return true; - } - } - } - - cel_Value_SetFalse(result); - return true; -} - -static void _cel_MutableMapValue_Rehash(_cel_MutableMapValueEntry** new_ents, - size_t new_cap, - _cel_MutableMapValueEntry** old_ents, - size_t old_cap, size_t len) { - const size_t new_mask = new_cap - 1; - const cel_HashState state = cel_HashState_Initialize(); - size_t old_bit; - for (old_bit = 0; len > 0; ++old_bit) { - _cel_MutableMapValueEntry* ent = old_ents[old_bit]; - if (ent == cel_nullptr) { - continue; - } - size_t new_bit = - cel_HashState_Finalize(_cel_MapValueKey_Hash(&ent->key, state)) & - new_mask; - for (; new_ents[new_bit] != cel_nullptr; - new_bit = (new_bit + 1) & new_mask) { - } - new_ents[new_bit] = ent; - --len; - } -} - -static bool _cel_MutableMapValue_Resize(cel_MapValue* cel_nonnull map_value, - _cel_MutableMapValueEntry** old_ents, - uint32_t new_cap, uint32_t old_cap, - uint32_t len, - cel_Arena* cel_nonnull arena) { - CEL_ASSERT(new_cap > old_cap && _cel_has_single_bit(new_cap) && - (old_cap == 0 || _cel_has_single_bit(old_cap))); - _cel_MutableMapValueEntry** new_ents = - (_cel_MutableMapValueEntry**)cel_Arena_Malloc( - arena, sizeof(_cel_MutableMapValueEntry) * new_cap, cel_nullptr); - if (CEL_UNLIKELY(new_ents == cel_nullptr)) { - return false; - } - memset(new_ents, 0, sizeof(_cel_MutableMapValueEntry) * new_cap); - _cel_MutableMapValue_Rehash(new_ents, new_cap, old_ents, old_cap, len); - map_value->content.ptr[_cel_MutableMapValueContent_kPtrOffset] = new_ents; - map_value->content.u32[_cel_MutableMapValueContent_kCapOffset] = new_cap; - return true; -} - -bool _cel_MutableMapValue_Reserve(cel_MapValue* cel_nonnull map_value, - uint32_t size, cel_Arena* cel_nonnull arena) { - CEL_ASSERT_NOT_NULL(map_value); - CEL_ASSERT_EQ(map_value->vtable, &_cel_MutableMapValueVTable); - CEL_ASSERT_NOT_NULL(arena); - - uint32_t cap = map_value->content.u32[_cel_MutableMapValueContent_kCapOffset]; - if (cap >= size) { - return true; - } - if (size > (((uint32_t)1) << ((sizeof(uint32_t) * CHAR_BIT) - 1))) { - return false; - } - size = _cel_bit_ceil(size); - if (size < 16) { - size = 16; - } - return _cel_MutableMapValue_Resize( - map_value, - (_cel_MutableMapValueEntry**) - map_value->content.ptr[_cel_MutableMapValueContent_kPtrOffset], - _cel_bit_ceil(size), cap, - map_value->content.u32[_cel_MutableMapValueContent_kLenOffset], arena); -} - -_cel_MutableMapValueInsertResult _cel_MutableMapValue_Insert( - cel_MapValue* cel_nonnull map_value, const cel_MapValueKey* cel_nonnull key, - cel_MapValueKey * cel_nullable * cel_nullable out_key, - cel_Value * cel_nullable * cel_nonnull out_value, - cel_Arena* cel_nonnull arena) { - CEL_ASSERT_NOT_NULL(map_value); - CEL_ASSERT_EQ(map_value->vtable, &_cel_MutableMapValueVTable); - CEL_ASSERT_NOT_NULL(key); - CEL_ASSERT_NOT_NULL(out_value); - CEL_ASSERT_NOT_NULL(arena); - - uint32_t cap = map_value->content.u32[_cel_MutableMapValueContent_kCapOffset]; - uint32_t len; - if (CEL_UNLIKELY(cap == 0)) { - cap = 16; - len = 0; - _cel_MutableMapValueEntry** ents = - (_cel_MutableMapValueEntry**)cel_Arena_Malloc( - arena, sizeof(_cel_MutableMapValueEntry) * cap, cel_nullptr); - if (CEL_UNLIKELY(ents == cel_nullptr)) { - return _cel_MutableMapValueInsertResult_kOutOfMemory; - } - memset(ents, 0, sizeof(_cel_MutableMapValueEntry) * cap); - map_value->content.ptr[_cel_MutableMapValueContent_kPtrOffset] = ents; - map_value->content.u32[_cel_MutableMapValueContent_kCapOffset] = cap; - } else { - len = map_value->content.u32[_cel_MutableMapValueContent_kLenOffset]; - } - _cel_MutableMapValueEntry** ents = - (_cel_MutableMapValueEntry**) - map_value->content.ptr[_cel_MutableMapValueContent_kPtrOffset]; - const size_t mask = - (size_t)map_value->content.u32[_cel_MutableMapValueContent_kCapOffset] - - 1; - size_t bit = cel_HashState_Finalize( - _cel_MapValueKey_Hash(key, cel_HashState_Initialize())) & - mask; - _cel_MutableMapValueEntry* ent; - for (ent = ents[bit]; ent != cel_nullptr; ent = ents[(++bit) & mask]) { - if (_cel_MapValueKey_Equals(&ent->key, key)) { - if (out_key != cel_nullptr) { - *out_key = &ent->key; - } - *out_value = &ent->value; - return _cel_MutableMapValueInsertResult_kReplaced; - } - } - size_t threshold = (size_t)cap * 2 / 3; - if (len > threshold) { - // Refuse insertion. We must have failed to resize before. - return _cel_MutableMapValueInsertResult_kOutOfMemory; - } - ent = cel_Arena_Malloc(arena, sizeof(_cel_MutableMapValueEntry), cel_nullptr); - if (CEL_UNLIKELY(ent == cel_nullptr)) { - return _cel_MutableMapValueInsertResult_kOutOfMemory; - } - ent->key = *key; - if (out_key != cel_nullptr) { - *out_key = &ent->key; - } - *out_value = &ent->value; - ents[bit] = ent; - map_value->content.u32[_cel_MutableMapValueContent_kLenOffset] = ++len; - - if (len > threshold) { - (void)_cel_MutableMapValue_Resize(map_value, ents, cap << 1, cap, len, - arena); - } - - return _cel_MutableMapValueInsertResult_kInserted; -} - -static cel_MapValueIterator* cel_nullable _cel_MutableMapValue_NewIterator( - const cel_MapValueVTable* cel_nonnull vtable, cel_ValueContent content, - const cel_ValueContext* cel_nonnull context, - cel_Status* cel_nonnull status) { - CEL_ASSERT_EQ(vtable, &_cel_MutableMapValueVTable); - CEL_ASSERT_NOT_NULL(context); - CEL_ASSERT_NOT_NULL(status); - - if (CEL_UNLIKELY(!cel_Status_Ok(status))) { - return cel_nullptr; - } - - uint32_t len = content.u32[_cel_MutableMapValueContent_kLenOffset]; - if (len == 0) { - return &_cel_EmptyMapValueIterator; - } - - _cel_MutableMapValueIterator* iter = - (_cel_MutableMapValueIterator*)cel_Allocator_Malloc( - context->alloc, sizeof(_cel_MutableMapValueIterator), cel_nullptr); - if (CEL_UNLIKELY(iter == cel_nullptr)) { - cel_OutOfMemoryStatus(status); - return cel_nullptr; - } - - _cel_MutableMapValueEntry** ents = - (_cel_MutableMapValueEntry**) - content.ptr[_cel_MutableMapValueContent_kPtrOffset]; - iter->super.vtable = &_cel_MutableMapValueIteratorVTable; - iter->alloc = context->alloc; - iter->ents = ents; - iter->len = iter->rem = len; - iter->cap = content.u32[_cel_MutableMapValueContent_kCapOffset]; - - size_t bit; - for (bit = 0; ents[bit] == cel_nullptr; ++bit) { - } - iter->bit = bit; - - return &iter->super; -} - -const cel_MapValueVTable _cel_MutableMapValueVTable = { - .Equals = cel_nullptr, - .FastSize = &_cel_MutableMapValue_FastSize, - .SlowSize = &_cel_MutableMapValue_SlowSize, - .Get = &_cel_MutableMapValue_Get, - .Find = &_cel_MutableMapValue_Find, - .Has = &_cel_MutableMapValue_Has, - .NewIterator = &_cel_MutableMapValue_NewIterator, -}; - -static void _cel_MutableMapValueIterator_Delete( - cel_ValueIterator* cel_nonnull iterator) { - CEL_ASSERT_NOT_NULL(iterator); - CEL_ASSERT_EQ( - iterator->vtable, - (const cel_ValueIteratorVTable*)&_cel_MutableMapValueIteratorVTable); - - _cel_MutableMapValueIterator* iter = - cel_containerof(iterator, _cel_MutableMapValueIterator, super); - cel_Allocator_FreeSized(iter->alloc, iter, sizeof(*iter)); -} - -static bool _cel_MutableMapValueIterator_Next1( - cel_ValueIterator* cel_nonnull iterator, - const cel_ValueContext* cel_nonnull context, - cel_Value* cel_nonnull key_or_value, cel_Status* cel_nonnull status) { - CEL_ASSERT_NOT_NULL(iterator); - CEL_ASSERT_EQ(iterator->vtable, &_cel_MutableMapValueIteratorVTable.super); - CEL_ASSERT_NOT_NULL(context); - CEL_ASSERT_NOT_NULL(key_or_value); - CEL_ASSERT_NOT_NULL(status); - - if (CEL_UNLIKELY(!cel_Status_Ok(status))) { - return false; - } - - _cel_MutableMapValueIterator* iter = - cel_containerof(iterator, _cel_MutableMapValueIterator, super); - if (_cel_MutableMapValueIterator_Done(iter)) { - return false; - } - - _cel_Value_SetMapValueKey(key_or_value, &iter->ents[iter->bit]->key); - --iter->rem; - if (iter->rem != 0) { - iter->bit = _cel_MutableMapValueIterator_Advance(iter); - } - return true; -} - -static bool _cel_MutableMapValueIterator_Next2( - cel_ValueIterator* cel_nonnull iterator, - const cel_ValueContext* cel_nonnull context, cel_Value* cel_nonnull key, - cel_Value* cel_nonnull value, cel_Status* cel_nonnull status) { - CEL_ASSERT_NOT_NULL(iterator); - CEL_ASSERT_EQ(iterator->vtable, &_cel_MutableMapValueIteratorVTable.super); - CEL_ASSERT_NOT_NULL(context); - CEL_ASSERT_NOT_NULL(key); - CEL_ASSERT_NOT_NULL(value); - CEL_ASSERT_NOT_NULL(status); - - if (CEL_UNLIKELY(!cel_Status_Ok(status))) { - return false; - } - - _cel_MutableMapValueIterator* iter = - cel_containerof(iterator, _cel_MutableMapValueIterator, super); - if (_cel_MutableMapValueIterator_Done(iter)) { - return false; - } - - _cel_MutableMapValueEntry* ent = iter->ents[iter->bit]; - _cel_Value_SetMapValueKey(key, &ent->key); - *value = ent->value; - --iter->rem; - if (iter->rem != 0) { - iter->bit = _cel_MutableMapValueIterator_Advance(iter); - } - return true; -} - -static bool _cel_MutableMapValueIterator_Remaining( - const cel_ValueIterator* cel_nonnull iterator, - size_t* cel_nonnull remaining) { - CEL_ASSERT_NOT_NULL(iterator); - CEL_ASSERT_EQ(iterator->vtable, &_cel_MutableMapValueIteratorVTable.super); - CEL_ASSERT_NOT_NULL(remaining); - - _cel_MutableMapValueIterator* iter = - cel_containerof(iterator, _cel_MutableMapValueIterator, super); - - *remaining = iter->rem; - return true; -} - -static bool _cel_MutableMapValueIterator_Next( - cel_MapValueIterator* cel_nonnull iterator, - const cel_ValueContext* cel_nonnull context, - cel_MapValueKey* cel_nullable key, cel_Value* cel_nonnull value, - cel_Status* cel_nonnull status) { - CEL_ASSERT_NOT_NULL(iterator); - CEL_ASSERT_EQ(iterator->vtable, &_cel_MutableMapValueIteratorVTable); - CEL_ASSERT_NOT_NULL(context); - CEL_ASSERT_NOT_NULL(key); - CEL_ASSERT_NOT_NULL(value); - CEL_ASSERT_NOT_NULL(status); - - if (CEL_UNLIKELY(!cel_Status_Ok(status))) { - return false; - } - - _cel_MutableMapValueIterator* iter = - cel_containerof(iterator, _cel_MutableMapValueIterator, super); - if (_cel_MutableMapValueIterator_Done(iter)) { - return false; - } - - _cel_MutableMapValueEntry* ent = iter->ents[iter->bit]; - if (key != cel_nullptr) { - *key = ent->key; - } - *value = ent->value; - --iter->rem; - if (iter->rem != 0) { - iter->bit = _cel_MutableMapValueIterator_Advance(iter); - } - return true; -} - -static const cel_MapValueIteratorVTable _cel_MutableMapValueIteratorVTable = { - .super = - { - .Delete = &_cel_MutableMapValueIterator_Delete, - .Next1 = &_cel_MutableMapValueIterator_Next1, - .Next2 = &_cel_MutableMapValueIterator_Next2, - .Remaining = &_cel_MutableMapValueIterator_Remaining, - }, - .Next = &_cel_MutableMapValueIterator_Next, -}; diff --git a/cel-c/src/opaque_value.c b/cel-c/src/opaque_value.c deleted file mode 100644 index 7bad675..0000000 --- a/cel-c/src/opaque_value.c +++ /dev/null @@ -1,66 +0,0 @@ -// Copyright 2025 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include -#include -#include - -#include "cel-c/assert.h" -#include "cel-c/config.h" -#include "cel-c/status.h" -#include "cel-c/string_view.h" -#include "cel-c/value.h" - -bool cel_OpaqueValue_Equals(const cel_OpaqueValue* cel_nonnull opaque_value, - const cel_ValueContext* cel_nonnull context, - const cel_OpaqueValue* cel_nonnull other, - cel_Value* cel_nonnull result, - cel_Status* cel_nonnull status) { - CEL_ASSERT_NOT_NULL(opaque_value); - CEL_ASSERT_NOT_NULL(context); - CEL_ASSERT_NOT_NULL(other); - CEL_ASSERT_NOT_NULL(result); - CEL_ASSERT_NOT_NULL(status); - - if (CEL_UNLIKELY(!cel_Status_Ok(status))) { - return false; - } - - if (cel_StringView_Equals(cel_OpaqueValue_TypeName(opaque_value), - cel_OpaqueValue_TypeName(other))) { - if (opaque_value->vtable->Equals != cel_nullptr) { - if ((*opaque_value->vtable->Equals)(opaque_value->vtable, - opaque_value->content, context, other, - result, status)) { - return true; - } - if (CEL_UNLIKELY(!cel_Status_Ok(status))) { - return false; - } - } - if (other->vtable->Equals != cel_nullptr && - other->vtable->Equals != opaque_value->vtable->Equals) { - if ((*other->vtable->Equals)(other->vtable, other->content, context, - opaque_value, result, status)) { - return true; - } - if (CEL_UNLIKELY(!cel_Status_Ok(status))) { - return false; - } - } - } - - cel_Value_SetFalse(result); - return true; -} diff --git a/cel-c/src/optional_value.c b/cel-c/src/optional_value.c deleted file mode 100644 index 1b181d4..0000000 --- a/cel-c/src/optional_value.c +++ /dev/null @@ -1,625 +0,0 @@ -// Copyright 2025 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include -#include -#include - -#include "cel-c/arena.h" -#include "cel-c/assert.h" -#include "cel-c/config.h" -#include "cel-c/duration.h" -#include "cel-c/error.h" -#include "cel-c/error_code.h" -#include "cel-c/status.h" -#include "cel-c/string_view.h" -#include "cel-c/timestamp.h" -#include "cel-c/value.h" -#include "cel-c/value_kind.h" - -static const cel_OptionalValueVTable _cel_OptionalValueVTables[11]; - -#define _cel_EmptyOptionalValueVTable _cel_OptionalValueVTables[0] -#define _cel_NullOptionalValueVTable _cel_OptionalValueVTables[1] -#define _cel_BoolOptionalValueVTable _cel_OptionalValueVTables[2] -#define _cel_IntOptionalValueVTable _cel_OptionalValueVTables[3] -#define _cel_UintOptionalValueVTable _cel_OptionalValueVTables[4] -#define _cel_DoubleOptionalValueVTable _cel_OptionalValueVTables[5] -#define _cel_BytesOptionalValueVTable _cel_OptionalValueVTables[6] -#define _cel_StringOptionalValueVTable _cel_OptionalValueVTables[7] -#define _cel_DurationOptionalValueVTable _cel_OptionalValueVTables[8] -#define _cel_TimestampOptionalValueVTable _cel_OptionalValueVTables[9] -#define _cel_OptionalValueVTable _cel_OptionalValueVTables[10] - -static void _cel_EmptyOptionalValue_Set( - cel_OptionalValue* cel_nonnull optional_value) { - CEL_ASSERT_NOT_NULL(optional_value); - - optional_value->vtable = &_cel_EmptyOptionalValueVTable; -} - -static void _cel_NullOptionalValue_Set( - cel_OptionalValue* cel_nonnull optional_value) { - CEL_ASSERT_NOT_NULL(optional_value); - - optional_value->vtable = &_cel_NullOptionalValueVTable; -} - -static void _cel_BoolOptionalValue_Set( - cel_OptionalValue* cel_nonnull optional_value, bool value) { - CEL_ASSERT_NOT_NULL(optional_value); - - optional_value->vtable = &_cel_BoolOptionalValueVTable; - optional_value->content.b[0] = value; -} - -static void _cel_IntOptionalValue_Set( - cel_OptionalValue* cel_nonnull optional_value, int64_t value) { - CEL_ASSERT_NOT_NULL(optional_value); - - optional_value->vtable = &_cel_IntOptionalValueVTable; - optional_value->content.i64[0] = value; -} - -static void _cel_UintOptionalValue_Set( - cel_OptionalValue* cel_nonnull optional_value, uint64_t value) { - CEL_ASSERT_NOT_NULL(optional_value); - - optional_value->vtable = &_cel_UintOptionalValueVTable; - optional_value->content.u64[0] = value; -} - -static void _cel_DoubleOptionalValue_Set( - cel_OptionalValue* cel_nonnull optional_value, double value) { - CEL_ASSERT_NOT_NULL(optional_value); - - optional_value->vtable = &_cel_DoubleOptionalValueVTable; - optional_value->content.d[0] = value; -} - -static void _cel_BytesOptionalValue_Set( - cel_OptionalValue* cel_nonnull optional_value, cel_StringView value) { - CEL_ASSERT_NOT_NULL(optional_value); - - optional_value->vtable = &_cel_BytesOptionalValueVTable; - optional_value->content.str.data = value.data; - optional_value->content.str.size = value.size; -} - -static void _cel_StringOptionalValue_Set( - cel_OptionalValue* cel_nonnull optional_value, cel_StringView value) { - CEL_ASSERT_NOT_NULL(optional_value); - - optional_value->vtable = &_cel_StringOptionalValueVTable; - optional_value->content.str.data = value.data; - optional_value->content.str.size = value.size; -} - -static void _cel_DurationOptionalValue_Set( - cel_OptionalValue* cel_nonnull optional_value, cel_Duration value) { - CEL_ASSERT_NOT_NULL(optional_value); - - optional_value->vtable = &_cel_DurationOptionalValueVTable; - CEL_STATIC_ASSERT(sizeof(cel_Duration) <= sizeof(cel_ValueContent)); - CEL_STATIC_ASSERT(alignof(cel_Duration) <= alignof(cel_ValueContent)); - memcpy(&optional_value->content.raw, &value, sizeof(value)); -} - -static void _cel_TimestampOptionalValue_Set( - cel_OptionalValue* cel_nonnull optional_value, cel_Timestamp value) { - CEL_ASSERT_NOT_NULL(optional_value); - - optional_value->vtable = &_cel_TimestampOptionalValueVTable; - CEL_STATIC_ASSERT(sizeof(cel_Timestamp) <= sizeof(cel_ValueContent)); - CEL_STATIC_ASSERT(alignof(cel_Timestamp) <= alignof(cel_ValueContent)); - memcpy(&optional_value->content.raw, &value, sizeof(value)); -} - -static void _cel_OptionalValue_Set(cel_OptionalValue* cel_nonnull - optional_value, - const cel_Value* cel_nonnull value) { - CEL_ASSERT_NOT_NULL(optional_value); - CEL_ASSERT_NOT(cel_Value_IsNull(value)); - CEL_ASSERT_NOT(cel_Value_IsBool(value)); - CEL_ASSERT_NOT(cel_Value_IsInt(value)); - CEL_ASSERT_NOT(cel_Value_IsUint(value)); - CEL_ASSERT_NOT(cel_Value_IsDouble(value)); - CEL_ASSERT_NOT(cel_Value_IsBytes(value)); - CEL_ASSERT_NOT(cel_Value_IsString(value)); - CEL_ASSERT_NOT(cel_Value_IsDuration(value)); - CEL_ASSERT_NOT(cel_Value_IsTimestamp(value)); - CEL_ASSERT_NOT(cel_Value_IsError(value)); - - optional_value->vtable = &_cel_OptionalValueVTable; - optional_value->content.ptr[0] = (cel_Value*)value; -} - -CEL_ATTRIBUTE_NODISCARD -static bool _cel_OpaqueValue_IsOptional(const cel_OpaqueValue* opaque_value) { - return opaque_value->vtable >= - ((const cel_OpaqueValueVTable*)_cel_OptionalValueVTables) && - opaque_value->vtable <= - ((const cel_OpaqueValueVTable*)(_cel_OptionalValueVTables + - cel_arraysize( - _cel_OptionalValueVTables))); -} - -static bool _cel_OptionalValue_Equals( - const cel_OpaqueValueVTable* cel_nonnull vtable, cel_ValueContent content, - const cel_ValueContext* cel_nonnull context, - const cel_OpaqueValue* cel_nonnull other, cel_Value* cel_nonnull result, - cel_Status* cel_nonnull status) { - CEL_ASSERT_NOT_NULL(vtable); - CEL_ASSERT_NOT_NULL(context); - CEL_ASSERT_NOT_NULL(other); - CEL_ASSERT_NOT_NULL(result); - CEL_ASSERT_NOT_NULL(status); - - if (CEL_UNLIKELY(!cel_Status_Ok(status))) { - return false; - } - - if (!_cel_OpaqueValue_IsOptional(other)) { - // The only way to get here would be if somebody tried to mimic the optional - // value implementation, as the type name would have to be `optional_type`. - cel_Value_SetFalse(result); - return true; - } - - const bool has_value = - vtable != (const cel_OpaqueValueVTable*)&_cel_EmptyOptionalValueVTable; - const bool other_has_value = - other->vtable != - (const cel_OpaqueValueVTable*)&_cel_EmptyOptionalValueVTable; - if (has_value && other_has_value) { - cel_Value value; - cel_Value other_value; - if (((const cel_OptionalValueVTable*)vtable) - ->Value((const cel_OptionalValueVTable*)vtable, content, context, - &value, status) && - ((const cel_OptionalValueVTable*)other->vtable) - ->Value((const cel_OptionalValueVTable*)other->vtable, - other->content, context, &other_value, status)) { - return cel_Value_Equals(&value, context, &other_value, result, status); - } - CEL_ASSERT(!cel_Status_Ok(status)); - return false; - } - if (has_value != other_has_value) { - // One empty. - cel_Value_SetFalse(result); - return true; - } - // Both empty. - cel_Value_SetTrue(result); - return true; -} - -static cel_StringView _cel_OptionalValue_TypeName( - const cel_OpaqueValueVTable* cel_nonnull vtable, cel_ValueContent content) { - CEL_ASSERT_NOT_NULL(vtable); - - return cel_StringView_From("optional_type"); -} - -static bool _cel_EmptyOptionalValue_HasValue( - const cel_OptionalValueVTable* cel_nonnull vtable, cel_ValueContent content, - const cel_ValueContext* cel_nonnull context, cel_Value* cel_nonnull result, - cel_Status* cel_nonnull status) { - CEL_ASSERT_NOT_NULL(vtable); - CEL_ASSERT_NOT_NULL(context); - CEL_ASSERT_NOT_NULL(result); - CEL_ASSERT_NOT_NULL(status); - - if (CEL_UNLIKELY(!cel_Status_Ok(status))) { - return false; - } - - cel_Value_SetFalse(result); - return true; -} - -static bool _cel_EmptyOptionalValue_Value( - const cel_OptionalValueVTable* cel_nonnull vtable, cel_ValueContent content, - const cel_ValueContext* cel_nonnull context, cel_Value* cel_nonnull value, - cel_Status* cel_nonnull status) { - CEL_ASSERT_NOT_NULL(vtable); - CEL_ASSERT_NOT_NULL(context); - CEL_ASSERT_NOT_NULL(value); - CEL_ASSERT_NOT_NULL(status); - - if (CEL_UNLIKELY(!cel_Status_Ok(status))) { - return false; - } - - cel_Error* error = cel_Error_New(context->arena); - if (CEL_UNLIKELY(error == cel_nullptr)) { - cel_OutOfMemoryStatus(status); - return false; - } - cel_Error_SetCanonicalCode(error, cel_ErrorCode_kFailedPrecondition); - cel_Error_SetMessage(error, - cel_StringView_From("optional.none() dereference")); - cel_Value_SetError(value, error); - return true; -} - -static bool _cel_NullOptionalValue_Value( - const cel_OptionalValueVTable* cel_nonnull vtable, cel_ValueContent content, - const cel_ValueContext* cel_nonnull context, cel_Value* cel_nonnull value, - cel_Status* cel_nonnull status) { - CEL_ASSERT_NOT_NULL(vtable); - CEL_ASSERT_NOT_NULL(value); - CEL_ASSERT_NOT_NULL(status); - - if (CEL_UNLIKELY(!cel_Status_Ok(status))) { - return false; - } - - cel_Value_SetNull(value); - return true; -} - -static bool _cel_BoolOptionalValue_Value( - const cel_OptionalValueVTable* cel_nonnull vtable, cel_ValueContent content, - const cel_ValueContext* cel_nonnull context, cel_Value* cel_nonnull value, - cel_Status* cel_nonnull status) { - CEL_ASSERT_NOT_NULL(vtable); - CEL_ASSERT_NOT_NULL(value); - CEL_ASSERT_NOT_NULL(status); - - if (CEL_UNLIKELY(!cel_Status_Ok(status))) { - return false; - } - - cel_Value_SetBool(value, content.b[0]); - return true; -} - -static bool _cel_IntOptionalValue_Value( - const cel_OptionalValueVTable* cel_nonnull vtable, cel_ValueContent content, - const cel_ValueContext* cel_nonnull context, cel_Value* cel_nonnull value, - cel_Status* cel_nonnull status) { - CEL_ASSERT_NOT_NULL(vtable); - CEL_ASSERT_NOT_NULL(value); - CEL_ASSERT_NOT_NULL(status); - - if (CEL_UNLIKELY(!cel_Status_Ok(status))) { - return false; - } - - cel_Value_SetInt(value, content.i64[0]); - return true; -} - -static bool _cel_UintOptionalValue_Value( - const cel_OptionalValueVTable* cel_nonnull vtable, cel_ValueContent content, - const cel_ValueContext* cel_nonnull context, cel_Value* cel_nonnull value, - cel_Status* cel_nonnull status) { - CEL_ASSERT_NOT_NULL(vtable); - CEL_ASSERT_NOT_NULL(value); - CEL_ASSERT_NOT_NULL(status); - - if (CEL_UNLIKELY(!cel_Status_Ok(status))) { - return false; - } - - cel_Value_SetUint(value, content.u64[0]); - return true; -} - -static bool _cel_DoubleOptionalValue_Value( - const cel_OptionalValueVTable* cel_nonnull vtable, cel_ValueContent content, - const cel_ValueContext* cel_nonnull context, cel_Value* cel_nonnull value, - cel_Status* cel_nonnull status) { - CEL_ASSERT_NOT_NULL(vtable); - CEL_ASSERT_NOT_NULL(value); - CEL_ASSERT_NOT_NULL(status); - - if (CEL_UNLIKELY(!cel_Status_Ok(status))) { - return false; - } - - cel_Value_SetDouble(value, content.d[0]); - return true; -} - -static bool _cel_BytesOptionalValue_Value( - const cel_OptionalValueVTable* cel_nonnull vtable, cel_ValueContent content, - const cel_ValueContext* cel_nonnull context, cel_Value* cel_nonnull value, - cel_Status* cel_nonnull status) { - CEL_ASSERT_NOT_NULL(vtable); - CEL_ASSERT_NOT_NULL(value); - CEL_ASSERT_NOT_NULL(status); - - if (CEL_UNLIKELY(!cel_Status_Ok(status))) { - return false; - } - - cel_Value_SetBytes( - value, cel_StringView_FromArray(content.str.data, content.str.size)); - return true; -} - -static bool _cel_StringOptionalValue_Value( - const cel_OptionalValueVTable* cel_nonnull vtable, cel_ValueContent content, - const cel_ValueContext* cel_nonnull context, cel_Value* cel_nonnull value, - cel_Status* cel_nonnull status) { - CEL_ASSERT_NOT_NULL(vtable); - CEL_ASSERT_NOT_NULL(value); - CEL_ASSERT_NOT_NULL(status); - - if (CEL_UNLIKELY(!cel_Status_Ok(status))) { - return false; - } - - cel_Value_SetString( - value, cel_StringView_FromArray(content.str.data, content.str.size)); - return true; -} - -static bool _cel_DurationOptionalValue_Value( - const cel_OptionalValueVTable* cel_nonnull vtable, cel_ValueContent content, - const cel_ValueContext* cel_nonnull context, cel_Value* cel_nonnull value, - cel_Status* cel_nonnull status) { - CEL_ASSERT_NOT_NULL(vtable); - CEL_ASSERT_NOT_NULL(value); - CEL_ASSERT_NOT_NULL(status); - - if (CEL_UNLIKELY(!cel_Status_Ok(status))) { - return false; - } - - CEL_STATIC_ASSERT(sizeof(cel_Duration) <= sizeof(cel_ValueContent)); - CEL_STATIC_ASSERT(alignof(cel_Duration) <= alignof(cel_ValueContent)); - - cel_Duration d; - memcpy(&d, content.raw, sizeof(d)); - cel_Value_SetDuration(value, d); - return true; -} - -static bool _cel_TimestampOptionalValue_Value( - const cel_OptionalValueVTable* cel_nonnull vtable, cel_ValueContent content, - const cel_ValueContext* cel_nonnull context, cel_Value* cel_nonnull value, - cel_Status* cel_nonnull status) { - CEL_ASSERT_NOT_NULL(vtable); - CEL_ASSERT_NOT_NULL(value); - CEL_ASSERT_NOT_NULL(status); - - if (CEL_UNLIKELY(!cel_Status_Ok(status))) { - return false; - } - - CEL_STATIC_ASSERT(sizeof(cel_Timestamp) <= sizeof(cel_ValueContent)); - CEL_STATIC_ASSERT(alignof(cel_Timestamp) <= alignof(cel_ValueContent)); - cel_Timestamp t; - memcpy(&t, content.raw, sizeof(t)); - cel_Value_SetTimestamp(value, t); - return true; -} - -static bool _cel_OptionalValue_HasValue( - const cel_OptionalValueVTable* cel_nonnull vtable, cel_ValueContent content, - const cel_ValueContext* cel_nonnull context, cel_Value* cel_nonnull result, - cel_Status* cel_nonnull status) { - CEL_ASSERT_NOT_NULL(vtable); - CEL_ASSERT_NOT_NULL(context); - CEL_ASSERT_NOT_NULL(result); - CEL_ASSERT_NOT_NULL(status); - - if (CEL_UNLIKELY(!cel_Status_Ok(status))) { - return false; - } - - cel_Value_SetTrue(result); - return true; -} - -static bool _cel_OptionalValue_Value( - const cel_OptionalValueVTable* cel_nonnull vtable, cel_ValueContent content, - const cel_ValueContext* cel_nonnull context, cel_Value* cel_nonnull value, - cel_Status* cel_nonnull status) { - CEL_ASSERT_NOT_NULL(vtable); - CEL_ASSERT_NOT_NULL(value); - CEL_ASSERT_NOT_NULL(status); - - if (CEL_UNLIKELY(!cel_Status_Ok(status))) { - return false; - } - - *value = *(const cel_Value*)content.ptr[0]; - return true; -} - -static const cel_OptionalValueVTable _cel_OptionalValueVTables[11] = { - // _cel_EmptyOptionalValueVTable - { - .super = - { - .Equals = &_cel_OptionalValue_Equals, - .TypeName = &_cel_OptionalValue_TypeName, - }, - .HasValue = &_cel_EmptyOptionalValue_HasValue, - .Value = &_cel_EmptyOptionalValue_Value, - }, - // _cel_NullOptionalValueVTable - { - .super = - { - .Equals = &_cel_OptionalValue_Equals, - .TypeName = &_cel_OptionalValue_TypeName, - }, - .HasValue = &_cel_OptionalValue_HasValue, - .Value = &_cel_NullOptionalValue_Value, - }, - // _cel_BoolOptionalValueVTable - { - .super = - { - .Equals = &_cel_OptionalValue_Equals, - .TypeName = &_cel_OptionalValue_TypeName, - }, - .HasValue = &_cel_OptionalValue_HasValue, - .Value = &_cel_BoolOptionalValue_Value, - }, - // _cel_IntOptionalValueVTable - { - .super = - { - .Equals = &_cel_OptionalValue_Equals, - .TypeName = &_cel_OptionalValue_TypeName, - }, - .HasValue = &_cel_OptionalValue_HasValue, - .Value = &_cel_IntOptionalValue_Value, - }, - // _cel_UintOptionalValueVTable - { - .super = - { - .Equals = &_cel_OptionalValue_Equals, - .TypeName = &_cel_OptionalValue_TypeName, - }, - .HasValue = &_cel_OptionalValue_HasValue, - .Value = &_cel_UintOptionalValue_Value, - }, - // _cel_DoubleOptionalValueVTable - { - .super = - { - .Equals = &_cel_OptionalValue_Equals, - .TypeName = &_cel_OptionalValue_TypeName, - }, - .HasValue = &_cel_OptionalValue_HasValue, - .Value = &_cel_DoubleOptionalValue_Value, - }, - // _cel_BytesOptionalValueVTable - { - .super = - { - .Equals = &_cel_OptionalValue_Equals, - .TypeName = &_cel_OptionalValue_TypeName, - }, - .HasValue = &_cel_OptionalValue_HasValue, - .Value = &_cel_BytesOptionalValue_Value, - }, - // _cel_StringOptionalValueVTable - { - .super = - { - .Equals = &_cel_OptionalValue_Equals, - .TypeName = &_cel_OptionalValue_TypeName, - }, - .HasValue = &_cel_OptionalValue_HasValue, - .Value = &_cel_StringOptionalValue_Value, - }, - // _cel_DurationOptionalValueVTable - { - .super = - { - .Equals = &_cel_OptionalValue_Equals, - .TypeName = &_cel_OptionalValue_TypeName, - }, - .HasValue = &_cel_OptionalValue_HasValue, - .Value = &_cel_DurationOptionalValue_Value, - }, - // _cel_TimestampOptionalValueVTable - { - .super = - { - .Equals = &_cel_OptionalValue_Equals, - .TypeName = &_cel_OptionalValue_TypeName, - }, - .HasValue = &_cel_OptionalValue_HasValue, - .Value = &_cel_TimestampOptionalValue_Value, - }, - // _cel_OptionalValueVTable - { - .super = - { - .Equals = &_cel_OptionalValue_Equals, - .TypeName = &_cel_OptionalValue_TypeName, - }, - .HasValue = &_cel_OptionalValue_HasValue, - .Value = &_cel_OptionalValue_Value, - }, -}; - -cel_OptionalValue* cel_nonnull -cel_OptionalValue_Empty(cel_OptionalValue* cel_nonnull optional_value) { - CEL_ASSERT_NOT_NULL(optional_value); - - _cel_EmptyOptionalValue_Set(optional_value); - return optional_value; -} - -bool cel_OptionalValue_Of(cel_OptionalValue* cel_nonnull optional_value, - const cel_Value* cel_nonnull value, - cel_Arena* cel_nonnull arena) { - CEL_ASSERT_NOT_NULL(optional_value); - CEL_ASSERT_NOT_NULL(value); - CEL_ASSERT_NOT_NULL(arena); - - switch (cel_Value_Kind(value)) { - case cel_ValueKind_kNull: - _cel_NullOptionalValue_Set(optional_value); - return true; - case cel_ValueKind_kBool: - _cel_BoolOptionalValue_Set(optional_value, cel_Value_GetBool(value)); - return true; - case cel_ValueKind_kInt: - _cel_IntOptionalValue_Set(optional_value, cel_Value_GetInt(value)); - return true; - case cel_ValueKind_kUint: - _cel_UintOptionalValue_Set(optional_value, cel_Value_GetUint(value)); - return true; - case cel_ValueKind_kDouble: - _cel_DoubleOptionalValue_Set(optional_value, cel_Value_GetDouble(value)); - return true; - case cel_ValueKind_kBytes: - _cel_BytesOptionalValue_Set(optional_value, cel_Value_GetBytes(value)); - return true; - case cel_ValueKind_kString: - _cel_StringOptionalValue_Set(optional_value, cel_Value_GetString(value)); - return true; - case cel_ValueKind_kDuration: - _cel_DurationOptionalValue_Set(optional_value, - cel_Value_GetDuration(value)); - return true; - case cel_ValueKind_kTimestamp: - _cel_TimestampOptionalValue_Set(optional_value, - cel_Value_GetTimestamp(value)); - return true; - default: { - cel_Value* value_ptr = - (cel_Value*)cel_Arena_Malloc(arena, sizeof(cel_Value), cel_nullptr); - if (CEL_UNLIKELY(value_ptr == cel_nullptr)) { - return false; - } - *value_ptr = *value; - _cel_OptionalValue_Set(optional_value, value_ptr); - return true; - } - } -} - -bool cel_Value_IsOptional(const cel_Value* cel_nonnull value) { - return cel_Value_IsOpaque(value) && - _cel_OpaqueValue_IsOptional(cel_Value_GetOpaque(value)); -} - -bool cel_OpaqueValue_IsOptional( - const cel_OpaqueValue* cel_nonnull opaque_value) { - return _cel_OpaqueValue_IsOptional(opaque_value); -} diff --git a/cel-c/src/parsed_map_field_value.c b/cel-c/src/parsed_map_field_value.c deleted file mode 100644 index 326ec71..0000000 --- a/cel-c/src/parsed_map_field_value.c +++ /dev/null @@ -1,461 +0,0 @@ -// Copyright 2025 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "cel-c/src/parsed_map_field_value.h" - -#include -#include -#include -#include - -#include "cel-c/alloc.h" -#include "cel-c/assert.h" -#include "cel-c/config.h" -#include "cel-c/error.h" -#include "cel-c/error_code.h" -#include "cel-c/status.h" -#include "cel-c/status_code.h" -#include "cel-c/string_view.h" -#include "cel-c/value.h" -#include "cel-c/src/map_value.h" -#include "cel-c/src/message_equality.h" -#include "upb/message/array.h" -#include "upb/message/map.h" -#include "upb/message/message.h" -#include "upb/reflection/def.h" - -static const cel_MapValueIteratorVTable _cel_ParsedMapFieldValueIteratorVTable; - -typedef struct { - cel_MapValueIterator base; - cel_Allocator* cel_nonnull alloc; - const upb_Message* cel_nonnull message; - const upb_FieldDef* cel_nonnull field_key_def; - const upb_FieldDef* cel_nonnull field_val_def; - const upb_Map* cel_nullability_unknown field_val; - size_t iter; - size_t remain; -} _cel_ParsedMapFieldValueIterator; - -static bool _cel_ParsedMapFieldValue_Equals( - const cel_MapValueVTable* cel_nonnull vtable, cel_ValueContent content, - const cel_ValueContext* cel_nonnull context, - const cel_MapValue* cel_nonnull other, cel_Value* cel_nonnull result, - cel_Status* cel_nonnull status) { - CEL_ASSERT_EQ(vtable, &_cel_ParsedMapFieldValueVTable); - CEL_ASSERT_NOT_NULL(context); - CEL_ASSERT_NOT_NULL(other); - CEL_ASSERT_NOT_NULL(result); - CEL_ASSERT_NOT_NULL(status); - - if (CEL_UNLIKELY(!cel_Status_Ok(status))) { - return false; - } - - if (other->vtable == &_cel_ParsedMapFieldValueVTable) { - upb_MessageValue field_val; - upb_MessageValue other_field_val; - field_val.map_val = (const upb_Map*)content.ptr[0]; - other_field_val.map_val = (const upb_Map*)other->content.ptr[0]; - const upb_FieldDef* field_def = (const upb_FieldDef*)content.ptr[1]; - const upb_FieldDef* other_field_def = - (const upb_FieldDef*)other->content.ptr[1]; - switch (_cel_MessageField_Equals( - field_val, field_def, other_field_val, other_field_def, - context->def_pool, context->well_known_types, context->alloc)) { - case _cel_MessageEquality_kEqual: - cel_Value_SetTrue(result); - return true; - case _cel_MessageEquality_kNotEqual: - cel_Value_SetFalse(result); - return true; - case _cel_MessageEquality_kOutOfMemory: - cel_OutOfMemoryStatus(status); - return false; - case _cel_MessageEquality_kMaxDepthExceeded: - cel_Status_SetCanonicalCode(status, cel_StatusCode_kInvalidArgument); - cel_Status_SetMessage( - status, cel_StringView_From("max message depth exceeded")); - return false; - } - } - - // Fallback to default implementation. - return false; -} - -static bool _cel_ParsedMapFieldValue_FastSize( - const cel_MapValueVTable* cel_nonnull vtable, cel_ValueContent content, - size_t* cel_nonnull size) { - CEL_ASSERT_EQ(vtable, &_cel_ParsedMapFieldValueVTable); - CEL_ASSERT_NOT_NULL(size); - - const upb_Map* field_val = (const upb_Map*)content.ptr[0]; - *size = field_val != cel_nullptr ? upb_Map_Size(field_val) : (size_t)0; - return true; -} - -static bool _cel_ParsedMapFieldValue_SlowSize( - const cel_MapValueVTable* cel_nonnull vtable, cel_ValueContent content, - const cel_ValueContext* cel_nonnull context, cel_Value* cel_nonnull size, - cel_Status* cel_nonnull status) { - CEL_ASSERT_EQ(vtable, &_cel_ParsedMapFieldValueVTable); - CEL_ASSERT_NOT_NULL(context); - CEL_ASSERT_NOT_NULL(size); - CEL_ASSERT_NOT_NULL(status); - - if (CEL_UNLIKELY(!cel_Status_Ok(status))) { - return false; - } - - const upb_Map* field_val = (const upb_Map*)content.ptr[0]; - cel_Value_SetInt(size, field_val != cel_nullptr - ? (int64_t)upb_Map_Size(field_val) - : (int64_t)0); - return true; -} - -static bool _cel_ParsedMapFieldValue_Get( - const cel_MapValueVTable* cel_nonnull vtable, cel_ValueContent content, - const cel_ValueContext* cel_nonnull context, - const cel_MapValueKey* cel_nonnull key, cel_Value* cel_nonnull value, - cel_Status* cel_nonnull status) { - CEL_ASSERT_EQ(vtable, &_cel_ParsedMapFieldValueVTable); - CEL_ASSERT_NOT_NULL(context); - CEL_ASSERT_NOT_NULL(key); - CEL_ASSERT_NOT_NULL(value); - CEL_ASSERT_NOT_NULL(status); - - if (CEL_UNLIKELY(!cel_Status_Ok(status))) { - return false; - } - - const upb_FieldDef* field_def = (const upb_FieldDef*)content.ptr[1]; - const upb_Map* field_val = (const upb_Map*)content.ptr[0]; - - if (field_val != cel_nullptr && upb_Map_Size(field_val) > 0) { - const upb_MessageDef* field_entry_def = - upb_FieldDef_MessageSubDef(field_def); - const upb_FieldDef* field_key_def = upb_MessageDef_FindFieldByNumber( - field_entry_def, kUpb_MapEntry_KeyFieldNumber); - - upb_MessageValue message_key; - if (!_cel_MapValueKey_ToMessageValue(key, upb_FieldDef_CType(field_key_def), - &message_key)) { - goto no_such_key; - } - - upb_MessageValue message_val; - if (!upb_Map_Get(field_val, message_key, &message_val)) { - goto no_such_key; - } - - const upb_FieldDef* field_val_def = upb_MessageDef_FindFieldByNumber( - field_entry_def, kUpb_MapEntry_ValueFieldNumber); - return cel_Value_FromMapFieldValue(value, context, message_val, - field_val_def, status); - } - -no_such_key: { - cel_Error* error = cel_Error_New(context->arena); - if (CEL_UNLIKELY(error == cel_nullptr)) { - cel_OutOfMemoryStatus(status); - return false; - } - cel_Error_SetCanonicalCode(error, cel_ErrorCode_kNotFound); - cel_Error_SetMessage(error, cel_StringView_From("no such key")); - cel_Value_SetError(value, error); - return true; -} -} - -static bool _cel_ParsedMapFieldValue_Find( - const cel_MapValueVTable* cel_nonnull vtable, cel_ValueContent content, - const cel_ValueContext* cel_nonnull context, - const cel_MapValueKey* cel_nonnull key, cel_Value* cel_nonnull value, - cel_Status* cel_nonnull status) { - CEL_ASSERT_EQ(vtable, &_cel_ParsedMapFieldValueVTable); - CEL_ASSERT_NOT_NULL(context); - CEL_ASSERT_NOT_NULL(key); - CEL_ASSERT_NOT_NULL(value); - CEL_ASSERT_NOT_NULL(status); - - if (CEL_UNLIKELY(!cel_Status_Ok(status))) { - return false; - } - - const upb_FieldDef* field_def = (const upb_FieldDef*)content.ptr[1]; - const upb_Map* field_val = (const upb_Map*)content.ptr[0]; - - if (field_val != cel_nullptr && upb_Map_Size(field_val) > 0) { - const upb_MessageDef* field_entry_def = - upb_FieldDef_MessageSubDef(field_def); - const upb_FieldDef* field_key_def = upb_MessageDef_FindFieldByNumber( - field_entry_def, kUpb_MapEntry_KeyFieldNumber); - - upb_MessageValue message_key; - if (!_cel_MapValueKey_ToMessageValue(key, upb_FieldDef_CType(field_key_def), - &message_key)) { - return false; - } - - upb_MessageValue message_val; - if (!upb_Map_Get(field_val, message_key, &message_val)) { - return false; - } - - const upb_FieldDef* field_val_def = upb_MessageDef_FindFieldByNumber( - field_entry_def, kUpb_MapEntry_ValueFieldNumber); - return cel_Value_FromMapFieldValue(value, context, message_val, - field_val_def, status); - } - - return false; -} - -static bool _cel_ParsedMapFieldValue_Has( - const cel_MapValueVTable* cel_nonnull vtable, cel_ValueContent content, - const cel_ValueContext* cel_nonnull context, - const cel_MapValueKey* cel_nonnull key, cel_Value* cel_nonnull result, - cel_Status* cel_nonnull status) { - CEL_ASSERT_EQ(vtable, &_cel_ParsedMapFieldValueVTable); - CEL_ASSERT_NOT_NULL(context); - CEL_ASSERT_NOT_NULL(key); - CEL_ASSERT_NOT_NULL(result); - CEL_ASSERT_NOT_NULL(status); - - if (CEL_UNLIKELY(!cel_Status_Ok(status))) { - return false; - } - - const upb_FieldDef* field_def = (const upb_FieldDef*)content.ptr[1]; - const upb_Map* field_val = (const upb_Map*)content.ptr[0]; - - if (field_val != cel_nullptr && upb_Map_Size(field_val) > 0) { - const upb_MessageDef* field_entry_def = - upb_FieldDef_MessageSubDef(field_def); - const upb_FieldDef* field_key_def = upb_MessageDef_FindFieldByNumber( - field_entry_def, kUpb_MapEntry_KeyFieldNumber); - - upb_MessageValue message_key; - if (!_cel_MapValueKey_ToMessageValue(key, upb_FieldDef_CType(field_key_def), - &message_key)) { - return false; - } - - upb_MessageValue message_val; - cel_Value_SetBool(result, - upb_Map_Get(field_val, message_key, &message_val)); - return true; - } - - cel_Value_SetFalse(result); - return true; -} - -static cel_MapValueIterator* cel_nullable _cel_ParsedMapFieldValue_NewIterator( - const cel_MapValueVTable* cel_nonnull vtable, cel_ValueContent content, - const cel_ValueContext* cel_nonnull context, - cel_Status* cel_nonnull status) { - CEL_ASSERT_EQ(vtable, &_cel_ParsedMapFieldValueVTable); - CEL_ASSERT_NOT_NULL(context); - CEL_ASSERT_NOT_NULL(status); - - if (CEL_UNLIKELY(!cel_Status_Ok(status))) { - return cel_nullptr; - } - - _cel_ParsedMapFieldValueIterator* iter = - (_cel_ParsedMapFieldValueIterator*)cel_Allocator_Malloc( - context->alloc, sizeof(_cel_ParsedMapFieldValueIterator), - cel_nullptr); - if (CEL_UNLIKELY(iter == cel_nullptr)) { - cel_OutOfMemoryStatus(status); - return cel_nullptr; - } - memset(iter, 0, sizeof(*iter)); - iter->base.vtable = &_cel_ParsedMapFieldValueIteratorVTable; - iter->alloc = context->alloc; - const upb_FieldDef* field_def = (const upb_FieldDef*)content.ptr[1]; - iter->field_val = (const upb_Map*)content.ptr[0]; - const upb_MessageDef* field_entry_def = upb_FieldDef_MessageSubDef(field_def); - iter->field_key_def = upb_MessageDef_FindFieldByNumber( - field_entry_def, kUpb_MapEntry_KeyFieldNumber); - iter->field_val_def = upb_MessageDef_FindFieldByNumber( - field_entry_def, kUpb_MapEntry_ValueFieldNumber); - iter->iter = kUpb_Map_Begin; - iter->remain = iter->field_val != cel_nullptr ? upb_Map_Size(iter->field_val) - : (size_t)0; - return &iter->base; -} - -const cel_MapValueVTable _cel_ParsedMapFieldValueVTable = { - .Equals = &_cel_ParsedMapFieldValue_Equals, - .FastSize = &_cel_ParsedMapFieldValue_FastSize, - .SlowSize = &_cel_ParsedMapFieldValue_SlowSize, - .Get = &_cel_ParsedMapFieldValue_Get, - .Find = &_cel_ParsedMapFieldValue_Find, - .Has = &_cel_ParsedMapFieldValue_Has, - .NewIterator = &_cel_ParsedMapFieldValue_NewIterator, -}; - -static void _cel_ParsedMapFieldValueIterator_Delete( - cel_ValueIterator* cel_nonnull iterator) { - CEL_ASSERT_NOT_NULL(iterator); - CEL_ASSERT_EQ(iterator->vtable, - &_cel_ParsedMapFieldValueIteratorVTable.super); - - _cel_ParsedMapFieldValueIterator* iter = - cel_containerof(iterator, _cel_ParsedMapFieldValueIterator, base); - cel_Allocator_FreeSized(iter->alloc, iter, sizeof(*iter)); -} - -static bool _cel_ParsedMapFieldValueIterator_Next1( - cel_ValueIterator* cel_nonnull iterator, - const cel_ValueContext* cel_nonnull context, - cel_Value* cel_nonnull key_or_value, cel_Status* cel_nonnull status) { - CEL_ASSERT_NOT_NULL(iterator); - CEL_ASSERT_EQ(iterator->vtable, - &_cel_ParsedMapFieldValueIteratorVTable.super); - CEL_ASSERT_NOT_NULL(context); - CEL_ASSERT_NOT_NULL(key_or_value); - CEL_ASSERT_NOT_NULL(status); - - if (CEL_UNLIKELY(!cel_Status_Ok(status))) { - return false; - } - - _cel_ParsedMapFieldValueIterator* iter = - cel_containerof(iterator, _cel_ParsedMapFieldValueIterator, base); - - upb_MessageValue entry_key; - upb_MessageValue entry_val; - size_t iter_next = iter->iter; - if (iter->field_val != cel_nullptr && - upb_Map_Next(iter->field_val, &entry_key, &entry_val, &iter_next)) { - const bool ok = cel_Value_FromMapFieldKey(key_or_value, context, entry_key, - iter->field_key_def, status); - if (ok) { - iter->iter = iter_next; - --iter->remain; - } - return ok; - } - - return false; -} - -static bool _cel_ParsedMapFieldValueIterator_Next2( - cel_ValueIterator* cel_nonnull iterator, - const cel_ValueContext* cel_nonnull context, cel_Value* cel_nonnull key, - cel_Value* cel_nonnull value, cel_Status* cel_nonnull status) { - CEL_ASSERT_NOT_NULL(iterator); - CEL_ASSERT_EQ(iterator->vtable, - &_cel_ParsedMapFieldValueIteratorVTable.super); - CEL_ASSERT_NOT_NULL(context); - CEL_ASSERT_NOT_NULL(key); - CEL_ASSERT_NOT_NULL(value); - CEL_ASSERT_NOT_NULL(status); - - if (CEL_UNLIKELY(!cel_Status_Ok(status))) { - return false; - } - - _cel_ParsedMapFieldValueIterator* iter = - cel_containerof(iterator, _cel_ParsedMapFieldValueIterator, base); - - upb_MessageValue entry_key; - upb_MessageValue entry_val; - size_t iter_next = iter->iter; - if (iter->field_val != cel_nullptr && - upb_Map_Next(iter->field_val, &entry_key, &entry_val, &iter_next)) { - bool ok = cel_Value_FromMapFieldKey(key, context, entry_key, - iter->field_key_def, status); - if (ok) { - ok = cel_Value_FromMapFieldValue(value, context, entry_val, - iter->field_val_def, status); - if (ok) { - iter->iter = iter_next; - --iter->remain; - } - } - return ok; - } - - return false; -} - -static bool _cel_ParsedMapFieldValueIterator_Remaining( - const cel_ValueIterator* cel_nonnull iterator, - size_t* cel_nonnull remaining) { - CEL_ASSERT_NOT_NULL(iterator); - CEL_ASSERT_EQ(iterator->vtable, - &_cel_ParsedMapFieldValueIteratorVTable.super); - CEL_ASSERT_NOT_NULL(remaining); - - _cel_ParsedMapFieldValueIterator* iter = - cel_containerof(iterator, _cel_ParsedMapFieldValueIterator, base); - *remaining = iter->remain; - return true; -} - -static bool _cel_ParsedMapFieldValueIterator_Next( - cel_MapValueIterator* cel_nonnull iterator, - const cel_ValueContext* cel_nonnull context, - cel_MapValueKey* cel_nullable key, cel_Value* cel_nonnull value, - cel_Status* cel_nonnull status) { - CEL_ASSERT_NOT_NULL(iterator); - CEL_ASSERT_EQ(iterator->vtable, &_cel_ParsedMapFieldValueIteratorVTable); - CEL_ASSERT_NOT_NULL(context); - CEL_ASSERT_NOT_NULL(key); - CEL_ASSERT_NOT_NULL(value); - CEL_ASSERT_NOT_NULL(status); - - if (CEL_UNLIKELY(!cel_Status_Ok(status))) { - return false; - } - - _cel_ParsedMapFieldValueIterator* iter = - cel_containerof(iterator, _cel_ParsedMapFieldValueIterator, base); - - upb_MessageValue entry_key; - upb_MessageValue entry_val; - size_t iter_next = iter->iter; - if (iter->field_val != cel_nullptr && - upb_Map_Next(iter->field_val, &entry_key, &entry_val, &iter_next)) { - _cel_MapValueKey_FromMessageValue( - key, upb_FieldDef_CType(iter->field_key_def), entry_key); - bool ok = cel_Value_FromMapFieldValue(value, context, entry_val, - iter->field_val_def, status); - if (ok) { - iter->iter = iter_next; - --iter->remain; - } - return ok; - } - - return false; -} - -static const cel_MapValueIteratorVTable _cel_ParsedMapFieldValueIteratorVTable = - { - .super = - { - .Delete = &_cel_ParsedMapFieldValueIterator_Delete, - .Next1 = &_cel_ParsedMapFieldValueIterator_Next1, - .Next2 = &_cel_ParsedMapFieldValueIterator_Next2, - .Remaining = &_cel_ParsedMapFieldValueIterator_Remaining, - }, - .Next = &_cel_ParsedMapFieldValueIterator_Next, -}; diff --git a/cel-c/src/parsed_message_value.c b/cel-c/src/parsed_message_value.c deleted file mode 100644 index c1ad99a..0000000 --- a/cel-c/src/parsed_message_value.c +++ /dev/null @@ -1,349 +0,0 @@ -// Copyright 2025 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "cel-c/src/parsed_message_value.h" - -#include -#include -#include -#include - -#include "cel-c/alloc.h" -#include "cel-c/assert.h" -#include "cel-c/config.h" -#include "cel-c/error.h" -#include "cel-c/error_code.h" -#include "cel-c/status.h" -#include "cel-c/status_code.h" -#include "cel-c/string_view.h" -#include "cel-c/value.h" -#include "cel-c/src/message_equality.h" -#include "upb/base/descriptor_constants.h" -#include "upb/message/array.h" -#include "upb/message/map.h" -#include "upb/message/message.h" -#include "upb/reflection/def.h" -#include "upb/reflection/message.h" - -static const cel_StructValueIteratorVTable - _cel_ParsedMessageValueIteratorVTable; - -typedef struct { - cel_StructValueIterator base; - cel_Allocator* cel_nonnull alloc; - const upb_Message* cel_nonnull message; - const upb_MessageDef* cel_nonnull message_def; - size_t iter; -} _cel_ParsedMessageValueIterator; - -static bool _cel_ParsedMessageValue_Equals( - const cel_StructValueVTable* cel_nonnull vtable, cel_ValueContent content, - const cel_ValueContext* cel_nonnull context, - const cel_StructValue* cel_nonnull other, cel_Value* cel_nonnull result, - cel_Status* cel_nonnull status) { - CEL_ASSERT_EQ(vtable, &_cel_ParsedMessageValueVTable); - CEL_ASSERT_NOT_NULL(context); - CEL_ASSERT_NOT_NULL(other); - CEL_ASSERT_NOT_NULL(result); - CEL_ASSERT_NOT_NULL(status); - - if (CEL_UNLIKELY(!cel_Status_Ok(status))) { - return false; - } - - if (other->vtable == &_cel_ParsedMessageValueVTable) { - const upb_Message* message = (const upb_Message*)content.ptr[0]; - const upb_Message* other_message = - (const upb_Message*)other->content.ptr[0]; - const upb_MessageDef* message_def = (const upb_MessageDef*)content.ptr[1]; - const upb_MessageDef* other_message_def = - (const upb_MessageDef*)other->content.ptr[1]; - CEL_ASSERT_EQ(message_def, other_message_def); - if (CEL_LIKELY(message_def == other_message_def)) { - switch (_cel_Message_Equals(message, other_message, other_message_def, - context->def_pool, context->well_known_types, - context->alloc)) { - case _cel_MessageEquality_kEqual: - cel_Value_SetTrue(result); - return true; - case _cel_MessageEquality_kNotEqual: - cel_Value_SetFalse(result); - return true; - case _cel_MessageEquality_kOutOfMemory: - cel_OutOfMemoryStatus(status); - return false; - case _cel_MessageEquality_kMaxDepthExceeded: - cel_Status_SetCanonicalCode(status, cel_StatusCode_kInvalidArgument); - cel_Status_SetMessage( - status, cel_StringView_From("max message depth exceeded")); - return false; - } - } - } - - // Fallback to default implementation. - return false; -} - -static cel_StringView _cel_ParsedMessageValue_TypeName( - const cel_StructValueVTable* cel_nonnull vtable, cel_ValueContent content) { - CEL_ASSERT_EQ(vtable, &_cel_ParsedMessageValueVTable); - - return cel_StringView_FromString( - upb_MessageDef_FullName((const upb_MessageDef*)content.ptr[1])); -} - -static bool _cel_ParsedMessageValue_Get( - const cel_StructValueVTable* cel_nonnull vtable, cel_ValueContent content, - const cel_ValueContext* cel_nonnull context, - const cel_StructValueKey* cel_nonnull key, cel_Value* cel_nonnull value, - cel_Status* cel_nonnull status) { - CEL_ASSERT_EQ(vtable, &_cel_ParsedMessageValueVTable); - - if (CEL_UNLIKELY(!cel_Status_Ok(status))) { - return false; - } - - const upb_Message* message = (const upb_Message*)content.ptr[0]; - const upb_MessageDef* message_def = (const upb_MessageDef*)content.ptr[1]; - const upb_FieldDef* field_def; - const cel_StructValueKeyKind key_kind = cel_StructValueKey_Kind(key); - switch (key_kind) { - case cel_StructValueKeyKind_kName: { - cel_StringView name = cel_StructValueKey_GetName(key); - field_def = upb_MessageDef_FindFieldByNameWithSize( - message_def, cel_StringView_Data(name), cel_StringView_Size(name)); - if (CEL_UNLIKELY(field_def == cel_nullptr)) { - cel_Error* error = cel_Error_New(context->arena); - if (CEL_UNLIKELY(error == cel_nullptr)) { - cel_OutOfMemoryStatus(status); - return false; - } - cel_Error_SetCanonicalCode(error, cel_ErrorCode_kNotFound); - cel_Error_SetMessage(error, cel_StringView_From("no such field")); - cel_Value_SetError(value, error); - return true; - } - } break; - case cel_StructValueKeyKind_kDef: - field_def = cel_StructValueKey_GetDef(key); - break; - default: - cel_InvalidArgumentStatusF( - status, "cel: unexpected struct value key kind: %d", key_kind); - return false; - } - - CEL_ASSERT_NOT_NULL(field_def); - - return cel_Value_FromField(value, context, - upb_Message_GetFieldByDef(message, field_def), - field_def, status); -} - -static bool _cel_ParsedMessageValue_Has( - const cel_StructValueVTable* cel_nonnull vtable, cel_ValueContent content, - const cel_ValueContext* cel_nonnull context, - const cel_StructValueKey* cel_nonnull key, cel_Value* cel_nonnull result, - cel_Status* cel_nonnull status) { - CEL_ASSERT_EQ(vtable, &_cel_ParsedMessageValueVTable); - - if (CEL_UNLIKELY(!cel_Status_Ok(status))) { - return false; - } - - const upb_Message* message = (const upb_Message*)content.ptr[0]; - const upb_MessageDef* message_def = (const upb_MessageDef*)content.ptr[1]; - const upb_FieldDef* field_def; - const cel_StructValueKeyKind key_kind = cel_StructValueKey_Kind(key); - switch (key_kind) { - case cel_StructValueKeyKind_kName: { - cel_StringView name = cel_StructValueKey_GetName(key); - field_def = upb_MessageDef_FindFieldByNameWithSize( - message_def, cel_StringView_Data(name), cel_StringView_Size(name)); - if (CEL_UNLIKELY(field_def == cel_nullptr)) { - cel_Error* error = cel_Error_New(context->arena); - if (CEL_UNLIKELY(error == cel_nullptr)) { - cel_OutOfMemoryStatus(status); - return false; - } - cel_Error_SetCanonicalCode(error, cel_ErrorCode_kNotFound); - cel_Error_SetMessage(error, cel_StringView_From("no such field")); - cel_Value_SetError(result, error); - return true; - } - } break; - case cel_StructValueKeyKind_kDef: - field_def = cel_StructValueKey_GetDef(key); - break; - default: - cel_InvalidArgumentStatusF( - status, "cel: unexpected struct value key kind: %d", key_kind); - return false; - } - - CEL_ASSERT_NOT_NULL(field_def); - - if (upb_FieldDef_IsMap(field_def)) { - upb_MessageValue value = upb_Message_GetFieldByDef(message, field_def); - cel_Value_SetBool(result, value.map_val != cel_nullptr && - upb_Map_Size(value.map_val) > 0); - } else if (upb_FieldDef_IsRepeated(field_def)) { - upb_MessageValue value = upb_Message_GetFieldByDef(message, field_def); - cel_Value_SetBool(result, value.array_val != cel_nullptr && - upb_Array_Size(value.array_val) > 0); - } else if (upb_FieldDef_HasPresence(field_def)) { - cel_Value_SetBool(result, upb_Message_HasFieldByDef(message, field_def)); - } else { - upb_MessageValue value = upb_Message_GetFieldByDef(message, field_def); - switch (upb_FieldDef_CType(field_def)) { - case kUpb_CType_Bool: - cel_Value_SetBool(result, value.bool_val); - break; - case kUpb_CType_Enum: - CEL_ATTRIBUTE_FALLTHROUGH; - case kUpb_CType_Int32: - cel_Value_SetBool(result, value.int32_val != 0); - break; - case kUpb_CType_Float: - CEL_ATTRIBUTE_FALLTHROUGH; - CEL_STATIC_ASSERT(sizeof(float) == sizeof(uint32_t)); - case kUpb_CType_UInt32: - cel_Value_SetBool(result, value.uint32_val != 0); - break; - case kUpb_CType_Int64: - cel_Value_SetBool(result, value.int64_val != 0); - break; - case kUpb_CType_Double: - CEL_ATTRIBUTE_FALLTHROUGH; - CEL_STATIC_ASSERT(sizeof(double) == sizeof(uint64_t)); - case kUpb_CType_UInt64: - cel_Value_SetBool(result, value.uint64_val != 0); - break; - case kUpb_CType_Bytes: - CEL_ATTRIBUTE_FALLTHROUGH; - case kUpb_CType_String: - cel_Value_SetBool(result, value.str_val.size != 0); - break; - case kUpb_CType_Message: - cel_Value_SetBool(result, value.msg_val != cel_nullptr); - break; - } - } - - return true; -} - -static cel_StructValueIterator* cel_nullable -_cel_ParsedMessageValue_NewIterator( - const cel_StructValueVTable* cel_nonnull vtable, cel_ValueContent content, - const cel_ValueContext* cel_nonnull context, - cel_Status* cel_nonnull status) { - CEL_ASSERT_EQ(vtable, &_cel_ParsedMessageValueVTable); - CEL_ASSERT_NOT_NULL(context); - CEL_ASSERT_NOT_NULL(status); - - if (CEL_UNLIKELY(!cel_Status_Ok(status))) { - return cel_nullptr; - } - - _cel_ParsedMessageValueIterator* iter = - (_cel_ParsedMessageValueIterator*)cel_Allocator_Malloc( - context->alloc, sizeof(_cel_ParsedMessageValueIterator), cel_nullptr); - if (CEL_UNLIKELY(iter == cel_nullptr)) { - cel_OutOfMemoryStatus(status); - return cel_nullptr; - } - memset(iter, 0, sizeof(*iter)); - iter->base.vtable = &_cel_ParsedMessageValueIteratorVTable; - iter->alloc = context->alloc; - iter->message = (const upb_Message*)content.ptr[0]; - iter->message_def = (const upb_MessageDef*)content.ptr[1]; - iter->iter = kUpb_Message_Begin; - return &iter->base; -} - -const cel_StructValueVTable _cel_ParsedMessageValueVTable = { - .Equals = &_cel_ParsedMessageValue_Equals, - .TypeName = &_cel_ParsedMessageValue_TypeName, - .Get = &_cel_ParsedMessageValue_Get, - .Has = &_cel_ParsedMessageValue_Has, - .NewIterator = &_cel_ParsedMessageValue_NewIterator, -}; - -static void _cel_ParsedMessageValueIterator_Delete( - cel_StructValueIterator* cel_nonnull iterator) { - CEL_ASSERT_NOT_NULL(iterator); - CEL_ASSERT_NOT_NULL(iterator->vtable); - CEL_ASSERT_EQ(iterator->vtable, &_cel_ParsedMessageValueIteratorVTable); - - _cel_ParsedMessageValueIterator* iter = - cel_containerof(iterator, _cel_ParsedMessageValueIterator, base); - cel_Allocator_FreeSized(iter->alloc, iter, sizeof(*iter)); -} - -static bool _cel_ParsedMessageValueIterator_Next( - cel_StructValueIterator* cel_nonnull iterator, - const cel_ValueContext* cel_nonnull context, - cel_StructValueKey* cel_nonnull key, cel_Value* cel_nullable value, - cel_Status* cel_nonnull status) { - CEL_ASSERT_NOT_NULL(iterator); - CEL_ASSERT_NOT_NULL(iterator->vtable); - CEL_ASSERT_EQ(iterator->vtable, &_cel_ParsedMessageValueIteratorVTable); - CEL_ASSERT_NOT_NULL(context); - CEL_ASSERT_NOT_NULL(key); - CEL_ASSERT_NOT_NULL(status); - - if (CEL_UNLIKELY(!cel_Status_Ok(status))) { - return false; - } - - _cel_ParsedMessageValueIterator* iter = - cel_containerof(iterator, _cel_ParsedMessageValueIterator, base); - const upb_FieldDef* field_def; - upb_MessageValue field_val; - size_t iter_next = iter->iter; - if (upb_Message_Next(iter->message, iter->message_def, context->def_pool, - &field_def, &field_val, &iter_next)) { - cel_StructValueKey_SetDef(key, field_def); - if (value != cel_nullptr) { - if (!cel_Value_FromField(value, context, field_val, field_def, status)) { - return false; - } - } - iter->iter = iter_next; - return true; - } - return false; -} - -static bool _cel_ParsedMessageValueIterator_Remaining( - const cel_StructValueIterator* cel_nonnull iterator, - size_t* cel_nonnull remaining) { - CEL_ASSERT_NOT_NULL(iterator); - CEL_ASSERT_NOT_NULL(iterator->vtable); - CEL_ASSERT_EQ(iterator->vtable, &_cel_ParsedMessageValueIteratorVTable); - CEL_ASSERT_NOT_NULL(remaining); - - // We do not know this in constant time, it requires iterating over all set - // fields to count. - return false; -} - -static const cel_StructValueIteratorVTable - _cel_ParsedMessageValueIteratorVTable = { - .Delete = &_cel_ParsedMessageValueIterator_Delete, - .Next = &_cel_ParsedMessageValueIterator_Next, - .Remaining = &_cel_ParsedMessageValueIterator_Remaining, -}; diff --git a/cel-c/src/parsed_repeated_field_value.c b/cel-c/src/parsed_repeated_field_value.c deleted file mode 100644 index 5ceab82..0000000 --- a/cel-c/src/parsed_repeated_field_value.c +++ /dev/null @@ -1,339 +0,0 @@ -// Copyright 2025 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "cel-c/src/parsed_repeated_field_value.h" - -#include -#include -#include -#include - -#include "cel-c/alloc.h" -#include "cel-c/assert.h" -#include "cel-c/config.h" -#include "cel-c/error.h" -#include "cel-c/error_code.h" -#include "cel-c/status.h" -#include "cel-c/status_code.h" -#include "cel-c/string_view.h" -#include "cel-c/value.h" -#include "cel-c/src/message_equality.h" -#include "upb/message/array.h" -#include "upb/message/message.h" -#include "upb/reflection/def.h" - -static const cel_ListValueIteratorVTable - _cel_ParsedRepeatedFieldValueIteratorVTable; - -typedef struct { - cel_ListValueIterator base; - cel_Allocator* cel_nonnull alloc; - const upb_Message* cel_nonnull message; - const upb_FieldDef* cel_nonnull field_def; - const upb_Array* cel_nullability_unknown field_val; - size_t index; - size_t remain; -} _cel_ParsedRepeatedFieldValueIterator; - -static bool _cel_ParsedRepeatedFieldValue_Equals( - const cel_ListValueVTable* cel_nonnull vtable, cel_ValueContent content, - const cel_ValueContext* cel_nonnull context, - const cel_ListValue* cel_nonnull other, cel_Value* cel_nonnull result, - cel_Status* cel_nonnull status) { - CEL_ASSERT_EQ(vtable, &_cel_ParsedRepeatedFieldValueVTable); - CEL_ASSERT_NOT_NULL(context); - CEL_ASSERT_NOT_NULL(other); - CEL_ASSERT_NOT_NULL(result); - CEL_ASSERT_NOT_NULL(status); - - if (CEL_UNLIKELY(!cel_Status_Ok(status))) { - return false; - } - - if (other->vtable == &_cel_ParsedRepeatedFieldValueVTable) { - upb_MessageValue field_val; - upb_MessageValue other_field_val; - field_val.array_val = (const upb_Array*)content.ptr[0]; - other_field_val.array_val = (const upb_Array*)other->content.ptr[0]; - const upb_FieldDef* field_def = (const upb_FieldDef*)content.ptr[1]; - const upb_FieldDef* other_field_def = - (const upb_FieldDef*)other->content.ptr[1]; - switch (_cel_MessageField_Equals( - field_val, field_def, other_field_val, other_field_def, - context->def_pool, context->well_known_types, context->alloc)) { - case _cel_MessageEquality_kEqual: - cel_Value_SetTrue(result); - return true; - case _cel_MessageEquality_kNotEqual: - cel_Value_SetFalse(result); - return true; - case _cel_MessageEquality_kOutOfMemory: - cel_OutOfMemoryStatus(status); - return false; - case _cel_MessageEquality_kMaxDepthExceeded: - cel_Status_SetCanonicalCode(status, cel_StatusCode_kInvalidArgument); - cel_Status_SetMessage( - status, cel_StringView_From("max message depth exceeded")); - return false; - } - } - - // Fallback to default implementation. - return false; -} - -static bool _cel_ParsedRepeatedFieldValue_FastSize( - const cel_ListValueVTable* cel_nonnull vtable, cel_ValueContent content, - size_t* cel_nonnull size) { - CEL_ASSERT_EQ(vtable, &_cel_ParsedRepeatedFieldValueVTable); - CEL_ASSERT_NOT_NULL(size); - - const upb_Array* field_val = (const upb_Array*)content.ptr[0]; - *size = field_val != cel_nullptr ? upb_Array_Size(field_val) : (size_t)0; - return true; -} - -static bool _cel_ParsedRepeatedFieldValue_SlowSize( - const cel_ListValueVTable* cel_nonnull vtable, cel_ValueContent content, - const cel_ValueContext* cel_nonnull context, cel_Value* cel_nonnull size, - cel_Status* cel_nonnull status) { - CEL_ASSERT_EQ(vtable, &_cel_ParsedRepeatedFieldValueVTable); - CEL_ASSERT_NOT_NULL(context); - CEL_ASSERT_NOT_NULL(size); - CEL_ASSERT_NOT_NULL(status); - - if (CEL_UNLIKELY(!cel_Status_Ok(status))) { - return false; - } - - const upb_Array* field_val = (const upb_Array*)content.ptr[0]; - cel_Value_SetInt(size, field_val != cel_nullptr - ? (int64_t)upb_Array_Size(field_val) - : (int64_t)0); - return true; -} - -static bool _cel_ParsedRepeatedFieldValue_Get( - const cel_ListValueVTable* cel_nonnull vtable, cel_ValueContent content, - const cel_ValueContext* cel_nonnull context, size_t index, - cel_Value* cel_nonnull element, cel_Status* cel_nonnull status) { - CEL_ASSERT_EQ(vtable, &_cel_ParsedRepeatedFieldValueVTable); - CEL_ASSERT_NOT_NULL(context); - CEL_ASSERT_NOT_NULL(element); - CEL_ASSERT_NOT_NULL(status); - - if (CEL_UNLIKELY(!cel_Status_Ok(status))) { - return false; - } - - const upb_FieldDef* field_def = (const upb_FieldDef*)content.ptr[1]; - const upb_Array* field_val = (const upb_Array*)content.ptr[0]; - - const size_t size = - field_val != cel_nullptr ? upb_Array_Size(field_val) : (size_t)0; - - if (CEL_UNLIKELY(index >= size)) { - cel_Error* error = cel_Error_New(context->arena); - if (CEL_UNLIKELY(error == cel_nullptr)) { - cel_OutOfMemoryStatus(status); - return false; - } - cel_Error_SetCanonicalCode(error, cel_ErrorCode_kOutOfRange); - cel_Error_SetMessage(error, cel_StringView_From("index out of range")); - cel_Value_SetError(element, error); - return true; - } - - return cel_Value_FromRepeatedFieldElement( - element, context, upb_Array_Get(field_val, index), field_def, status); -} - -static cel_ListValueIterator* cel_nullable -_cel_ParsedRepeatedFieldValue_NewIterator( - const cel_ListValueVTable* cel_nonnull vtable, cel_ValueContent content, - const cel_ValueContext* cel_nonnull context, - cel_Status* cel_nonnull status) { - CEL_ASSERT_EQ(vtable, &_cel_ParsedRepeatedFieldValueVTable); - CEL_ASSERT_NOT_NULL(context); - CEL_ASSERT_NOT_NULL(status); - - if (CEL_UNLIKELY(!cel_Status_Ok(status))) { - return cel_nullptr; - } - - _cel_ParsedRepeatedFieldValueIterator* iter = - (_cel_ParsedRepeatedFieldValueIterator*)cel_Allocator_Malloc( - context->alloc, sizeof(_cel_ParsedRepeatedFieldValueIterator), - cel_nullptr); - if (CEL_UNLIKELY(iter == cel_nullptr)) { - cel_OutOfMemoryStatus(status); - return cel_nullptr; - } - memset(iter, 0, sizeof(*iter)); - iter->base.vtable = &_cel_ParsedRepeatedFieldValueIteratorVTable; - iter->alloc = context->alloc; - iter->field_def = (const upb_FieldDef*)content.ptr[1]; - iter->field_val = (const upb_Array*)content.ptr[0]; - iter->index = 0; - iter->remain = iter->field_val != cel_nullptr - ? upb_Array_Size(iter->field_val) - : (size_t)0; - return &iter->base; -} - -const cel_ListValueVTable _cel_ParsedRepeatedFieldValueVTable = { - .Equals = &_cel_ParsedRepeatedFieldValue_Equals, - .FastSize = &_cel_ParsedRepeatedFieldValue_FastSize, - .SlowSize = &_cel_ParsedRepeatedFieldValue_SlowSize, - .Get = &_cel_ParsedRepeatedFieldValue_Get, - .NewIterator = &_cel_ParsedRepeatedFieldValue_NewIterator, -}; - -static void _cel_ParsedRepeatedFieldValueIterator_Delete( - cel_ValueIterator* cel_nonnull iterator) { - CEL_ASSERT_NOT_NULL(iterator); - CEL_ASSERT_EQ( - iterator->vtable, - (const cel_ValueIteratorVTable*)&_cel_ParsedRepeatedFieldValueIteratorVTable); - - _cel_ParsedRepeatedFieldValueIterator* iter = - cel_containerof(iterator, _cel_ParsedRepeatedFieldValueIterator, base); - cel_Allocator_FreeSized(iter->alloc, iter, sizeof(*iter)); -} - -static bool _cel_ParsedRepeatedFieldValueIterator_Next1( - cel_ValueIterator* cel_nonnull iterator, - const cel_ValueContext* cel_nonnull context, - cel_Value* cel_nonnull key_or_value, cel_Status* cel_nonnull status) { - CEL_ASSERT_NOT_NULL(iterator); - CEL_ASSERT_EQ( - iterator->vtable, - (const cel_ValueIteratorVTable*)&_cel_ParsedRepeatedFieldValueIteratorVTable); - CEL_ASSERT_NOT_NULL(context); - CEL_ASSERT_NOT_NULL(key_or_value); - CEL_ASSERT_NOT_NULL(status); - - if (CEL_UNLIKELY(!cel_Status_Ok(status))) { - return false; - } - - _cel_ParsedRepeatedFieldValueIterator* iter = - cel_containerof(iterator, _cel_ParsedRepeatedFieldValueIterator, base); - if (iter->remain == 0) { - return false; - } - - const bool ok = cel_Value_FromRepeatedFieldElement( - key_or_value, context, upb_Array_Get(iter->field_val, iter->index), - iter->field_def, status); - if (ok) { - ++iter->index; - --iter->remain; - } - return ok; -} - -static bool _cel_ParsedRepeatedFieldValueIterator_Next2( - cel_ValueIterator* cel_nonnull iterator, - const cel_ValueContext* cel_nonnull context, cel_Value* cel_nonnull key, - cel_Value* cel_nonnull value, cel_Status* cel_nonnull status) { - CEL_ASSERT_NOT_NULL(iterator); - CEL_ASSERT_EQ( - iterator->vtable, - (const cel_ValueIteratorVTable*)&_cel_ParsedRepeatedFieldValueIteratorVTable); - CEL_ASSERT_NOT_NULL(context); - CEL_ASSERT_NOT_NULL(key); - CEL_ASSERT_NOT_NULL(value); - CEL_ASSERT_NOT_NULL(status); - - if (CEL_UNLIKELY(!cel_Status_Ok(status))) { - return false; - } - - _cel_ParsedRepeatedFieldValueIterator* iter = - cel_containerof(iterator, _cel_ParsedRepeatedFieldValueIterator, base); - if (iter->remain == 0) { - return false; - } - - const bool ok = cel_Value_FromRepeatedFieldElement( - value, context, upb_Array_Get(iter->field_val, iter->index), - iter->field_def, status); - if (ok) { - cel_Value_SetInt(key, (int64_t)iter->index); - ++iter->index; - --iter->remain; - } - return ok; -} - -static bool _cel_ParsedRepeatedFieldValueIterator_Remaining( - const cel_ValueIterator* cel_nonnull iterator, - size_t* cel_nonnull remaining) { - CEL_ASSERT_NOT_NULL(iterator); - CEL_ASSERT_EQ( - iterator->vtable, - (const cel_ValueIteratorVTable*)&_cel_ParsedRepeatedFieldValueIteratorVTable); - CEL_ASSERT_NOT_NULL(remaining); - - _cel_ParsedRepeatedFieldValueIterator* iter = - cel_containerof(iterator, _cel_ParsedRepeatedFieldValueIterator, base); - *remaining = iter->remain; - return true; -} - -static bool _cel_ParsedRepeatedFieldValueIterator_Next( - cel_ListValueIterator* cel_nonnull iterator, - const cel_ValueContext* cel_nonnull context, size_t* cel_nullable index, - cel_Value* cel_nonnull value, cel_Status* cel_nonnull status) { - CEL_ASSERT_NOT_NULL(iterator); - CEL_ASSERT_EQ(iterator->vtable, &_cel_ParsedRepeatedFieldValueIteratorVTable); - CEL_ASSERT_NOT_NULL(context); - CEL_ASSERT_NOT_NULL(value); - CEL_ASSERT_NOT_NULL(status); - - if (CEL_UNLIKELY(!cel_Status_Ok(status))) { - return false; - } - - _cel_ParsedRepeatedFieldValueIterator* iter = - cel_containerof(iterator, _cel_ParsedRepeatedFieldValueIterator, base); - if (iter->remain == 0) { - return false; - } - - const bool ok = cel_Value_FromRepeatedFieldElement( - value, context, upb_Array_Get(iter->field_val, iter->index), - iter->field_def, status); - if (ok) { - if (index != cel_nullptr) { - *index = iter->index; - } - ++iter->index; - --iter->remain; - } - return ok; -} - -static const cel_ListValueIteratorVTable - _cel_ParsedRepeatedFieldValueIteratorVTable = { - .super = - { - .Delete = &_cel_ParsedRepeatedFieldValueIterator_Delete, - .Next1 = &_cel_ParsedRepeatedFieldValueIterator_Next1, - .Next2 = &_cel_ParsedRepeatedFieldValueIterator_Next2, - .Remaining = &_cel_ParsedRepeatedFieldValueIterator_Remaining, - }, - .Next = &_cel_ParsedRepeatedFieldValueIterator_Next, -}; diff --git a/cel-c/src/runtime/activation.c b/cel-c/src/runtime/activation.c deleted file mode 100644 index 0557467..0000000 --- a/cel-c/src/runtime/activation.c +++ /dev/null @@ -1,104 +0,0 @@ -// Copyright 2025 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "cel-c/src/runtime/activation.h" - -#include -#include -#include - -#include "cel-c/alloc.h" -#include "cel-c/arena.h" -#include "cel-c/assert.h" -#include "cel-c/config.h" -#include "cel-c/status.h" -#include "cel-c/string_view.h" -#include "cel-c/trilean.h" -#include "cel-c/value.h" -#include "cel-c/src/runtime/instr.h" -#include "cel-c/src/runtime/interpretable.h" -#include "cel-c/src/runtime/program.h" -#include "cel-c/src/runtime/runtime.h" - -cel_ActivationOptions* cel_nonnull -cel_ActivationOptions_Default(cel_ActivationOptions* cel_nonnull opts) { - CEL_ASSERT_NOT_NULL(opts); - - memset(opts, 0, sizeof(*opts)); - return opts; -} - -void cel_Activation_Delete(cel_Activation* cel_nullable activation) { - if (activation == cel_nullptr) { - return; - } - const cel_Program* prog = activation->prog; - cel_Allocator_FreeSized(prog->rt->alloc, activation, activation->size); - _cel_Program_Unref(prog); -} - -cel_Activation* cel_nullable -_cel_Activation_New(const cel_Program* cel_nonnull prog, - const cel_VariableResolver* cel_nonnull var_resolver) { - CEL_ASSERT_NOT_NULL(prog); - CEL_ASSERT_NOT_NULL(var_resolver); - - // Allocate the activation, value stack, slots, and call stack in a single - // allocation. - size_t size = sizeof(cel_Activation) + - (sizeof(cel_Value) * prog->max_stack_size) + - (sizeof(_cel_InterpretableSlot) * prog->max_slot_size) + - (sizeof(_cel_Instr*) * prog->max_slot_size); - char* addr = (char*)cel_Allocator_Malloc(prog->rt->alloc, size, cel_nullptr); - if (addr == cel_nullptr) { - return cel_nullptr; - } - memset(addr, 0, sizeof(cel_Activation)); - cel_Activation* act = (cel_Activation*)addr; - act->size = size; - act->prog = _cel_Program_ConstRef(prog); - act->var_resolver = var_resolver; - act->value_stack_base = (cel_Value*)(addr + sizeof(cel_Activation)); - act->value_stack_end = act->value_stack_base + prog->max_stack_size; - act->slots = (_cel_InterpretableSlot*)act->value_stack_end; - act->lazy_stack_base = (const _cel_Instr**)(act->slots + prog->max_slot_size); - act->lazy_stack_end = act->lazy_stack_base + prog->max_slot_size; - memset(act->slots, 0, sizeof(_cel_InterpretableSlot) * prog->max_slot_size); - _cel_Interpretable_Initialize(&act->interp, prog, act->value_stack_base, - act->value_stack_end - act->value_stack_base, - act->slots, act->prog->max_slot_size, - act->lazy_stack_base, - act->lazy_stack_end - act->lazy_stack_base); - return act; -} - -cel_Trilean cel_Activation_FindVariable( - const cel_Activation* cel_nonnull activation, cel_StringView name, - cel_Value* cel_nonnull result, cel_Arena* cel_nonnull arena, - cel_Status* cel_nonnull status) { - return _cel_Activation_FindVariable(activation, name, result, arena, status); -} - -bool cel_Activation_Execute(cel_Activation* cel_nonnull activation, - cel_Value* cel_nonnull result, - cel_Arena* cel_nonnull arena, - cel_Status* cel_nonnull status) { - CEL_ASSERT_NOT_NULL(activation); - CEL_ASSERT_NOT_NULL(result); - CEL_ASSERT_NOT_NULL(arena); - CEL_ASSERT(cel_Status_Ok(status)); - - return _cel_Interpretable_Interpret(&activation->interp, result, arena, - status); -} diff --git a/cel-c/src/runtime/interpretable.c b/cel-c/src/runtime/interpretable.c deleted file mode 100644 index 19a6730..0000000 --- a/cel-c/src/runtime/interpretable.c +++ /dev/null @@ -1,3615 +0,0 @@ -// Copyright 2025 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "cel-c/src/runtime/interpretable.h" - -#include -#include -#include -#include -#include -#include -#include - -#include "cel-c/activation.h" -#include "cel-c/arena.h" -#include "cel-c/assert.h" -#include "cel-c/config.h" -#include "cel-c/duration.h" -#include "cel-c/error.h" -#include "cel-c/error_code.h" -#include "cel-c/src/array.h" -#include "cel-c/src/charconv.h" -#include "cel-c/src/ckdint.h" -#include "cel-c/src/compare.h" -#include "cel-c/src/config.h" -#include "cel-c/src/durationconv.h" -#include "cel-c/src/empty_list_value.h" -#include "cel-c/src/empty_map_value.h" -#include "cel-c/src/mutable_list_value.h" -#include "cel-c/src/mutable_map_value.h" -#include "cel-c/src/number.h" -#include "cel-c/src/regexp.h" -#include "cel-c/src/runtime/activation.h" -#include "cel-c/src/runtime/instr.h" -#include "cel-c/src/runtime/program.h" -#include "cel-c/src/runtime/runtime.h" -#include "cel-c/src/setjmp.h" -#include "cel-c/src/string.h" -#include "cel-c/src/timestampconv.h" -#include "cel-c/src/utf8.h" -#include "cel-c/status.h" -#include "cel-c/string_view.h" -#include "cel-c/timestamp.h" -#include "cel-c/trilean.h" -#include "cel-c/value.h" -#include "cel-c/value_kind.h" -#include "upb/reflection/def.h" - -CEL_ATTRIBUTE_NODISCARD -static CEL_INLINE cel_Activation* _cel_Interpretable_ToActivation( - _cel_Interpretable* cel_nonnull interp) { - CEL_ASSERT_NOT_NULL(interp); - - return cel_containerof(interp, cel_Activation, interp); -} - -CEL_ATTRIBUTE_NORETURN -static CEL_INLINE void _cel_Interpretable_Throw( - _cel_Interpretable* cel_nonnull interp) { - CEL_ASSERT_NOT_NULL(interp); - CEL_ASSERT_NOT(cel_Status_Ok(interp->status)); - - _cel_longjmp(interp->jmp); -} - -CEL_ATTRIBUTE_NORETURN -static CEL_INLINE void _cel_Interpretable_ThrowOutOfMemory( - _cel_Interpretable* cel_nonnull interp) { - CEL_ASSERT_NOT_NULL(interp); - - cel_OutOfMemoryStatus(interp->status); - _cel_Interpretable_Throw(interp); -} - -CEL_ATTRIBUTE_NORETURN -static CEL_INLINE void _cel_Interpretable_ThrowStackOverflow( - _cel_Interpretable* cel_nonnull interp, const _cel_InstrData* instr) { - CEL_ASSERT_NOT_NULL(interp); - CEL_ASSERT_NOT_NULL(instr); - - cel_InternalStatusF( - interp->status, "cel: stack overflow: pc=%" PRIuPTR, - cel_containerof(instr, _cel_Instr, data) - interp->instr_ptr); - _cel_Interpretable_Throw(interp); -} - -CEL_ATTRIBUTE_NORETURN -static CEL_INLINE void _cel_Interpretable_ThrowStackUnderflow( - _cel_Interpretable* cel_nonnull interp, const _cel_InstrData* instr) { - CEL_ASSERT_NOT_NULL(interp); - CEL_ASSERT_NOT_NULL(instr); - - cel_InternalStatusF( - interp->status, "cel: stack underflow: pc=%" PRIuPTR, - cel_containerof(instr, _cel_Instr, data) - interp->instr_ptr); - _cel_Interpretable_Throw(interp); -} - -static CEL_INLINE void _cel_Interpretable_ThrowIfError( - _cel_Interpretable* cel_nonnull interp) { - if (CEL_UNLIKELY(!cel_Status_Ok(interp->status))) { - _cel_Interpretable_Throw(interp); - } -} - -CEL_ATTRIBUTE_NORETURN -static void _cel_Interpretable_Unreachable( - _cel_Interpretable* cel_nonnull interp, const _cel_InstrData* instr) { - CEL_ASSERT_NOT_NULL(interp); - CEL_ASSERT_NOT_NULL(instr); - - cel_InternalStatusF( - interp->status, "cel: unreachable code reached: pc=%" PRIuPTR, - cel_containerof(instr, _cel_Instr, data) - interp->instr_ptr); - _cel_Interpretable_Throw(interp); -} - -CEL_ATTRIBUTE_NODISCARD -static CEL_INLINE cel_StringView _cel_Interpretable_InternedString( - const _cel_Interpretable* cel_nonnull interp, uint32_t index) { - CEL_ASSERT_NOT_NULL(interp); - CEL_ASSERT_LT(index, interp->strings_table_len); - - return _cel_String_ToStringView(&interp->strings_table_ptr[index]); -} - -CEL_ATTRIBUTE_NODISCARD -static CEL_INLINE const _cel_CandidateNames* cel_nonnull -_cel_Interpretable_InternedCandidateNames( - const _cel_Interpretable* cel_nonnull interp, uint32_t index) { - CEL_ASSERT_NOT_NULL(interp); - CEL_ASSERT_LT(index, interp->candidate_names_len); - - return &interp->candidate_names_ptr[index]; -} - -CEL_ATTRIBUTE_NODISCARD -static CEL_INLINE cel_Value* cel_nonnull _cel_Interpretable_PushN( - _cel_Interpretable* cel_nonnull interp, - const _cel_InstrData* cel_nonnull instr, uint32_t count) { - CEL_ASSERT_NOT_NULL(interp); - CEL_ASSERT_NOT_NULL(instr); - CEL_ASSERT_GT(count, 0); - - cel_Value* top = interp->value_stack_top; - if (CEL_UNLIKELY(interp->value_stack_end - top < count)) { - _cel_Interpretable_ThrowStackOverflow(interp, instr); - } - interp->value_stack_top += count; - return top; -} - -CEL_ATTRIBUTE_NODISCARD -static CEL_INLINE cel_Value* cel_nonnull -_cel_Interpretable_Push(_cel_Interpretable* cel_nonnull interp, - const _cel_InstrData* cel_nonnull instr) { - return _cel_Interpretable_PushN(interp, instr, 1); -} - -static CEL_INLINE void _cel_Interpretable_PopN( - _cel_Interpretable* cel_nonnull interp, - const _cel_InstrData* cel_nonnull instr, uint32_t count) { - CEL_ASSERT_NOT_NULL(interp); - CEL_ASSERT_NOT_NULL(instr); - CEL_ASSERT_GT(count, 0); - - cel_Value* top = interp->value_stack_top; - if (CEL_UNLIKELY(top - interp->value_stack_base < count)) { - _cel_Interpretable_ThrowStackUnderflow(interp, instr); - } - interp->value_stack_top -= count; -} - -static CEL_INLINE void _cel_Interpretable_Pop( - _cel_Interpretable* cel_nonnull interp, - const _cel_InstrData* cel_nonnull instr) { - _cel_Interpretable_PopN(interp, instr, 1); -} - -CEL_ATTRIBUTE_NODISCARD -static CEL_INLINE cel_Value* cel_nonnull _cel_Interpretable_TopN( - _cel_Interpretable* cel_nonnull interp, - const _cel_InstrData* cel_nonnull instr, uint32_t count) { - CEL_ASSERT_NOT_NULL(interp); - CEL_ASSERT_NOT_NULL(instr); - CEL_ASSERT_GT(count, 0); - CEL_ASSERT(interp->value_stack_top >= interp->value_stack_base); - CEL_ASSERT(interp->value_stack_top <= interp->value_stack_end); - - cel_Value* top = interp->value_stack_top; - if (CEL_UNLIKELY(top - interp->value_stack_base < count)) { - _cel_Interpretable_ThrowStackUnderflow(interp, instr); - } - return top - count; -} - -CEL_ATTRIBUTE_NODISCARD -static CEL_INLINE cel_Value* cel_nonnull -_cel_Interpretable_Top(_cel_Interpretable* cel_nonnull interp, - const _cel_InstrData* cel_nonnull instr) { - return _cel_Interpretable_TopN(interp, instr, 1); -} - -CEL_ATTRIBUTE_NODISCARD -static CEL_INLINE cel_Value* _cel_Interpretable_PushAndPopN( - _cel_Interpretable* cel_nonnull interp, - const _cel_InstrData* cel_nonnull instr, uint32_t count) { - CEL_ASSERT_NOT_NULL(interp); - CEL_ASSERT_NOT_NULL(instr); - - if (count == 0) { - return _cel_Interpretable_Push(interp, instr); - } - if (count > 1) { - _cel_Interpretable_PopN(interp, instr, count - 1); - } - return _cel_Interpretable_Top(interp, instr); -} - -CEL_ATTRIBUTE_NODISCARD -static CEL_INLINE const _cel_Instr* cel_nonnull _cel_Interpretable_ShortJump( - const _cel_InstrData* cel_nonnull instr, int32_t offset) { - CEL_ASSERT_NOT_NULL(instr); - CEL_ASSERT_NE(offset, 0); - - return cel_containerof(instr, _cel_Instr, data) + offset; -} - -CEL_ATTRIBUTE_NODISCARD -static CEL_INLINE cel_Error* cel_nonnull -_cel_Interpretable_NewNoSuchOverloadError( - _cel_Interpretable* cel_nonnull interp) { - cel_Error* error = cel_Error_New(interp->arena); - if (CEL_UNLIKELY(error == cel_nullptr)) { - _cel_Interpretable_ThrowOutOfMemory(interp); - } - cel_Error_SetMessage(error, cel_StringView_From("cel: no such overload")); - cel_Error_SetCanonicalCode(error, cel_ErrorCode_kInvalidArgument); - return error; -} - -CEL_ATTRIBUTE_NODISCARD -static CEL_INLINE cel_Error* cel_nonnull -_cel_Interpretable_NewModuloByZeroError( - _cel_Interpretable* cel_nonnull interp) { - cel_Error* error = cel_Error_New(interp->arena); - if (CEL_UNLIKELY(error == cel_nullptr)) { - _cel_Interpretable_ThrowOutOfMemory(interp); - } - cel_Error_SetMessage(error, cel_StringView_From("cel: modulo by zero")); - cel_Error_SetCanonicalCode(error, cel_ErrorCode_kInvalidArgument); - return error; -} - -CEL_ATTRIBUTE_NODISCARD -static CEL_INLINE cel_Error* cel_nonnull -_cel_Interpretable_NewDivideByZeroError( - _cel_Interpretable* cel_nonnull interp) { - cel_Error* error = cel_Error_New(interp->arena); - if (CEL_UNLIKELY(error == cel_nullptr)) { - _cel_Interpretable_ThrowOutOfMemory(interp); - } - cel_Error_SetMessage(error, cel_StringView_From("cel: divide by zero")); - cel_Error_SetCanonicalCode(error, cel_ErrorCode_kInvalidArgument); - return error; -} - -CEL_ATTRIBUTE_NODISCARD -static CEL_INLINE cel_Error* cel_nonnull -_cel_Interpretable_NewIntOverflowError(_cel_Interpretable* cel_nonnull interp) { - cel_Error* error = cel_Error_New(interp->arena); - if (CEL_UNLIKELY(error == cel_nullptr)) { - _cel_Interpretable_ThrowOutOfMemory(interp); - } - cel_Error_SetMessage(error, cel_StringView_From("cel: int overflow")); - cel_Error_SetCanonicalCode(error, cel_ErrorCode_kInvalidArgument); - return error; -} - -CEL_ATTRIBUTE_NODISCARD -static CEL_INLINE cel_Error* cel_nonnull -_cel_Interpretable_NewUintOverflowError( - _cel_Interpretable* cel_nonnull interp) { - cel_Error* error = cel_Error_New(interp->arena); - if (CEL_UNLIKELY(error == cel_nullptr)) { - _cel_Interpretable_ThrowOutOfMemory(interp); - } - cel_Error_SetMessage(error, cel_StringView_From("cel: uint overflow")); - cel_Error_SetCanonicalCode(error, cel_ErrorCode_kInvalidArgument); - return error; -} - -CEL_ATTRIBUTE_NODISCARD -static CEL_INLINE cel_Error* cel_nonnull -_cel_Interpretable_NewDurationOverflowError( - _cel_Interpretable* cel_nonnull interp) { - cel_Error* error = cel_Error_New(interp->arena); - if (CEL_UNLIKELY(error == cel_nullptr)) { - _cel_Interpretable_ThrowOutOfMemory(interp); - } - cel_Error_SetMessage(error, cel_StringView_From("cel: duration overflow")); - cel_Error_SetCanonicalCode(error, cel_ErrorCode_kInvalidArgument); - return error; -} - -CEL_ATTRIBUTE_NODISCARD -static CEL_INLINE cel_Error* cel_nonnull -_cel_Interpretable_NewTimestampOverflowError( - _cel_Interpretable* cel_nonnull interp) { - cel_Error* error = cel_Error_New(interp->arena); - if (CEL_UNLIKELY(error == cel_nullptr)) { - _cel_Interpretable_ThrowOutOfMemory(interp); - } - cel_Error_SetMessage(error, cel_StringView_From("cel: int overflow")); - cel_Error_SetCanonicalCode(error, cel_ErrorCode_kInvalidArgument); - return error; -} - -CEL_ATTRIBUTE_NODISCARD -static CEL_INLINE cel_Error* cel_nonnull -_cel_Interpretable_NewDuplicateKeyError( - _cel_Interpretable* cel_nonnull interp) { - cel_Error* error = cel_Error_New(interp->arena); - if (CEL_UNLIKELY(error == cel_nullptr)) { - _cel_Interpretable_ThrowOutOfMemory(interp); - } - cel_Error_SetMessage(error, cel_StringView_From("cel: duplicate key in map")); - cel_Error_SetCanonicalCode(error, cel_ErrorCode_kAlreadyExists); - return error; -} - -CEL_ATTRIBUTE_NODISCARD -static CEL_INLINE cel_Error* cel_nonnull -_cel_Interpretable_NewBadKeyError(_cel_Interpretable* cel_nonnull interp) { - cel_Error* error = cel_Error_New(interp->arena); - if (CEL_UNLIKELY(error == cel_nullptr)) { - _cel_Interpretable_ThrowOutOfMemory(interp); - } - cel_Error_SetMessage(error, cel_StringView_From("cel: bad map key")); - cel_Error_SetCanonicalCode(error, cel_ErrorCode_kInvalidArgument); - return error; -} - -CEL_ATTRIBUTE_NODISCARD -static CEL_INLINE cel_Error* cel_nonnull -_cel_Interpretable_NewIndexOutOfRangeError( - _cel_Interpretable* cel_nonnull interp) { - cel_Error* error = cel_Error_New(interp->arena); - if (CEL_UNLIKELY(error == cel_nullptr)) { - _cel_Interpretable_ThrowOutOfMemory(interp); - } - cel_Error_SetMessage(error, cel_StringView_From("cel: index out of range")); - cel_Error_SetCanonicalCode(error, cel_ErrorCode_kInvalidArgument); - return error; -} - -CEL_ATTRIBUTE_NODISCARD -static CEL_INLINE cel_Error* cel_nonnull -_cel_Interpretable_NewNoSuchKeyError(_cel_Interpretable* cel_nonnull interp) { - cel_Error* error = cel_Error_New(interp->arena); - if (CEL_UNLIKELY(error == cel_nullptr)) { - _cel_Interpretable_ThrowOutOfMemory(interp); - } - cel_Error_SetMessage(error, cel_StringView_From("cel: no such key in map")); - cel_Error_SetCanonicalCode(error, cel_ErrorCode_kNotFound); - return error; -} - -static inline void _cel_Interpretable_NullConst( - _cel_Interpretable* cel_nonnull interp, - const _cel_InstrData* cel_nonnull instr) { - CEL_ASSERT_NOT_NULL(interp); - CEL_ASSERT_NOT_NULL(instr); - - cel_Value_SetNull(_cel_Interpretable_Push(interp, instr)); -} - -static inline void _cel_Interpretable_FalseConst( - _cel_Interpretable* cel_nonnull interp, - const _cel_InstrData* cel_nonnull instr) { - CEL_ASSERT_NOT_NULL(interp); - CEL_ASSERT_NOT_NULL(instr); - - cel_Value_SetFalse(_cel_Interpretable_Push(interp, instr)); -} - -static inline void _cel_Interpretable_TrueConst( - _cel_Interpretable* cel_nonnull interp, - const _cel_InstrData* cel_nonnull instr) { - CEL_ASSERT_NOT_NULL(interp); - CEL_ASSERT_NOT_NULL(instr); - - cel_Value_SetTrue(_cel_Interpretable_Push(interp, instr)); -} - -static inline void _cel_Interpretable_IntConst( - _cel_Interpretable* cel_nonnull interp, - const _cel_InstrData* cel_nonnull instr) { - CEL_ASSERT_NOT_NULL(interp); - CEL_ASSERT_NOT_NULL(instr); - - cel_Value_SetInt(_cel_Interpretable_Push(interp, instr), - instr->int_const.value); -} - -static inline void _cel_Interpretable_UintConst( - _cel_Interpretable* cel_nonnull interp, - const _cel_InstrData* cel_nonnull instr) { - CEL_ASSERT_NOT_NULL(interp); - CEL_ASSERT_NOT_NULL(instr); - - cel_Value_SetUint(_cel_Interpretable_Push(interp, instr), - instr->uint_const.value); -} - -static inline void _cel_Interpretable_DoubleConst( - _cel_Interpretable* cel_nonnull interp, - const _cel_InstrData* cel_nonnull instr) { - CEL_ASSERT_NOT_NULL(interp); - CEL_ASSERT_NOT_NULL(instr); - - cel_Value_SetDouble(_cel_Interpretable_Push(interp, instr), - instr->double_const.value); -} - -static inline void _cel_Interpretable_BytesConst( - _cel_Interpretable* cel_nonnull interp, - const _cel_InstrData* cel_nonnull instr) { - CEL_ASSERT_NOT_NULL(interp); - CEL_ASSERT_NOT_NULL(instr); - - cel_Value_SetBytes( - _cel_Interpretable_Push(interp, instr), - _cel_PackedStringView_ToStringView(instr->bytes_const.value.direct)); -} - -static inline void _cel_Interpretable_StringConst( - _cel_Interpretable* cel_nonnull interp, - const _cel_InstrData* cel_nonnull instr) { - CEL_ASSERT_NOT_NULL(interp); - CEL_ASSERT_NOT_NULL(instr); - - cel_Value_SetString( - _cel_Interpretable_Push(interp, instr), - _cel_PackedStringView_ToStringView(instr->string_const.value.direct)); -} - -static inline void _cel_Interpretable_DurationConst( - _cel_Interpretable* cel_nonnull interp, - const _cel_InstrData* cel_nonnull instr) { - CEL_ASSERT_NOT_NULL(interp); - CEL_ASSERT_NOT_NULL(instr); - - cel_Value_SetDuration(_cel_Interpretable_Push(interp, instr), - instr->duration_const.value); -} - -static inline void _cel_Interpretable_TimestampConst( - _cel_Interpretable* cel_nonnull interp, - const _cel_InstrData* cel_nonnull instr) { - CEL_ASSERT_NOT_NULL(interp); - CEL_ASSERT_NOT_NULL(instr); - - cel_Value_SetTimestamp(_cel_Interpretable_Push(interp, instr), - instr->timestamp_const.value); -} - -static inline void _cel_Interpretable_Ident( - _cel_Interpretable* cel_nonnull interp, - const _cel_InstrData* cel_nonnull instr) { - CEL_ASSERT_NOT_NULL(interp); - CEL_ASSERT_NOT_NULL(instr); - - cel_StringView name = - _cel_PackedStringView_ToStringView(instr->ident.name.direct); - cel_Value* top = _cel_Interpretable_Push(interp, instr); - switch (_cel_Activation_FindVariable(_cel_Interpretable_ToActivation(interp), - name, top, interp->arena, - interp->status)) { - case cel_Trilean_kFalse: { - CEL_ASSERT(cel_Status_Ok(interp->status)); - // Did not find the variable. - cel_Error* error = cel_Error_New(interp->arena); - if (CEL_UNLIKELY(error == cel_nullptr)) { - _cel_Interpretable_ThrowOutOfMemory(interp); - } - cel_Error_SetCanonicalCode(error, cel_ErrorCode_kNotFound); - if (CEL_UNLIKELY( - !cel_Error_FormatMessage(error, interp->arena, - "cel: variable binding not found in " - "activation: " CEL_STRINGVIEW_FMT, - CEL_STRINGVIEW_ARGS(name)))) { - _cel_Interpretable_ThrowOutOfMemory(interp); - } - cel_Value_SetError(top, error); - } break; - case cel_Trilean_kTrue: - CEL_ASSERT(cel_Status_Ok(interp->status)); - break; - case cel_Trilean_kError: - _cel_Interpretable_Throw(interp); - default: - CEL_UNREACHABLE(); - } -} - -CEL_ATTRIBUTE_NODISCARD -static inline const _cel_Instr* cel_nonnull -_cel_Interpretable_IdentJump(_cel_Interpretable* cel_nonnull interp, - const _cel_InstrData* cel_nonnull instr) { - CEL_ASSERT_NOT_NULL(interp); - CEL_ASSERT_NOT_NULL(instr); - CEL_ASSERT_NE(instr->ident_jump.found_jump, 0); - CEL_ASSERT_NE(instr->ident_jump.missing_jump, 0); - - ptrdiff_t jump; - - cel_StringView name = - _cel_Interpretable_InternedString(interp, instr->ident_jump.name); - cel_Value* top = _cel_Interpretable_Push(interp, instr); - switch (_cel_Activation_FindVariable(_cel_Interpretable_ToActivation(interp), - name, top, interp->arena, - interp->status)) { - case cel_Trilean_kFalse: - CEL_ASSERT(cel_Status_Ok(interp->status)); - if (instr->ident_jump.missing_error) { - // Did not find the variable. - cel_Error* error = cel_Error_New(interp->arena); - if (CEL_UNLIKELY(error == cel_nullptr)) { - _cel_Interpretable_ThrowOutOfMemory(interp); - } - cel_Error_SetCanonicalCode(error, cel_ErrorCode_kNotFound); - if (CEL_UNLIKELY( - !cel_Error_FormatMessage(error, interp->arena, - "cel: variable binding not found in " - "activation: " CEL_STRINGVIEW_FMT, - CEL_STRINGVIEW_ARGS(name)))) { - _cel_Interpretable_ThrowOutOfMemory(interp); - } - cel_Value_SetError(top, error); - } else { - _cel_Interpretable_Pop(interp, instr); - } - jump = instr->ident_jump.missing_jump; - break; - case cel_Trilean_kTrue: - CEL_ASSERT(cel_Status_Ok(interp->status)); - jump = instr->ident_jump.found_jump; - break; - case cel_Trilean_kError: - _cel_Interpretable_Pop(interp, instr); - _cel_Interpretable_Throw(interp); - default: - CEL_UNREACHABLE(); - } - return _cel_Interpretable_ShortJump(instr, jump); -} - -static inline void _cel_Interpretable_ContIdent( - _cel_Interpretable* cel_nonnull interp, - const _cel_InstrData* cel_nonnull instr) { - CEL_ASSERT_NOT_NULL(interp); - CEL_ASSERT_NOT_NULL(instr); - - cel_Value* top = _cel_Interpretable_Push(interp, instr); - const _cel_CandidateNames* candidate_names = - _cel_Interpretable_InternedCandidateNames( - interp, instr->cont_ident.candidate_names); - for (size_t i = 0; i < candidate_names->size; ++i) { - switch (_cel_Activation_FindVariable( - _cel_Interpretable_ToActivation(interp), - _cel_Interpretable_InternedString(interp, candidate_names->data[i]), - top, interp->arena, interp->status)) { - case cel_Trilean_kFalse: - CEL_ASSERT(cel_Status_Ok(interp->status)); - break; - case cel_Trilean_kTrue: - CEL_ASSERT(cel_Status_Ok(interp->status)); - return; - case cel_Trilean_kError: - _cel_Interpretable_Throw(interp); - default: - CEL_UNREACHABLE(); - } - } - // Did not find the variable. - cel_Error* error = cel_Error_New(interp->arena); - if (CEL_UNLIKELY(error == cel_nullptr)) { - _cel_Interpretable_ThrowOutOfMemory(interp); - } - cel_Error_SetCanonicalCode(error, cel_ErrorCode_kNotFound); - if (CEL_UNLIKELY(!cel_Error_FormatMessage( - error, interp->arena, - "cel: variable binding not found in " - "activation: " CEL_STRINGVIEW_FMT, - CEL_STRINGVIEW_ARGS(_cel_Interpretable_InternedString( - interp, candidate_names->data[candidate_names->size - 1]))))) { - _cel_Interpretable_ThrowOutOfMemory(interp); - } - cel_Value_SetError(top, error); -} - -CEL_ATTRIBUTE_NODISCARD -static inline const _cel_Instr* cel_nonnull -_cel_Interpretable_ContIdentJump(_cel_Interpretable* cel_nonnull interp, - const _cel_InstrData* cel_nonnull instr) { - CEL_ASSERT_NOT_NULL(interp); - CEL_ASSERT_NOT_NULL(instr); - CEL_ASSERT_NE(instr->cont_ident_jump.found_jump, 0); - CEL_ASSERT_NE(instr->cont_ident_jump.missing_jump, 0); - - cel_Value* top = _cel_Interpretable_Push(interp, instr); - const _cel_CandidateNames* candidate_names = - _cel_Interpretable_InternedCandidateNames( - interp, instr->cont_ident_jump.candidate_names); - for (size_t i = 0; i < candidate_names->size; ++i) { - switch (_cel_Activation_FindVariable( - _cel_Interpretable_ToActivation(interp), - _cel_Interpretable_InternedString(interp, candidate_names->data[i]), - top, interp->arena, interp->status)) { - case cel_Trilean_kFalse: - CEL_ASSERT(cel_Status_Ok(interp->status)); - break; - case cel_Trilean_kTrue: - CEL_ASSERT(cel_Status_Ok(interp->status)); - return _cel_Interpretable_ShortJump(instr, - instr->cont_ident_jump.found_jump); - case cel_Trilean_kError: - _cel_Interpretable_Pop(interp, instr); - _cel_Interpretable_Throw(interp); - default: - CEL_UNREACHABLE(); - } - } - if (instr->cont_ident_jump.missing_error) { - // Did not find the variable. - cel_Error* error = cel_Error_New(interp->arena); - if (CEL_UNLIKELY(error == cel_nullptr)) { - _cel_Interpretable_ThrowOutOfMemory(interp); - } - cel_Error_SetCanonicalCode(error, cel_ErrorCode_kNotFound); - if (CEL_UNLIKELY(!cel_Error_FormatMessage( - error, interp->arena, - "cel: variable binding not found in " - "activation: " CEL_STRINGVIEW_FMT, - CEL_STRINGVIEW_ARGS(_cel_Interpretable_InternedString( - interp, candidate_names->data[candidate_names->size - 1]))))) { - _cel_Interpretable_ThrowOutOfMemory(interp); - } - cel_Value_SetError(top, error); - } else { - _cel_Interpretable_Pop(interp, instr); - } - return _cel_Interpretable_ShortJump(instr, - instr->cont_ident_jump.missing_jump); -} - -CEL_ATTRIBUTE_NODISCARD -static inline const _cel_Instr* cel_nonnull -_cel_Interpretable_Jump(_cel_Interpretable* cel_nonnull interp, - const _cel_InstrData* cel_nonnull instr) { - CEL_ASSERT_NOT_NULL(interp); - CEL_ASSERT_NOT_NULL(instr); - CEL_ASSERT_NE(instr->jump.jump, 0); - - return _cel_Interpretable_ShortJump(instr, instr->jump.jump); -} - -static inline void _cel_Interpretable_Has( - _cel_Interpretable* cel_nonnull interp, - const _cel_InstrData* cel_nonnull instr) { - cel_Value* top = _cel_Interpretable_Top(interp, instr); - switch (cel_Value_Kind(top)) { - case cel_ValueKind_kError: - break; - case cel_ValueKind_kMap: { - cel_MapValue map_value = *cel_Value_GetMap(top); - cel_MapValueKey map_value_key; - cel_MapValueKey_SetString( - &map_value_key, - _cel_PackedStringView_ToStringView(instr->has.field.direct)); - if (CEL_UNLIKELY(!cel_MapValue_Has(&map_value, &interp->context, - &map_value_key, top, - interp->status))) { - _cel_Interpretable_Throw(interp); - } - } break; - case cel_ValueKind_kStruct: { - cel_StructValue struct_value = *cel_Value_GetStruct(top); - cel_StructValueKey struct_value_key; - cel_StructValueKey_SetName( - &struct_value_key, - _cel_PackedStringView_ToStringView(instr->has.field.direct)); - if (CEL_UNLIKELY(!cel_StructValue_Has(&struct_value, &interp->context, - &struct_value_key, top, - interp->status))) { - _cel_Interpretable_Throw(interp); - } - } break; - default: { - cel_Error* error = cel_Error_New(interp->arena); - if (CEL_UNLIKELY(error == cel_nullptr)) { - _cel_Interpretable_ThrowOutOfMemory(interp); - } - cel_Error_SetCanonicalCode(error, cel_ErrorCode_kInvalidArgument); - cel_Value_SetError(top, error); - } break; - } -} - -// Similar to _cel_Interpretable_Has, except this is used when we know the -// underlying field is in a message. This is an optimization and allows us to -// avoid looking up the field by reflection everytime. -static inline void _cel_Interpretable_MessageHas( - _cel_Interpretable* cel_nonnull interp, - const _cel_InstrData* cel_nonnull instr) { - CEL_ASSERT_NOT_NULL(interp); - CEL_ASSERT_NOT_NULL(instr); - - cel_Value* top = _cel_Interpretable_Top(interp, instr); - switch (cel_Value_Kind(top)) { - case cel_ValueKind_kError: - break; - case cel_ValueKind_kMap: { - cel_MapValue map_value = *cel_Value_GetMap(top); - cel_MapValueKey map_value_key; - cel_MapValueKey_SetString( - &map_value_key, cel_StringView_FromString( - upb_FieldDef_Name(instr->message_has.field))); - if (CEL_UNLIKELY(!cel_MapValue_Has(&map_value, &interp->context, - &map_value_key, top, - interp->status))) { - _cel_Interpretable_Throw(interp); - } - } break; - case cel_ValueKind_kStruct: { - cel_StructValue struct_value = *cel_Value_GetStruct(top); - cel_StructValueKey struct_value_key; - cel_StructValueKey_SetDef(&struct_value_key, instr->message_has.field); - if (CEL_UNLIKELY(!cel_StructValue_Has(&struct_value, &interp->context, - &struct_value_key, top, - interp->status))) { - _cel_Interpretable_Throw(interp); - } - } break; - default: { - cel_Error* error = cel_Error_New(interp->arena); - if (CEL_UNLIKELY(error == cel_nullptr)) { - _cel_Interpretable_ThrowOutOfMemory(interp); - } - cel_Error_SetCanonicalCode(error, cel_ErrorCode_kInvalidArgument); - cel_Value_SetError(top, error); - } break; - } -} - -static inline void _cel_Interpretable_Select( - _cel_Interpretable* cel_nonnull interp, - const _cel_InstrData* cel_nonnull instr) { - CEL_ASSERT_NOT_NULL(interp); - CEL_ASSERT_NOT_NULL(instr); - - cel_Value* top = _cel_Interpretable_Top(interp, instr); - switch (cel_Value_Kind(top)) { - case cel_ValueKind_kError: - break; - case cel_ValueKind_kMap: { - cel_MapValue map_value = *cel_Value_GetMap(top); - cel_MapValueKey map_value_key; - cel_MapValueKey_SetString( - &map_value_key, - _cel_PackedStringView_ToStringView(instr->select.field.direct)); - if (CEL_UNLIKELY(!cel_MapValue_Get(&map_value, &interp->context, - &map_value_key, top, - interp->status))) { - _cel_Interpretable_Throw(interp); - } - } break; - case cel_ValueKind_kStruct: { - cel_StructValue struct_value = *cel_Value_GetStruct(top); - cel_StructValueKey struct_value_key; - cel_StructValueKey_SetName( - &struct_value_key, - _cel_PackedStringView_ToStringView(instr->select.field.direct)); - if (CEL_UNLIKELY(!cel_StructValue_Get(&struct_value, &interp->context, - &struct_value_key, top, - interp->status))) { - _cel_Interpretable_Throw(interp); - } - } break; - default: { - cel_Error* error = cel_Error_New(interp->arena); - if (CEL_UNLIKELY(error == cel_nullptr)) { - _cel_Interpretable_ThrowOutOfMemory(interp); - } - cel_Error_SetCanonicalCode(error, cel_ErrorCode_kInvalidArgument); - cel_Value_SetError(top, error); - } break; - } -} - -// Similar to _cel_Interpretable_Select, except this is used when we know the -// underlying field is in a message. This is an optimization and allows us to -// avoid looking up the field by reflection everytime. -static inline void _cel_Interpretable_MessageSelect( - _cel_Interpretable* cel_nonnull interp, - const _cel_InstrData* cel_nonnull instr) { - CEL_ASSERT_NOT_NULL(interp); - CEL_ASSERT_NOT_NULL(instr); - - cel_Value* top = _cel_Interpretable_Top(interp, instr); - switch (cel_Value_Kind(top)) { - case cel_ValueKind_kError: - break; - case cel_ValueKind_kMap: { - cel_MapValue map_value = *cel_Value_GetMap(top); - cel_MapValueKey map_value_key; - cel_MapValueKey_SetString( - &map_value_key, cel_StringView_FromString( - upb_FieldDef_Name(instr->message_has.field))); - if (CEL_UNLIKELY(!cel_MapValue_Get(&map_value, &interp->context, - &map_value_key, top, - interp->status))) { - _cel_Interpretable_Throw(interp); - } - } break; - case cel_ValueKind_kStruct: { - cel_StructValue struct_value = *cel_Value_GetStruct(top); - cel_StructValueKey struct_value_key; - cel_StructValueKey_SetDef(&struct_value_key, instr->message_has.field); - if (CEL_UNLIKELY(!cel_StructValue_Get(&struct_value, &interp->context, - &struct_value_key, top, - interp->status))) { - _cel_Interpretable_Throw(interp); - } - } break; - default: { - cel_Error* error = cel_Error_New(interp->arena); - if (CEL_UNLIKELY(error == cel_nullptr)) { - _cel_Interpretable_ThrowOutOfMemory(interp); - } - cel_Error_SetCanonicalCode(error, cel_ErrorCode_kInvalidArgument); - cel_Value_SetError(top, error); - } break; - } -} - -CEL_ATTRIBUTE_NODISCARD -static inline cel_StringView _cel_Interpretable_Concat( - _cel_Interpretable* cel_nonnull interp, cel_StringView lhs, - cel_StringView rhs) { - CEL_ASSERT_NOT_NULL(interp); - - size_t lhs_size = cel_StringView_Size(lhs); - size_t rhs_size = cel_StringView_Size(rhs); - if (lhs_size == 0) { - return rhs; - } - if (rhs_size == 0) { - return lhs; - } - size_t size; - if (_cel_ckd_add(&size, lhs_size, rhs_size) || - size > (size_t)(uint32_t)INT32_MAX) { - _cel_Interpretable_ThrowOutOfMemory(interp); - } - char* data = cel_Arena_Malloc(interp->arena, size, cel_nullptr); - if (CEL_UNLIKELY(data == cel_nullptr)) { - _cel_Interpretable_ThrowOutOfMemory(interp); - } - memcpy(data, cel_StringView_Data(lhs), lhs_size); - memcpy(data + lhs_size, cel_StringView_Data(rhs), rhs_size); - return cel_StringView_FromArray(data, size); -} - -static inline void _cel_Interpretable_Add( - _cel_Interpretable* cel_nonnull interp, - const _cel_InstrData* cel_nonnull instr) { - CEL_ASSERT_NOT_NULL(interp); - CEL_ASSERT_NOT_NULL(instr); - - cel_Value* const top = _cel_Interpretable_TopN(interp, instr, 2); - cel_Value* const lhs = top; - cel_Value* const rhs = lhs + 1; - switch (cel_Value_Kind(lhs)) { - case cel_ValueKind_kError: - break; - case cel_ValueKind_kInt: { - switch (cel_Value_Kind(rhs)) { - case cel_ValueKind_kError: - *top = *rhs; - break; - case cel_ValueKind_kInt: { - int64_t result; - if (_cel_ckd_add(&result, cel_Value_GetInt(lhs), - cel_Value_GetInt(rhs))) { - cel_Value_SetError(top, - _cel_Interpretable_NewIntOverflowError(interp)); - break; - } - cel_Value_SetInt(top, result); - } break; - default: - cel_Value_SetError(top, - _cel_Interpretable_NewNoSuchOverloadError(interp)); - break; - } - } break; - case cel_ValueKind_kUint: { - switch (cel_Value_Kind(rhs)) { - case cel_ValueKind_kError: - *top = *rhs; - break; - case cel_ValueKind_kUint: { - uint64_t result; - if (_cel_ckd_add(&result, cel_Value_GetUint(lhs), - cel_Value_GetUint(rhs))) { - cel_Value_SetError(top, - _cel_Interpretable_NewUintOverflowError(interp)); - break; - } - cel_Value_SetUint(top, result); - } break; - default: - cel_Value_SetError(top, - _cel_Interpretable_NewNoSuchOverloadError(interp)); - break; - } - } break; - case cel_ValueKind_kDouble: { - switch (cel_Value_Kind(rhs)) { - case cel_ValueKind_kError: - *top = *rhs; - break; - case cel_ValueKind_kDouble: - cel_Value_SetDouble( - top, cel_Value_GetDouble(lhs) + cel_Value_GetDouble(rhs)); - break; - default: - cel_Value_SetError(top, - _cel_Interpretable_NewNoSuchOverloadError(interp)); - break; - } - } break; - case cel_ValueKind_kBytes: { - switch (cel_Value_Kind(rhs)) { - case cel_ValueKind_kError: - *top = *rhs; - break; - case cel_ValueKind_kBytes: - cel_Value_SetBytes( - top, _cel_Interpretable_Concat(interp, cel_Value_GetBytes(lhs), - cel_Value_GetBytes(rhs))); - break; - default: - cel_Value_SetError(top, - _cel_Interpretable_NewNoSuchOverloadError(interp)); - break; - } - } break; - case cel_ValueKind_kString: { - switch (cel_Value_Kind(rhs)) { - case cel_ValueKind_kError: - *top = *rhs; - break; - case cel_ValueKind_kString: - cel_Value_SetString( - top, _cel_Interpretable_Concat(interp, cel_Value_GetString(lhs), - cel_Value_GetString(rhs))); - break; - default: - cel_Value_SetError(top, - _cel_Interpretable_NewNoSuchOverloadError(interp)); - break; - } - } break; - case cel_ValueKind_kDuration: { - switch (cel_Value_Kind(rhs)) { - case cel_ValueKind_kError: - *top = *rhs; - break; - case cel_ValueKind_kDuration: { - cel_Duration result; - if (!cel_Duration_Add(&result, cel_Value_GetDuration(lhs), - cel_Value_GetDuration(rhs))) { - cel_Value_SetError( - top, _cel_Interpretable_NewDurationOverflowError(interp)); - break; - } - cel_Value_SetDuration(top, result); - } break; - case cel_ValueKind_kTimestamp: { - cel_Timestamp result; - if (!cel_Timestamp_Add(&result, cel_Value_GetTimestamp(rhs), - cel_Value_GetDuration(lhs))) { - cel_Value_SetError( - top, _cel_Interpretable_NewTimestampOverflowError(interp)); - break; - } - cel_Value_SetTimestamp(top, result); - } break; - default: - cel_Value_SetError(top, - _cel_Interpretable_NewNoSuchOverloadError(interp)); - break; - } - } break; - case cel_ValueKind_kTimestamp: { - switch (cel_Value_Kind(rhs)) { - case cel_ValueKind_kError: - *top = *rhs; - break; - case cel_ValueKind_kDuration: { - cel_Timestamp result; - if (!cel_Timestamp_Add(&result, cel_Value_GetTimestamp(lhs), - cel_Value_GetDuration(rhs))) { - cel_Value_SetError( - top, _cel_Interpretable_NewTimestampOverflowError(interp)); - break; - } - cel_Value_SetTimestamp(top, result); - } break; - default: - cel_Value_SetError(top, - _cel_Interpretable_NewNoSuchOverloadError(interp)); - break; - } - } break; - default: - if (cel_Value_IsError(rhs)) { - *top = *rhs; - break; - } - cel_Value_SetError(top, - _cel_Interpretable_NewNoSuchOverloadError(interp)); - break; - } - _cel_Interpretable_Pop(interp, instr); -} - -static inline void _cel_Interpretable_Subtract( - _cel_Interpretable* cel_nonnull interp, - const _cel_InstrData* cel_nonnull instr) { - CEL_ASSERT_NOT_NULL(interp); - CEL_ASSERT_NOT_NULL(instr); - - cel_Value* const top = _cel_Interpretable_TopN(interp, instr, 2); - cel_Value* const lhs = top; - cel_Value* const rhs = lhs + 1; - switch (cel_Value_Kind(lhs)) { - case cel_ValueKind_kError: - // error - T -> error - break; - case cel_ValueKind_kInt: { - switch (cel_Value_Kind(rhs)) { - case cel_ValueKind_kError: - // int - error -> error - *top = *rhs; - break; - case cel_ValueKind_kInt: { - // int - int -> int - int64_t result; - if (_cel_ckd_sub(&result, cel_Value_GetInt(lhs), - cel_Value_GetInt(rhs))) { - cel_Value_SetError(top, - _cel_Interpretable_NewIntOverflowError(interp)); - break; - } - cel_Value_SetInt(top, result); - } break; - default: - cel_Value_SetError(top, - _cel_Interpretable_NewNoSuchOverloadError(interp)); - break; - } - } break; - case cel_ValueKind_kUint: { - switch (cel_Value_Kind(rhs)) { - case cel_ValueKind_kError: - // uint - error -> error - *top = *rhs; - *top = *rhs; - break; - case cel_ValueKind_kUint: { - // uint - uint -> uint - uint64_t result; - if (_cel_ckd_sub(&result, cel_Value_GetUint(lhs), - cel_Value_GetUint(rhs))) { - cel_Value_SetError(top, - _cel_Interpretable_NewUintOverflowError(interp)); - break; - } - cel_Value_SetUint(top, result); - } break; - default: - cel_Value_SetError(top, - _cel_Interpretable_NewNoSuchOverloadError(interp)); - break; - } - } break; - case cel_ValueKind_kDouble: { - switch (cel_Value_Kind(rhs)) { - case cel_ValueKind_kError: - // double - error -> error - *top = *rhs; - break; - case cel_ValueKind_kDouble: - // double - double -> double - cel_Value_SetDouble( - top, cel_Value_GetDouble(lhs) - cel_Value_GetDouble(rhs)); - break; - default: - cel_Value_SetError(top, - _cel_Interpretable_NewNoSuchOverloadError(interp)); - break; - } - } break; - case cel_ValueKind_kDuration: { - switch (cel_Value_Kind(rhs)) { - case cel_ValueKind_kError: - // google.protobuf.Duration - error -> error - *top = *rhs; - break; - case cel_ValueKind_kDuration: { - // google.protobuf.Duration - google.protobuf.Duration -> - // google.protobuf.Duration - cel_Duration result; - if (!cel_Duration_Sub(&result, cel_Value_GetDuration(lhs), - cel_Value_GetDuration(rhs))) { - cel_Value_SetError( - top, _cel_Interpretable_NewDurationOverflowError(interp)); - break; - } - cel_Value_SetDuration(top, result); - } break; - default: - cel_Value_SetError(top, - _cel_Interpretable_NewNoSuchOverloadError(interp)); - break; - } - } break; - case cel_ValueKind_kTimestamp: { - switch (cel_Value_Kind(rhs)) { - case cel_ValueKind_kError: - // google.protobuf.Timestamp - error -> error - *top = *rhs; - break; - case cel_ValueKind_kDuration: { - // google.protobuf.Timestamp - google.protobuf.Duration -> - // google.protobuf.Timestamp - cel_Timestamp result; - if (!cel_Timestamp_Sub(&result, cel_Value_GetTimestamp(lhs), - cel_Value_GetDuration(rhs))) { - cel_Value_SetError( - top, _cel_Interpretable_NewTimestampOverflowError(interp)); - break; - } - cel_Value_SetTimestamp(top, result); - } break; - case cel_ValueKind_kTimestamp: { - // google.protobuf.Timestamp - google.protobuf.Timestamp -> - // google.protobuf.Duration - cel_Duration result; - if (!cel_Timestamp_Diff(&result, cel_Value_GetTimestamp(lhs), - cel_Value_GetTimestamp(rhs))) { - cel_Value_SetError( - top, _cel_Interpretable_NewDurationOverflowError(interp)); - break; - } - cel_Value_SetDuration(top, result); - } break; - default: - cel_Value_SetError(top, - _cel_Interpretable_NewNoSuchOverloadError(interp)); - break; - } - } break; - default: { - cel_Error* error = cel_Error_New(interp->arena); - if (CEL_UNLIKELY(error == cel_nullptr)) { - _cel_Interpretable_ThrowOutOfMemory(interp); - } - cel_Error_SetCanonicalCode(error, cel_ErrorCode_kInvalidArgument); - cel_Value_SetError(top, error); - } break; - } - _cel_Interpretable_Pop(interp, instr); -} - -static inline void _cel_Interpretable_Multiply( - _cel_Interpretable* cel_nonnull interp, - const _cel_InstrData* cel_nonnull instr) { - CEL_ASSERT_NOT_NULL(interp); - CEL_ASSERT_NOT_NULL(instr); - - cel_Value* const top = _cel_Interpretable_TopN(interp, instr, 2); - cel_Value* const lhs = top; - cel_Value* const rhs = lhs + 1; - - switch (cel_Value_Kind(lhs)) { - case cel_ValueKind_kError: - // error * T -> error - break; - case cel_ValueKind_kInt: { - switch (cel_Value_Kind(rhs)) { - case cel_ValueKind_kError: - // int * error -> error - *top = *rhs; - break; - case cel_ValueKind_kInt: { - // int * int -> int - int64_t result; - if (_cel_ckd_mul(&result, cel_Value_GetInt(lhs), - cel_Value_GetInt(rhs))) { - cel_Value_SetError(top, - _cel_Interpretable_NewIntOverflowError(interp)); - break; - } - cel_Value_SetInt(top, result); - } break; - default: - cel_Value_SetError(top, - _cel_Interpretable_NewNoSuchOverloadError(interp)); - break; - } - } break; - case cel_ValueKind_kUint: { - switch (cel_Value_Kind(rhs)) { - case cel_ValueKind_kError: - // uint * error -> error - *top = *rhs; - break; - case cel_ValueKind_kUint: { - // uint * uint -> uint - uint64_t result; - if (_cel_ckd_mul(&result, cel_Value_GetUint(lhs), - cel_Value_GetUint(rhs))) { - cel_Value_SetError(top, - _cel_Interpretable_NewUintOverflowError(interp)); - break; - } - cel_Value_SetUint(top, result); - } break; - default: - cel_Value_SetError(top, - _cel_Interpretable_NewNoSuchOverloadError(interp)); - break; - } - } break; - case cel_ValueKind_kDouble: { - switch (cel_Value_Kind(rhs)) { - case cel_ValueKind_kError: - // double * error -> error - *top = *rhs; - break; - case cel_ValueKind_kDouble: - // double * double -> double - cel_Value_SetDouble( - top, cel_Value_GetDouble(lhs) * cel_Value_GetDouble(rhs)); - break; - default: - cel_Value_SetError(top, - _cel_Interpretable_NewNoSuchOverloadError(interp)); - break; - } - } break; - default: { - cel_Error* error = cel_Error_New(interp->arena); - if (CEL_UNLIKELY(error == cel_nullptr)) { - _cel_Interpretable_ThrowOutOfMemory(interp); - } - cel_Error_SetCanonicalCode(error, cel_ErrorCode_kInvalidArgument); - cel_Value_SetError(top, error); - } break; - } - - _cel_Interpretable_Pop(interp, instr); -} - -static inline void _cel_Interpretable_Divide( - _cel_Interpretable* cel_nonnull interp, - const _cel_InstrData* cel_nonnull instr) { - CEL_ASSERT_NOT_NULL(interp); - CEL_ASSERT_NOT_NULL(instr); - - cel_Value* const top = _cel_Interpretable_TopN(interp, instr, 2); - cel_Value* const lhs = top; - cel_Value* const rhs = lhs + 1; - - switch (cel_Value_Kind(lhs)) { - case cel_ValueKind_kError: - // error / T -> error - break; - case cel_ValueKind_kInt: { - switch (cel_Value_Kind(rhs)) { - case cel_ValueKind_kError: - // int / error -> error - *top = *rhs; - break; - case cel_ValueKind_kInt: { - // int / 0 -> error - if (cel_Value_GetInt(rhs) == 0) { - cel_Value_SetError(top, - _cel_Interpretable_NewDivideByZeroError(interp)); - break; - } - // int / int -> int - int64_t result; - if (_cel_ckd_div(&result, cel_Value_GetInt(lhs), - cel_Value_GetInt(rhs))) { - cel_Value_SetError(top, - _cel_Interpretable_NewIntOverflowError(interp)); - break; - } - cel_Value_SetInt(top, result); - } break; - default: - cel_Value_SetError(top, - _cel_Interpretable_NewNoSuchOverloadError(interp)); - break; - } - } break; - case cel_ValueKind_kUint: { - switch (cel_Value_Kind(rhs)) { - case cel_ValueKind_kError: - // uint / error -> error - *top = *rhs; - break; - case cel_ValueKind_kUint: { - // uint / 0 -> error - if (cel_Value_GetUint(rhs) == 0) { - cel_Value_SetError(top, - _cel_Interpretable_NewDivideByZeroError(interp)); - break; - } - // uint / uint -> uint - uint64_t result; - if (_cel_ckd_div(&result, cel_Value_GetUint(lhs), - cel_Value_GetUint(rhs))) { - cel_Value_SetError(top, - _cel_Interpretable_NewUintOverflowError(interp)); - break; - } - cel_Value_SetUint(top, result); - } break; - default: - cel_Value_SetError(top, - _cel_Interpretable_NewNoSuchOverloadError(interp)); - break; - } - } break; - case cel_ValueKind_kDouble: { - switch (cel_Value_Kind(rhs)) { - case cel_ValueKind_kError: - // double / error -> error - *top = *rhs; - break; - case cel_ValueKind_kDouble: - // double / 0 -> error - if (cel_Value_GetDouble(rhs) == 0) { - cel_Value_SetError(top, - _cel_Interpretable_NewDivideByZeroError(interp)); - break; - } - // double / double -> double - cel_Value_SetDouble( - top, cel_Value_GetDouble(lhs) / cel_Value_GetDouble(rhs)); - break; - default: - cel_Value_SetError(top, - _cel_Interpretable_NewNoSuchOverloadError(interp)); - break; - } - } break; - default: { - cel_Error* error = cel_Error_New(interp->arena); - if (CEL_UNLIKELY(error == cel_nullptr)) { - _cel_Interpretable_ThrowOutOfMemory(interp); - } - cel_Error_SetCanonicalCode(error, cel_ErrorCode_kInvalidArgument); - cel_Value_SetError(top, error); - } break; - } - _cel_Interpretable_Pop(interp, instr); -} - -static inline void _cel_Interpretable_Modulo( - _cel_Interpretable* cel_nonnull interp, - const _cel_InstrData* cel_nonnull instr) { - CEL_ASSERT_NOT_NULL(interp); - CEL_ASSERT_NOT_NULL(instr); - - cel_Value* const top = _cel_Interpretable_TopN(interp, instr, 2); - cel_Value* const lhs = top; - cel_Value* const rhs = lhs + 1; - - switch (cel_Value_Kind(lhs)) { - case cel_ValueKind_kError: - // error % T -> error - break; - case cel_ValueKind_kInt: { - switch (cel_Value_Kind(rhs)) { - case cel_ValueKind_kError: - // int % error -> error - *top = *rhs; - break; - case cel_ValueKind_kInt: { - // int % 0 -> error - if (cel_Value_GetInt(rhs) == 0) { - cel_Value_SetError(top, - _cel_Interpretable_NewModuloByZeroError(interp)); - break; - } - // int % int -> int - int64_t result; - if (_cel_ckd_mod(&result, cel_Value_GetInt(lhs), - cel_Value_GetInt(rhs))) { - cel_Value_SetError(top, - _cel_Interpretable_NewIntOverflowError(interp)); - break; - } - cel_Value_SetInt(top, result); - } break; - default: - cel_Value_SetError(top, - _cel_Interpretable_NewNoSuchOverloadError(interp)); - break; - } - } break; - case cel_ValueKind_kUint: { - switch (cel_Value_Kind(rhs)) { - case cel_ValueKind_kError: - // uint % error -> error - *top = *rhs; - break; - case cel_ValueKind_kUint: { - // uint % 0 -> error - if (cel_Value_GetUint(rhs) == 0) { - cel_Value_SetError(top, - _cel_Interpretable_NewModuloByZeroError(interp)); - break; - } - // uint % uint -> uint - uint64_t result; - if (_cel_ckd_mod(&result, cel_Value_GetUint(lhs), - cel_Value_GetUint(rhs))) { - cel_Value_SetError(top, - _cel_Interpretable_NewUintOverflowError(interp)); - break; - } - cel_Value_SetUint(top, result); - } break; - default: - cel_Value_SetError(top, - _cel_Interpretable_NewNoSuchOverloadError(interp)); - break; - } - } break; - default: { - cel_Error* error = cel_Error_New(interp->arena); - if (CEL_UNLIKELY(error == cel_nullptr)) { - _cel_Interpretable_ThrowOutOfMemory(interp); - } - cel_Error_SetCanonicalCode(error, cel_ErrorCode_kInvalidArgument); - cel_Value_SetError(top, error); - } break; - } - - _cel_Interpretable_Pop(interp, instr); -} - -static inline void _cel_Interpretable_LogicalNot( - _cel_Interpretable* cel_nonnull interp, - const _cel_InstrData* cel_nonnull instr) { - CEL_ASSERT_NOT_NULL(interp); - CEL_ASSERT_NOT_NULL(instr); - - cel_Value* const top = _cel_Interpretable_TopN(interp, instr, 1); - cel_Value* const val = top; - - switch (cel_Value_Kind(val)) { - case cel_ValueKind_kError: - // !error -> error - break; - case cel_ValueKind_kBool: { - // !true -> false - cel_Value_SetBool(top, !cel_Value_GetBool(val)); - } break; - default: { - cel_Error* error = cel_Error_New(interp->arena); - if (CEL_UNLIKELY(error == cel_nullptr)) { - _cel_Interpretable_ThrowOutOfMemory(interp); - } - cel_Error_SetCanonicalCode(error, cel_ErrorCode_kInvalidArgument); - cel_Value_SetError(top, error); - } break; - } -} - -static inline void _cel_Interpretable_Negate( - _cel_Interpretable* cel_nonnull interp, - const _cel_InstrData* cel_nonnull instr) { - CEL_ASSERT_NOT_NULL(interp); - CEL_ASSERT_NOT_NULL(instr); - - cel_Value* const top = _cel_Interpretable_TopN(interp, instr, 1); - cel_Value* const val = top; - - switch (cel_Value_Kind(val)) { - case cel_ValueKind_kError: - // -error -> error - break; - case cel_ValueKind_kInt: { - // -(int) -> -int - int64_t result; - if (_cel_ckd_sub(&result, 0, cel_Value_GetInt(val))) { - cel_Value_SetError(top, _cel_Interpretable_NewIntOverflowError(interp)); - break; - } - cel_Value_SetInt(top, result); - } break; - case cel_ValueKind_kDouble: { - // -(double) -> -double - cel_Value_SetDouble(top, -cel_Value_GetDouble(val)); - } break; - default: { - cel_Error* error = cel_Error_New(interp->arena); - if (CEL_UNLIKELY(error == cel_nullptr)) { - _cel_Interpretable_ThrowOutOfMemory(interp); - } - cel_Error_SetCanonicalCode(error, cel_ErrorCode_kInvalidArgument); - cel_Value_SetError(top, error); - } break; - } -} - -static inline void _cel_Interpretable_LogicalAnd( - _cel_Interpretable* cel_nonnull interp, - const _cel_InstrData* cel_nonnull instr) { - CEL_ASSERT_NOT_NULL(interp); - CEL_ASSERT_NOT_NULL(instr); - - cel_Value* const top = _cel_Interpretable_TopN(interp, instr, 2); - cel_Value* const lhs = top; - cel_Value* const rhs = lhs + 1; - - switch (cel_Value_Kind(lhs)) { - case cel_ValueKind_kError: { - // error && T - if (cel_Value_Kind(rhs) == cel_ValueKind_kBool && - cel_Value_GetBool(rhs) == false) { - // error && False -> False - cel_Value_SetFalse(top); - } - // Otherwise, error && T -> error, which is already the value of *top. - } break; - case cel_ValueKind_kBool: { - switch (cel_Value_Kind(rhs)) { - case cel_ValueKind_kError: - // bool && error - if (cel_Value_GetBool(lhs) == false) { - // False && error -> False - cel_Value_SetFalse(top); - } else { - // True && error -> error - *top = *rhs; - } - break; - case cel_ValueKind_kBool: - // bool && bool -> bool - cel_Value_SetBool(top, - cel_Value_GetBool(lhs) && cel_Value_GetBool(rhs)); - break; - default: - cel_Value_SetError(top, - _cel_Interpretable_NewNoSuchOverloadError(interp)); - break; - } - } break; - default: { - cel_Error* error = cel_Error_New(interp->arena); - if (CEL_UNLIKELY(error == cel_nullptr)) { - _cel_Interpretable_ThrowOutOfMemory(interp); - } - cel_Error_SetCanonicalCode(error, cel_ErrorCode_kInvalidArgument); - cel_Value_SetError(top, error); - } break; - } - - _cel_Interpretable_Pop(interp, instr); -} - -static inline void _cel_Interpretable_LogicalOr( - _cel_Interpretable* cel_nonnull interp, - const _cel_InstrData* cel_nonnull instr) { - CEL_ASSERT_NOT_NULL(interp); - CEL_ASSERT_NOT_NULL(instr); - - cel_Value* const top = _cel_Interpretable_TopN(interp, instr, 2); - cel_Value* const lhs = top; - cel_Value* const rhs = lhs + 1; - - switch (cel_Value_Kind(lhs)) { - case cel_ValueKind_kError: { - // error || T - if (cel_Value_Kind(rhs) == cel_ValueKind_kBool && - cel_Value_GetBool(rhs) == true) { - // error || True -> True - cel_Value_SetTrue(top); - } - // Otherwise, error || T -> error, which is already the value of *top. - } break; - case cel_ValueKind_kBool: { - switch (cel_Value_Kind(rhs)) { - case cel_ValueKind_kError: - // bool || error - if (cel_Value_GetBool(lhs) == true) { - // True || error -> True - cel_Value_SetTrue(top); - } else { - // False || error -> error - *top = *rhs; - } - break; - case cel_ValueKind_kBool: - // bool || bool -> bool - cel_Value_SetBool(top, - cel_Value_GetBool(lhs) || cel_Value_GetBool(rhs)); - break; - default: - cel_Value_SetError(top, - _cel_Interpretable_NewNoSuchOverloadError(interp)); - break; - } - } break; - default: { - cel_Error* error = cel_Error_New(interp->arena); - if (CEL_UNLIKELY(error == cel_nullptr)) { - _cel_Interpretable_ThrowOutOfMemory(interp); - } - cel_Error_SetCanonicalCode(error, cel_ErrorCode_kInvalidArgument); - cel_Value_SetError(top, error); - } break; - } - - _cel_Interpretable_Pop(interp, instr); -} - -static inline void _cel_Interpretable_Equals( - _cel_Interpretable* cel_nonnull interp, - const _cel_InstrData* cel_nonnull instr) { - CEL_ASSERT_NOT_NULL(interp); - CEL_ASSERT_NOT_NULL(instr); - - cel_Value* const top = _cel_Interpretable_TopN(interp, instr, 2); - cel_Value* const lhs = top; - cel_Value* const rhs = lhs + 1; - - if (cel_Value_IsError(lhs)) { - // Already on top. - } else if (cel_Value_IsError(rhs)) { - *top = *rhs; - } else { - if (!cel_Value_Equals(lhs, &interp->context, rhs, top, interp->status)) { - _cel_Interpretable_ThrowIfError(interp); - cel_Value_SetError(top, - _cel_Interpretable_NewNoSuchOverloadError(interp)); - } - } - - _cel_Interpretable_Pop(interp, instr); -} - -static inline void _cel_Interpretable_NotEquals( - _cel_Interpretable* cel_nonnull interp, - const _cel_InstrData* cel_nonnull instr) { - CEL_ASSERT_NOT_NULL(interp); - CEL_ASSERT_NOT_NULL(instr); - - cel_Value* const top = _cel_Interpretable_TopN(interp, instr, 2); - cel_Value* const lhs = top; - cel_Value* const rhs = lhs + 1; - - if (cel_Value_IsError(lhs)) { - // Already on top. - } else if (cel_Value_IsError(rhs)) { - *top = *rhs; - } else { - if (cel_Value_Equals(lhs, &interp->context, rhs, top, interp->status)) { - cel_Value_SetBool(top, !cel_Value_GetBool(top)); - } else { - _cel_Interpretable_ThrowIfError(interp); - cel_Value_SetError(top, - _cel_Interpretable_NewNoSuchOverloadError(interp)); - } - } - - _cel_Interpretable_Pop(interp, instr); -} - -CEL_ATTRIBUTE_NODISCARD -static inline bool _cel_Interpretable_Compare( - const cel_Value* cel_nonnull lhs, const cel_Value* cel_nonnull rhs, - cel_ValueKind lhs_kind, cel_ValueKind rhs_kind, - _cel_PartialOrdering* cel_nonnull order) { - if (lhs_kind != rhs_kind) { - // Heterogeneous - switch (lhs_kind) { - case cel_ValueKind_kInt: { - _cel_Number lhs_number = _cel_IntNumber(cel_Value_GetInt(lhs)); - switch (rhs_kind) { - case cel_ValueKind_kUint: { - _cel_Number rhs_number = _cel_UintNumber(cel_Value_GetUint(rhs)); - *order = _cel_Number_Compare(lhs_number, rhs_number); - return true; - } - case cel_ValueKind_kDouble: { - _cel_Number rhs_number = - _cel_DoubleNumber(cel_Value_GetDouble(rhs)); - *order = _cel_Number_Compare(lhs_number, rhs_number); - return true; - } - default: - return false; - } - } - case cel_ValueKind_kUint: { - _cel_Number lhs_number = _cel_UintNumber(cel_Value_GetUint(lhs)); - switch (rhs_kind) { - case cel_ValueKind_kInt: { - _cel_Number rhs_number = _cel_IntNumber(cel_Value_GetInt(rhs)); - *order = _cel_Number_Compare(lhs_number, rhs_number); - return true; - } - case cel_ValueKind_kDouble: { - _cel_Number rhs_number = - _cel_DoubleNumber(cel_Value_GetDouble(rhs)); - *order = _cel_Number_Compare(lhs_number, rhs_number); - return true; - } - default: - return false; - } - } - case cel_ValueKind_kDouble: { - _cel_Number lhs_number = _cel_DoubleNumber(cel_Value_GetDouble(lhs)); - switch (rhs_kind) { - case cel_ValueKind_kInt: { - _cel_Number rhs_number = _cel_IntNumber(cel_Value_GetInt(rhs)); - *order = _cel_Number_Compare(lhs_number, rhs_number); - return true; - } - case cel_ValueKind_kUint: { - _cel_Number rhs_number = _cel_UintNumber(cel_Value_GetUint(rhs)); - *order = _cel_Number_Compare(lhs_number, rhs_number); - return true; - } - default: - return false; - } - } - default: - return false; - } - } - switch (lhs_kind) { - case cel_ValueKind_kBool: { - bool lhs_val = cel_Value_GetBool(lhs); - bool rhs_val = cel_Value_GetBool(rhs); - *order = lhs_val < rhs_val ? _cel_PartialOrdering_kLess - : lhs_val > rhs_val ? _cel_PartialOrdering_kGreater - : _cel_PartialOrdering_kEquivalent; - return true; - } - case cel_ValueKind_kInt: { - int64_t lhs_val = cel_Value_GetInt(lhs); - int64_t rhs_val = cel_Value_GetInt(rhs); - *order = lhs_val < rhs_val ? _cel_PartialOrdering_kLess - : lhs_val > rhs_val ? _cel_PartialOrdering_kGreater - : _cel_PartialOrdering_kEquivalent; - return true; - } - case cel_ValueKind_kUint: { - uint64_t lhs_val = cel_Value_GetUint(lhs); - uint64_t rhs_val = cel_Value_GetUint(rhs); - *order = lhs_val < rhs_val ? _cel_PartialOrdering_kLess - : lhs_val > rhs_val ? _cel_PartialOrdering_kGreater - : _cel_PartialOrdering_kEquivalent; - return true; - } - case cel_ValueKind_kDouble: { - double lhs_val = cel_Value_GetDouble(lhs); - double rhs_val = cel_Value_GetDouble(rhs); - *order = _cel_Number_DoubleCompare(lhs_val, rhs_val); - return true; - } - case cel_ValueKind_kString: { - *order = _cel_PartialOrdering_FromInt(cel_StringView_Compare( - cel_Value_GetString(lhs), cel_Value_GetString(rhs))); - return true; - } - case cel_ValueKind_kBytes: { - *order = _cel_PartialOrdering_FromInt(cel_StringView_Compare( - cel_Value_GetBytes(lhs), cel_Value_GetBytes(rhs))); - return true; - } - case cel_ValueKind_kDuration: { - *order = _cel_PartialOrdering_FromInt(cel_Duration_Compare( - cel_Value_GetDuration(lhs), cel_Value_GetDuration(rhs))); - return true; - } - case cel_ValueKind_kTimestamp: { - *order = _cel_PartialOrdering_FromInt(cel_Timestamp_Compare( - cel_Value_GetTimestamp(lhs), cel_Value_GetTimestamp(rhs))); - return true; - } - default: - return false; - } -} - -static inline void _cel_Interpretable_Less( - _cel_Interpretable* cel_nonnull interp, - const _cel_InstrData* cel_nonnull instr) { - CEL_ASSERT_NOT_NULL(interp); - CEL_ASSERT_NOT_NULL(instr); - - cel_Value* const top = _cel_Interpretable_TopN(interp, instr, 2); - cel_Value* const lhs = top; - cel_Value* const rhs = lhs + 1; - - const cel_ValueKind lhs_kind = cel_Value_Kind(lhs); - const cel_ValueKind rhs_kind = cel_Value_Kind(rhs); - - if (lhs_kind == cel_ValueKind_kError) { - // Already on top. - } else if (rhs_kind == cel_ValueKind_kError) { - *top = *rhs; - } else { - _cel_PartialOrdering order; - if (_cel_Interpretable_Compare(lhs, rhs, lhs_kind, rhs_kind, &order)) { - cel_Value_SetBool(top, order == _cel_PartialOrdering_kLess); - } else { - cel_Value_SetError(top, - _cel_Interpretable_NewNoSuchOverloadError(interp)); - } - } - - _cel_Interpretable_Pop(interp, instr); -} - -static inline void _cel_Interpretable_LessEquals( - _cel_Interpretable* cel_nonnull interp, - const _cel_InstrData* cel_nonnull instr) { - CEL_ASSERT_NOT_NULL(interp); - CEL_ASSERT_NOT_NULL(instr); - - cel_Value* const top = _cel_Interpretable_TopN(interp, instr, 2); - cel_Value* const lhs = top; - cel_Value* const rhs = lhs + 1; - - const cel_ValueKind lhs_kind = cel_Value_Kind(lhs); - const cel_ValueKind rhs_kind = cel_Value_Kind(rhs); - - if (lhs_kind == cel_ValueKind_kError) { - // Already on top. - } else if (rhs_kind == cel_ValueKind_kError) { - *top = *rhs; - } else { - _cel_PartialOrdering order; - if (_cel_Interpretable_Compare(lhs, rhs, lhs_kind, rhs_kind, &order)) { - cel_Value_SetBool(top, order == _cel_PartialOrdering_kLess || - order == _cel_PartialOrdering_kEquivalent); - } else { - cel_Value_SetError(top, - _cel_Interpretable_NewNoSuchOverloadError(interp)); - } - } - - _cel_Interpretable_Pop(interp, instr); -} - -static inline void _cel_Interpretable_Greater( - _cel_Interpretable* cel_nonnull interp, - const _cel_InstrData* cel_nonnull instr) { - CEL_ASSERT_NOT_NULL(interp); - CEL_ASSERT_NOT_NULL(instr); - - cel_Value* const top = _cel_Interpretable_TopN(interp, instr, 2); - cel_Value* const lhs = top; - cel_Value* const rhs = lhs + 1; - - const cel_ValueKind lhs_kind = cel_Value_Kind(lhs); - const cel_ValueKind rhs_kind = cel_Value_Kind(rhs); - - if (lhs_kind == cel_ValueKind_kError) { - // Already on top. - } else if (rhs_kind == cel_ValueKind_kError) { - *top = *rhs; - } else { - _cel_PartialOrdering order; - if (_cel_Interpretable_Compare(lhs, rhs, lhs_kind, rhs_kind, &order)) { - cel_Value_SetBool(top, order == _cel_PartialOrdering_kGreater); - } else { - cel_Value_SetError(top, - _cel_Interpretable_NewNoSuchOverloadError(interp)); - } - } - - _cel_Interpretable_Pop(interp, instr); -} - -static inline void _cel_Interpretable_GreaterEquals( - _cel_Interpretable* cel_nonnull interp, - const _cel_InstrData* cel_nonnull instr) { - CEL_ASSERT_NOT_NULL(interp); - CEL_ASSERT_NOT_NULL(instr); - - cel_Value* const top = _cel_Interpretable_TopN(interp, instr, 2); - cel_Value* const lhs = top; - cel_Value* const rhs = lhs + 1; - - const cel_ValueKind lhs_kind = cel_Value_Kind(lhs); - const cel_ValueKind rhs_kind = cel_Value_Kind(rhs); - - if (lhs_kind == cel_ValueKind_kError) { - // Already on top. - } else if (rhs_kind == cel_ValueKind_kError) { - *top = *rhs; - } else { - _cel_PartialOrdering order; - if (_cel_Interpretable_Compare(lhs, rhs, lhs_kind, rhs_kind, &order)) { - cel_Value_SetBool(top, order == _cel_PartialOrdering_kGreater || - order == _cel_PartialOrdering_kEquivalent); - } else { - cel_Value_SetError(top, - _cel_Interpretable_NewNoSuchOverloadError(interp)); - } - } - - _cel_Interpretable_Pop(interp, instr); -} - -CEL_ATTRIBUTE_NODISCARD -static inline const _cel_Instr* cel_nonnull -_cel_Interpretable_CondJump(_cel_Interpretable* cel_nonnull interp, - const _cel_InstrData* cel_nonnull instr) { - CEL_ASSERT_NOT_NULL(interp); - CEL_ASSERT_NOT_NULL(instr); - CEL_ASSERT_NE(instr->cond_jump.jump, 0); - - cel_Value* const top = _cel_Interpretable_TopN(interp, instr, 1); - if (cel_Value_IsBool(top) && - cel_Value_GetBool(top) == instr->cond_jump.cond) { - return _cel_Interpretable_ShortJump(instr, instr->cond_jump.jump); - } - return _cel_Interpretable_ShortJump(instr, 1); -} - -CEL_ATTRIBUTE_NODISCARD -static inline const _cel_Instr* cel_nonnull -_cel_Interpretable_TrileanJump(_cel_Interpretable* cel_nonnull interp, - const _cel_InstrData* cel_nonnull instr) { - CEL_ASSERT_NOT_NULL(interp); - CEL_ASSERT_NOT_NULL(instr); - CEL_ASSERT_NE(instr->trilean_jump.false_jump, 0); - CEL_ASSERT_NE(instr->trilean_jump.error_jump, 0); - - cel_Value* const top = _cel_Interpretable_TopN(interp, instr, 1); - if (cel_Value_IsError(top)) { - return _cel_Interpretable_ShortJump(instr, instr->trilean_jump.error_jump); - } - if (cel_Value_IsBool(top)) { - int32_t jump = cel_Value_GetBool(top) ? 1 : instr->trilean_jump.false_jump; - _cel_Interpretable_Pop(interp, instr); - return _cel_Interpretable_ShortJump(instr, jump); - } - cel_Value_SetError(top, _cel_Interpretable_NewNoSuchOverloadError(interp)); - return _cel_Interpretable_ShortJump(instr, instr->trilean_jump.error_jump); -} - -CEL_ATTRIBUTE_NODISCARD -static inline const _cel_Instr* cel_nonnull -_cel_Interpretable_ErrorJump(_cel_Interpretable* cel_nonnull interp, - const _cel_InstrData* cel_nonnull instr) { - CEL_ASSERT_NOT_NULL(interp); - CEL_ASSERT_NOT_NULL(instr); - CEL_ASSERT_NE(instr->error_jump.jump, 0); - - cel_Value* const top = _cel_Interpretable_TopN(interp, instr, 1); - if (cel_Value_IsError(top)) { - uint32_t pop = instr->error_jump.pop; - if (pop > 0) { - cel_Value error = *top; - _cel_Interpretable_PopN(interp, instr, pop); - *_cel_Interpretable_Top(interp, instr) = error; - } - return _cel_Interpretable_ShortJump(instr, instr->error_jump.jump); - } - return _cel_Interpretable_ShortJump(instr, 1); -} - -static inline void _cel_Interpretable_List( - _cel_Interpretable* cel_nonnull interp, - const _cel_InstrData* cel_nonnull instr) { - CEL_ASSERT_NOT_NULL(interp); - CEL_ASSERT_NOT_NULL(instr); - - uint32_t element_count = instr->list.count; - if (element_count == 0) { - _cel_EmptyListValue_Set( - cel_Value_SetList(_cel_Interpretable_Push(interp, instr))); - return; - } - cel_Value* src_elements = - _cel_Interpretable_TopN(interp, instr, element_count); - cel_Value value; - cel_ListValue* list_value = cel_Value_SetList(&value); - _cel_MutableListValue_Set(list_value); - if (!_cel_MutableListValue_Reserve(list_value, element_count, - interp->arena)) { - _cel_Interpretable_ThrowOutOfMemory(interp); - } - cel_Value* dst_elements = - _cel_MutableListValue_AddN(list_value, element_count, interp->arena); - if (dst_elements == cel_nullptr) { - _cel_Interpretable_ThrowOutOfMemory(interp); - } - memcpy(dst_elements, src_elements, element_count * sizeof(cel_Value)); - *_cel_Interpretable_PushAndPopN(interp, instr, element_count) = value; -} - -CEL_ATTRIBUTE_NODISCARD -static inline const _cel_Instr* cel_nonnull -_cel_Interpretable_KeyJump(_cel_Interpretable* cel_nonnull interp, - const _cel_InstrData* cel_nonnull instr) { - CEL_ASSERT_NOT_NULL(interp); - CEL_ASSERT_NOT_NULL(instr); - CEL_ASSERT_NE(instr->key_jump.jump, 0); - - cel_Value* const top = _cel_Interpretable_TopN(interp, instr, 1); - if (cel_Value_IsError(top)) { - uint32_t pop = instr->key_jump.pop; - if (pop > 0) { - cel_Value error = *top; - _cel_Interpretable_PopN(interp, instr, pop); - *_cel_Interpretable_Top(interp, instr) = error; - } - return _cel_Interpretable_ShortJump(instr, instr->key_jump.jump); - } - if (!cel_Value_IsMapKey(top)) { - cel_Value_SetError( - _cel_Interpretable_PushAndPopN(interp, instr, instr->key_jump.pop + 1), - _cel_Interpretable_NewBadKeyError(interp)); - return _cel_Interpretable_ShortJump(instr, instr->key_jump.jump); - } - return _cel_Interpretable_ShortJump(instr, 1); -} - -static inline void _cel_Interpretable_Map( - _cel_Interpretable* cel_nonnull interp, - const _cel_InstrData* cel_nonnull instr) { - CEL_ASSERT_NOT_NULL(interp); - CEL_ASSERT_NOT_NULL(instr); - - uint32_t entry_count = instr->map.count; - if (entry_count == 0) { - _cel_EmptyMapValue_Set( - cel_Value_SetMap(_cel_Interpretable_Push(interp, instr))); - return; - } - cel_Value* src_entries = - _cel_Interpretable_TopN(interp, instr, entry_count * 2); - cel_Value value; - cel_MapValue* map_value = cel_Value_SetMap(&value); - _cel_MutableMapValue_Set(map_value); - if (!_cel_MutableMapValue_Reserve(map_value, entry_count, interp->arena)) { - _cel_Interpretable_ThrowOutOfMemory(interp); - } - for (size_t i = 0; i < entry_count; ++i) { - cel_Value* src_entry_key = &src_entries[i * 2]; - cel_MapValueKey entry_key; - switch (cel_Value_Kind(src_entry_key)) { - case cel_ValueKind_kBool: - cel_MapValueKey_SetBool(&entry_key, cel_Value_GetBool(src_entry_key)); - break; - case cel_ValueKind_kInt: - cel_MapValueKey_SetInt(&entry_key, cel_Value_GetInt(src_entry_key)); - break; - case cel_ValueKind_kUint: - cel_MapValueKey_SetUint(&entry_key, cel_Value_GetUint(src_entry_key)); - break; - case cel_ValueKind_kString: - cel_MapValueKey_SetString(&entry_key, - cel_Value_GetString(src_entry_key)); - break; - default: - CEL_UNREACHABLE(); - } - cel_Value* entry_value; - switch (_cel_MutableMapValue_Insert(map_value, &entry_key, cel_nullptr, - &entry_value, interp->arena)) { - case _cel_MutableMapValueInsertResult_kInserted: { - *entry_value = src_entries[i * 2 + 1]; - } break; - case _cel_MutableMapValueInsertResult_kReplaced: { - cel_Value_SetError( - _cel_Interpretable_PushAndPopN(interp, instr, entry_count * 2), - _cel_Interpretable_NewDuplicateKeyError(interp)); - return; - } - case _cel_MutableMapValueInsertResult_kOutOfMemory: - _cel_Interpretable_ThrowOutOfMemory(interp); - } - } - *_cel_Interpretable_PushAndPopN(interp, instr, entry_count * 2) = value; -} - -CEL_ATTRIBUTE_NODISCARD -int _cel_Interpretable_FromCharsToInt(cel_StringView string, int64_t* val) { - const char* data = cel_StringView_Data(string); - size_t size = cel_StringView_Size(string); - _cel_FromCharsResult result = _cel_FromChars(data, data + size, val, 10); - if (result.ec == 0 && result.ptr != data + size) { - return EINVAL; - } - return result.ec; -} - -CEL_ATTRIBUTE_NODISCARD -int _cel_Interpretable_FromCharsToUint(cel_StringView string, uint64_t* val) { - const char* data = cel_StringView_Data(string); - size_t size = cel_StringView_Size(string); - _cel_FromCharsResult result = _cel_FromChars(data, data + size, val, 10); - if (result.ec == 0 && result.ptr != data + size) { - return EINVAL; - } - return result.ec; -} - -CEL_ATTRIBUTE_NODISCARD -int _cel_Interpretable_FromCharsToDouble(cel_StringView string, double* val) { - const char* data = cel_StringView_Data(string); - size_t size = cel_StringView_Size(string); - _cel_FromCharsResult result = _cel_FromChars(data, data + size, val); - if (result.ec == 0 && result.ptr != data + size) { - return EINVAL; - } - return result.ec; -} - -CEL_ATTRIBUTE_NODISCARD -cel_StringView _cel_Interpretable_FromIntToChars(_cel_Interpretable* interp, - long long val) { - CEL_ASSERT_NOT_NULL(interp); - char buffer[_CEL_MAX_INT_CHARS]; - size_t buffer_size = _cel_ToChars(buffer, val, 10); - char* data = (char*)cel_Arena_Malloc(interp->arena, buffer_size, cel_nullptr); - if (CEL_UNLIKELY(data == cel_nullptr)) { - _cel_Interpretable_ThrowOutOfMemory(interp); - } - memcpy(data, buffer, buffer_size); - return cel_StringView_FromArray(data, buffer_size); -} - -CEL_ATTRIBUTE_NODISCARD -cel_StringView _cel_Interpretable_FromUintToChars(_cel_Interpretable* interp, - unsigned long long val) { - CEL_ASSERT_NOT_NULL(interp); - char buffer[_CEL_MAX_UINT_CHARS]; - size_t buffer_size = _cel_ToChars(buffer, val, 10); - char* data = (char*)cel_Arena_Malloc(interp->arena, buffer_size, cel_nullptr); - if (CEL_UNLIKELY(data == cel_nullptr)) { - _cel_Interpretable_ThrowOutOfMemory(interp); - } - memcpy(data, buffer, buffer_size); - return cel_StringView_FromArray(data, buffer_size); -} - -CEL_ATTRIBUTE_NODISCARD -cel_StringView _cel_Interpretable_FromDoubleToChars(_cel_Interpretable* interp, - double val) { - CEL_ASSERT_NOT_NULL(interp); - char buffer[_CEL_MAX_DOUBLE_CHARS]; - size_t buffer_size = _cel_ToChars(buffer, val); - char* data = (char*)cel_Arena_Malloc(interp->arena, buffer_size, cel_nullptr); - if (CEL_UNLIKELY(data == cel_nullptr)) { - _cel_Interpretable_ThrowOutOfMemory(interp); - } - memcpy(data, buffer, buffer_size); - return cel_StringView_FromArray(data, buffer_size); -} - -static inline void _cel_Interpretable_CallUint( - _cel_Interpretable* cel_nonnull interp, - const _cel_InstrData* cel_nonnull instr) { - CEL_ASSERT_NOT_NULL(interp); - CEL_ASSERT_NOT_NULL(instr); - CEL_ASSERT(instr->call.args == 1); - - cel_Value* const top = _cel_Interpretable_Top(interp, instr); - switch (cel_Value_Kind(top)) { - case cel_ValueKind_kError: - break; - case cel_ValueKind_kInt: { - _cel_Number number = _cel_IntNumber(cel_Value_GetInt(top)); - uint64_t uint_value; - if (!_cel_Number_ToUint(number, &uint_value)) { - cel_Value_SetError(top, - _cel_Interpretable_NewNoSuchOverloadError(interp)); - } else { - cel_Value_SetUint(top, uint_value); - } - } break; - case cel_ValueKind_kUint: - cel_Value_SetUint(top, cel_Value_GetUint(top)); - break; - case cel_ValueKind_kDouble: { - _cel_Number number = _cel_DoubleNumber(cel_Value_GetDouble(top)); - uint64_t uint_value; - if (!_cel_Number_ToUint(number, &uint_value)) { - cel_Value_SetError(top, - _cel_Interpretable_NewNoSuchOverloadError(interp)); - } else { - cel_Value_SetUint(top, uint_value); - } - } break; - case cel_ValueKind_kString: { - uint64_t value; - cel_StringView str = cel_Value_GetString(top); - if (_cel_Interpretable_FromCharsToUint(str, &value) != 0) { - cel_Value_SetError(top, - _cel_Interpretable_NewNoSuchOverloadError(interp)); - } else { - cel_Value_SetUint(top, value); - } - } break; - default: - cel_Value_SetError(top, - _cel_Interpretable_NewNoSuchOverloadError(interp)); - } -} - -static inline void _cel_Interpretable_CallDouble( - _cel_Interpretable* cel_nonnull interp, - const _cel_InstrData* cel_nonnull instr) { - CEL_ASSERT_NOT_NULL(interp); - CEL_ASSERT_NOT_NULL(instr); - CEL_ASSERT(instr->call.args == 1); - - cel_Value* const top = _cel_Interpretable_Top(interp, instr); - switch (cel_Value_Kind(top)) { - case cel_ValueKind_kError: - break; - case cel_ValueKind_kInt: { - _cel_Number number = _cel_IntNumber(cel_Value_GetInt(top)); - double double_value = _cel_Number_ToDouble(number); - if (double_value == NAN) { - cel_Value_SetError(top, - _cel_Interpretable_NewNoSuchOverloadError(interp)); - } else { - cel_Value_SetDouble(top, double_value); - } - } break; - case cel_ValueKind_kUint: { - _cel_Number number = _cel_UintNumber(cel_Value_GetUint(top)); - double double_value = _cel_Number_ToDouble(number); - if (double_value == NAN) { - cel_Value_SetError(top, - _cel_Interpretable_NewNoSuchOverloadError(interp)); - } else { - cel_Value_SetDouble(top, double_value); - } - } break; - case cel_ValueKind_kDouble: - cel_Value_SetDouble(top, cel_Value_GetDouble(top)); - break; - case cel_ValueKind_kString: { - double value; - cel_StringView str = cel_Value_GetString(top); - if (_cel_Interpretable_FromCharsToDouble(str, &value) != 0) { - cel_Value_SetError(top, - _cel_Interpretable_NewNoSuchOverloadError(interp)); - } else { - cel_Value_SetDouble(top, value); - } - } break; - default: - cel_Value_SetError(top, - _cel_Interpretable_NewNoSuchOverloadError(interp)); - } -} - -static inline void _cel_Interpretable_CallBytes( - _cel_Interpretable* cel_nonnull interp, - const _cel_InstrData* cel_nonnull instr) { - CEL_ASSERT_NOT_NULL(interp); - CEL_ASSERT_NOT_NULL(instr); - CEL_ASSERT(instr->call.args == 1); - - cel_Value* const top = _cel_Interpretable_Top(interp, instr); - switch (cel_Value_Kind(top)) { - case cel_ValueKind_kError: - break; - case cel_ValueKind_kBytes: - cel_Value_SetBytes(top, cel_Value_GetBytes(top)); - break; - case cel_ValueKind_kString: - cel_Value_SetBytes(top, cel_Value_GetString(top)); - break; - default: - cel_Value_SetError(top, - _cel_Interpretable_NewNoSuchOverloadError(interp)); - } -} - -static inline void _cel_Interpretable_CallString( - _cel_Interpretable* cel_nonnull interp, - const _cel_InstrData* cel_nonnull instr) { - CEL_ASSERT_NOT_NULL(interp); - CEL_ASSERT_NOT_NULL(instr); - CEL_ASSERT(instr->call.args == 1); - - cel_Value* const top = _cel_Interpretable_Top(interp, instr); - switch (cel_Value_Kind(top)) { - case cel_ValueKind_kError: - break; - case cel_ValueKind_kBool: { - cel_Value_SetString(top, cel_Value_GetBool(top) - ? cel_StringView_From("true") - : cel_StringView_From("false")); - } break; - case cel_ValueKind_kInt: { - long long value = cel_Value_GetInt(top); - cel_Value_SetString(top, - _cel_Interpretable_FromIntToChars(interp, value)); - } break; - case cel_ValueKind_kUint: { - unsigned long long value = cel_Value_GetUint(top); - cel_Value_SetString(top, - _cel_Interpretable_FromUintToChars(interp, value)); - } break; - case cel_ValueKind_kDouble: { - double value = cel_Value_GetDouble(top); - cel_Value_SetString(top, - _cel_Interpretable_FromDoubleToChars(interp, value)); - } break; - case cel_ValueKind_kBytes: { - cel_StringView bytes = cel_Value_GetBytes(top); - if (!_cel_Utf8_IsValid(bytes)) { - cel_Value_SetError(top, - _cel_Interpretable_NewNoSuchOverloadError(interp)); - } else { - cel_Value_SetString(top, bytes); - } - } break; - case cel_ValueKind_kString: - cel_Value_SetString(top, cel_Value_GetString(top)); - break; - case cel_ValueKind_kTimestamp: { - cel_StringView str; - if (!_cel_Timestamp_ToRFC3339(cel_Value_GetTimestamp(top), &str, - interp->arena)) { - cel_Value_SetError(top, - _cel_Interpretable_NewNoSuchOverloadError(interp)); - } else { - cel_Value_SetString(top, str); - } - } break; - case cel_ValueKind_kDuration: { - cel_StringView str; - if (!_cel_Duration_ToStringView(cel_Value_GetDuration(top), interp->arena, - &str)) { - cel_Value_SetError(top, - _cel_Interpretable_NewNoSuchOverloadError(interp)); - } else { - cel_Value_SetString(top, str); - } - } break; - default: - cel_Value_SetError(top, - _cel_Interpretable_NewNoSuchOverloadError(interp)); - } -} - -static inline void _cel_Interpretable_CallBool( - _cel_Interpretable* cel_nonnull interp, - const _cel_InstrData* cel_nonnull instr) { - CEL_ASSERT_NOT_NULL(interp); - CEL_ASSERT_NOT_NULL(instr); - CEL_ASSERT(instr->call.args == 1); - - cel_Value* const top = _cel_Interpretable_Top(interp, instr); - switch (cel_Value_Kind(top)) { - case cel_ValueKind_kError: - break; - case cel_ValueKind_kBool: - cel_Value_SetBool(top, cel_Value_GetBool(top)); - break; - case cel_ValueKind_kString: { - cel_StringView value = cel_Value_GetString(top); - if (cel_StringView_EqualsIgnoreCase(value, cel_StringView_From("true"))) { - cel_Value_SetBool(top, true); - } else if (cel_StringView_EqualsIgnoreCase( - value, cel_StringView_From("false"))) { - cel_Value_SetBool(top, false); - } else { - cel_Value_SetError(top, - _cel_Interpretable_NewNoSuchOverloadError(interp)); - } - } break; - default: - cel_Value_SetError(top, - _cel_Interpretable_NewNoSuchOverloadError(interp)); - } -} - -static inline void _cel_Interpretable_CallTimestamp( - _cel_Interpretable* cel_nonnull interp, - const _cel_InstrData* cel_nonnull instr) { - CEL_ASSERT_NOT_NULL(interp); - CEL_ASSERT_NOT_NULL(instr); - CEL_ASSERT(instr->call.args == 1); - - cel_Value* const top = _cel_Interpretable_Top(interp, instr); - switch (cel_Value_Kind(top)) { - case cel_ValueKind_kError: - break; - case cel_ValueKind_kTimestamp: - cel_Value_SetTimestamp(top, cel_Value_GetTimestamp(top)); - break; - case cel_ValueKind_kString: { - cel_Timestamp value; - cel_StringView str = cel_Value_GetString(top); - if (!_cel_Timestamp_FromRFC3339(&value, str)) { - cel_Value_SetError(top, - _cel_Interpretable_NewNoSuchOverloadError(interp)); - } else { - cel_Value_SetTimestamp(top, value); - } - } break; - default: - cel_Value_SetError(top, - _cel_Interpretable_NewNoSuchOverloadError(interp)); - } -} - -static inline void _cel_Interpretable_CallDuration( - _cel_Interpretable* cel_nonnull interp, - const _cel_InstrData* cel_nonnull instr) { - CEL_ASSERT_NOT_NULL(interp); - CEL_ASSERT_NOT_NULL(instr); - CEL_ASSERT(instr->call.args == 1); - - cel_Value* const top = _cel_Interpretable_Top(interp, instr); - switch (cel_Value_Kind(top)) { - case cel_ValueKind_kError: - break; - case cel_ValueKind_kDuration: - cel_Value_SetDuration(top, cel_Value_GetDuration(top)); - break; - case cel_ValueKind_kString: { - cel_Duration value; - cel_StringView str = cel_Value_GetString(top); - if (!_cel_Duration_FromStringView(str, &value)) { - cel_Value_SetError(top, - _cel_Interpretable_NewNoSuchOverloadError(interp)); - } else { - cel_Value_SetDuration(top, value); - } - } break; - default: - cel_Value_SetError(top, - _cel_Interpretable_NewNoSuchOverloadError(interp)); - } -} - -static inline void _cel_Interpretable_CallContainsString( - _cel_Interpretable* cel_nonnull interp, - const _cel_InstrData* cel_nonnull instr) { - CEL_ASSERT_NOT_NULL(interp); - CEL_ASSERT_NOT_NULL(instr); - CEL_ASSERT(instr->call.args == 2); - - cel_Value* const top = _cel_Interpretable_TopN(interp, instr, 2); - cel_Value* const str = top; - cel_Value* const substr = str + 1; - - switch (cel_Value_Kind(str)) { - case cel_ValueKind_kError: - break; - case cel_ValueKind_kString: - switch (cel_Value_Kind(substr)) { - case cel_ValueKind_kError: - *top = *substr; - break; - case cel_ValueKind_kString: - cel_Value_SetBool( - top, cel_StringView_FindFirst(cel_Value_GetString(str), - cel_Value_GetString(substr)) != - cel_nullptr); - break; - default: - cel_Value_SetError(top, - _cel_Interpretable_NewNoSuchOverloadError(interp)); - break; - } - break; - default: - if (cel_Value_IsError(substr)) { - *top = *substr; - } else { - cel_Value_SetError(top, - _cel_Interpretable_NewNoSuchOverloadError(interp)); - } - break; - } - - _cel_Interpretable_Pop(interp, instr); -} - -static inline void _cel_Interpretable_CallStartsWithString( - _cel_Interpretable* cel_nonnull interp, - const _cel_InstrData* cel_nonnull instr) { - CEL_ASSERT_NOT_NULL(interp); - CEL_ASSERT_NOT_NULL(instr); - CEL_ASSERT(instr->call.args == 2); - - cel_Value* const top = _cel_Interpretable_TopN(interp, instr, 2); - cel_Value* const str = top; - cel_Value* const substr = str + 1; - - switch (cel_Value_Kind(str)) { - case cel_ValueKind_kError: - break; - case cel_ValueKind_kString: - switch (cel_Value_Kind(substr)) { - case cel_ValueKind_kError: - *top = *substr; - break; - case cel_ValueKind_kString: - cel_Value_SetBool( - top, cel_StringView_StartsWith(cel_Value_GetString(str), - cel_Value_GetString(substr))); - break; - default: - cel_Value_SetError(top, - _cel_Interpretable_NewNoSuchOverloadError(interp)); - break; - } - break; - default: - if (cel_Value_IsError(substr)) { - *top = *substr; - } else { - cel_Value_SetError(top, - _cel_Interpretable_NewNoSuchOverloadError(interp)); - } - break; - } - - _cel_Interpretable_Pop(interp, instr); -} - -static inline void _cel_Interpretable_CallEndsWithString( - _cel_Interpretable* cel_nonnull interp, - const _cel_InstrData* cel_nonnull instr) { - CEL_ASSERT_NOT_NULL(interp); - CEL_ASSERT_NOT_NULL(instr); - CEL_ASSERT(instr->call.args == 2); - - cel_Value* const top = _cel_Interpretable_TopN(interp, instr, 2); - cel_Value* const str = top; - cel_Value* const substr = str + 1; - - switch (cel_Value_Kind(str)) { - case cel_ValueKind_kError: - break; - case cel_ValueKind_kString: - switch (cel_Value_Kind(substr)) { - case cel_ValueKind_kError: - *top = *substr; - break; - case cel_ValueKind_kString: - cel_Value_SetBool( - top, cel_StringView_EndsWith(cel_Value_GetString(str), - cel_Value_GetString(substr))); - break; - default: - cel_Value_SetError(top, - _cel_Interpretable_NewNoSuchOverloadError(interp)); - break; - } - break; - default: - if (cel_Value_IsError(substr)) { - *top = *substr; - } else { - cel_Value_SetError(top, - _cel_Interpretable_NewNoSuchOverloadError(interp)); - } - break; - } - - _cel_Interpretable_Pop(interp, instr); -} - -static inline void _cel_Interpretable_CallRegexExpMatch( - _cel_Interpretable* cel_nonnull interp, - const _cel_InstrData* cel_nonnull instr) { - CEL_ASSERT_NOT_NULL(interp); - CEL_ASSERT_NOT_NULL(instr); - CEL_ASSERT(instr->call.args == 2); - - cel_Value* const top = _cel_Interpretable_TopN(interp, instr, 2); - cel_Value* const str = top; - cel_Value* const regex = str + 1; - - switch (cel_Value_Kind(str)) { - case cel_ValueKind_kError: - break; - case cel_ValueKind_kString: - switch (cel_Value_Kind(regex)) { - case cel_ValueKind_kError: - *top = *regex; - break; - case cel_ValueKind_kString: { - cel_Status status; - cel_Status_Construct(&status); - cel_StringView pattern = cel_Value_GetString(regex); - cel_StringView subject = cel_Value_GetString(str); - // TODO: Enable regexp limits to be configurable. - bool matched = - _cel_RegExp_Matches(pattern, cel_nullptr, subject, &status); - if (CEL_UNLIKELY(!cel_Status_Ok(&status))) { - cel_Error* error = cel_Error_New(interp->arena); - if (CEL_UNLIKELY(error == cel_nullptr)) { - cel_Status_Destruct(&status); - _cel_Interpretable_ThrowOutOfMemory(interp); - } - cel_Error_SetMessage(error, cel_Status_Message(&status)); - cel_Value_SetError(top, error); - } else { - cel_Value_SetBool(top, matched); - } - cel_Status_Destruct(&status); - } break; - default: - cel_Value_SetError(top, - _cel_Interpretable_NewNoSuchOverloadError(interp)); - break; - } - break; - default: - if (cel_Value_IsError(regex)) { - *top = *regex; - } else { - cel_Value_SetError(top, - _cel_Interpretable_NewNoSuchOverloadError(interp)); - } - break; - } - _cel_Interpretable_Pop(interp, instr); -} - -static inline void _cel_Interpretable_CallInt( - _cel_Interpretable* cel_nonnull interp, - const _cel_InstrData* cel_nonnull instr) { - CEL_ASSERT_NOT_NULL(interp); - CEL_ASSERT_NOT_NULL(instr); - CEL_ASSERT(instr->call.args == 1); - - cel_Value* const top = _cel_Interpretable_Top(interp, instr); - switch (cel_Value_Kind(top)) { - case cel_ValueKind_kError: - break; - case cel_ValueKind_kInt: - cel_Value_SetInt(top, cel_Value_GetInt(top)); - break; - case cel_ValueKind_kUint: { - _cel_Number number = _cel_UintNumber(cel_Value_GetUint(top)); - int64_t int_value; - if (!_cel_Number_ToInt(number, &int_value)) { - cel_Value_SetError(top, _cel_Interpretable_NewIntOverflowError(interp)); - } else { - cel_Value_SetInt(top, int_value); - } - } break; - case cel_ValueKind_kDouble: { - _cel_Number number = _cel_DoubleNumber(cel_Value_GetDouble(top)); - int64_t int_value; - if (!_cel_Number_ToInt(number, &int_value)) { - cel_Value_SetError(top, _cel_Interpretable_NewIntOverflowError(interp)); - } else { - cel_Value_SetInt(top, int_value); - } - } break; - case cel_ValueKind_kString: { - int64_t value; - cel_StringView str = cel_Value_GetString(top); - if (_cel_Interpretable_FromCharsToInt(str, &value) != 0) { - cel_Value_SetError(top, - _cel_Interpretable_NewNoSuchOverloadError(interp)); - } else { - cel_Value_SetInt(top, value); - } - } break; - case cel_ValueKind_kTimestamp: { - cel_Value_SetInt( - top, cel_Timestamp_ToUnixSeconds(cel_Value_GetTimestamp(top))); - } break; - default: - cel_Value_SetError(top, - _cel_Interpretable_NewNoSuchOverloadError(interp)); - } -} - -static inline void _cel_Interpretable_CallSize( - _cel_Interpretable* cel_nonnull interp, - const _cel_InstrData* cel_nonnull instr) { - CEL_ASSERT_NOT_NULL(interp); - CEL_ASSERT_NOT_NULL(instr); - CEL_ASSERT(instr->call.args == 1); - - cel_Value* const top = _cel_Interpretable_Top(interp, instr); - switch (cel_Value_Kind(top)) { - case cel_ValueKind_kError: - break; - case cel_ValueKind_kString: - cel_Value_SetInt(top, _cel_Utf8_DecodedSize(cel_Value_GetString(top))); - break; - case cel_ValueKind_kBytes: - cel_Value_SetInt(top, cel_StringView_Size(cel_Value_GetBytes(top))); - break; - // TODO: Add support for other types. - default: - cel_Value_SetError(top, - _cel_Interpretable_NewNoSuchOverloadError(interp)); - } -} - -static inline void _cel_Interpretable_Index( - _cel_Interpretable* cel_nonnull interp, - const _cel_InstrData* cel_nonnull instr) { - CEL_ASSERT_NOT_NULL(interp); - CEL_ASSERT_NOT_NULL(instr); - - cel_Value* const top = _cel_Interpretable_TopN(interp, instr, 2); - cel_Value* const lhs = top; - cel_Value* const rhs = lhs + 1; - - cel_ValueContext context = interp->context; - - switch (cel_Value_Kind(lhs)) { - case cel_ValueKind_kError: - // error[T] -> error - break; - case cel_ValueKind_kList: { - int64_t index; - bool index_is_int = false; - if (cel_Value_Kind(rhs) == cel_ValueKind_kError) { - *top = *rhs; - break; - } - switch (cel_Value_Kind(rhs)) { - case cel_ValueKind_kInt: - index = cel_Value_GetInt(rhs); - index_is_int = true; - break; - case cel_ValueKind_kUint: - index_is_int = _cel_Number_ToIntLossless( - _cel_UintNumber(cel_Value_GetUint(rhs)), &index); - break; - case cel_ValueKind_kDouble: - index_is_int = _cel_Number_ToIntLossless( - _cel_DoubleNumber(cel_Value_GetDouble(rhs)), &index); - break; - default: - index_is_int = false; - break; - } - - if (!index_is_int) { - cel_Value_SetError(top, - _cel_Interpretable_NewNoSuchOverloadError(interp)); - break; - } - - // List[int] -> cel_value - cel_Value list_size; - const cel_ListValue* list_value = cel_Value_GetList(lhs); - if (!cel_ListValue_Size(list_value, &context, &list_size, - interp->status)) { - _cel_Interpretable_Throw(interp); - } - if (index < 0 || index >= cel_Value_GetInt(&list_size)) { - cel_Value_SetError(top, - _cel_Interpretable_NewIndexOutOfRangeError(interp)); - } else { - if (!cel_ListValue_Get(list_value, &context, index, top, - interp->status)) { - _cel_Interpretable_Throw(interp); - } - } - } break; - case cel_ValueKind_kMap: { - cel_MapValueKey key; - bool in_error = false; - switch (cel_Value_Kind(rhs)) { - case cel_ValueKind_kError: - *top = *rhs; - in_error = true; - break; - case cel_ValueKind_kInt: - cel_MapValueKey_SetInt(&key, cel_Value_GetInt(rhs)); - break; - case cel_ValueKind_kUint: - cel_MapValueKey_SetUint(&key, cel_Value_GetUint(rhs)); - break; - case cel_ValueKind_kBool: - cel_MapValueKey_SetBool(&key, cel_Value_GetBool(rhs)); - break; - case cel_ValueKind_kString: - cel_MapValueKey_SetString(&key, cel_Value_GetString(rhs)); - break; - default: - cel_Value_SetError(top, - _cel_Interpretable_NewNoSuchOverloadError(interp)); - in_error = true; - break; - } - if (!in_error) { - cel_MapValue map_value = *cel_Value_GetMap(lhs); - cel_Value has_result; - if (!cel_MapValue_Has(&map_value, &interp->context, &key, &has_result, - interp->status)) { - _cel_Interpretable_Throw(interp); - } - if (!cel_Value_GetBool(&has_result)) { - cel_Value_SetError(top, _cel_Interpretable_NewNoSuchKeyError(interp)); - } else { - if (!cel_MapValue_Get(&map_value, &interp->context, &key, top, - interp->status)) { - _cel_Interpretable_Throw(interp); - } - } - } - } break; - default: { - cel_Value_SetError(top, - _cel_Interpretable_NewNoSuchOverloadError(interp)); - } break; - } - - _cel_Interpretable_Pop(interp, instr); -} - -static inline void _cel_Interpretable_In(_cel_Interpretable* cel_nonnull interp, - const _cel_InstrData* cel_nonnull - instr) { - CEL_ASSERT_NOT_NULL(interp); - CEL_ASSERT_NOT_NULL(instr); - - cel_Value* const top = _cel_Interpretable_TopN(interp, instr, 2); - cel_Value* const lhs = top; - cel_Value* const rhs = lhs + 1; - - switch (cel_Value_Kind(rhs)) { - case cel_ValueKind_kError: - if (!cel_Value_IsError(lhs)) { - *top = *rhs; - } - break; - case cel_ValueKind_kList: { - if (cel_Value_IsError(lhs)) { - break; - } - const cel_ListValue* list_value = cel_Value_GetList(rhs); - cel_Value list_size_value; - if (!cel_ListValue_Size(list_value, &interp->context, &list_size_value, - interp->status)) { - _cel_Interpretable_Throw(interp); - } - int64_t list_size = cel_Value_GetInt(&list_size_value); - bool present = false; - for (int64_t i = 0; i < list_size; ++i) { - cel_Value element; - if (!cel_ListValue_Get(list_value, &interp->context, i, &element, - interp->status)) { - _cel_Interpretable_Throw(interp); - } - cel_Value eq_result; - if (!cel_Value_Equals(lhs, &interp->context, &element, &eq_result, - interp->status)) { - _cel_Interpretable_ThrowIfError(interp); - continue; - } - if (cel_Value_IsError(&eq_result)) { - continue; - } - if (cel_Value_IsBool(&eq_result) && cel_Value_GetBool(&eq_result)) { - present = true; - break; - } - } - cel_Value_SetBool(top, present); - } break; - case cel_ValueKind_kMap: { - if (cel_Value_IsError(lhs)) { - break; - } - if (!cel_Value_IsMapKey(lhs)) { - cel_Value_SetError(top, _cel_Interpretable_NewBadKeyError(interp)); - break; - } - cel_MapValueKey key; - switch (cel_Value_Kind(lhs)) { - case cel_ValueKind_kBool: - cel_MapValueKey_SetBool(&key, cel_Value_GetBool(lhs)); - break; - case cel_ValueKind_kInt: - cel_MapValueKey_SetInt(&key, cel_Value_GetInt(lhs)); - break; - case cel_ValueKind_kUint: - cel_MapValueKey_SetUint(&key, cel_Value_GetUint(lhs)); - break; - case cel_ValueKind_kString: - cel_MapValueKey_SetString(&key, cel_Value_GetString(lhs)); - break; - default: - // Unreachable - CEL_UNREACHABLE(); - } - const cel_MapValue* map_value = cel_Value_GetMap(rhs); - if (!cel_MapValue_Has(map_value, &interp->context, &key, top, - interp->status)) { - _cel_Interpretable_Throw(interp); - } - if (cel_Value_IsError(top)) { - cel_Value_SetBool(top, false); - } - } break; - default: { - if (cel_Value_IsError(lhs)) { - break; - } - cel_Value_SetError(top, - _cel_Interpretable_NewNoSuchOverloadError(interp)); - } break; - } - - _cel_Interpretable_Pop(interp, instr); -} - -CEL_ATTRIBUTE_NODISCARD -static inline const _cel_Instr* cel_nonnull -_cel_Interpretable_LazyCall(_cel_Interpretable* cel_nonnull interp, - const _cel_InstrData* cel_nonnull instr) { - if (CEL_UNLIKELY(instr->lazy_call.slot) >= interp->slots_len) { - cel_InternalStatusF( - interp->status, "cel: bad slot: pc=%" PRIuPTR, - cel_containerof(instr, _cel_Instr, data) - interp->instr_ptr); - _cel_Interpretable_Throw(interp); - } - _cel_InterpretableSlot* slot = &interp->slots[instr->lazy_call.slot]; - const _cel_Instr* next = _cel_Interpretable_ShortJump(instr, 1); - if (slot->active) { - *_cel_Interpretable_Push(interp, instr) = slot->value; - return next; - } - if (CEL_UNLIKELY(interp->lazy_stack_top == interp->lazy_stack_end)) { - cel_InternalStatusF( - interp->status, "cel: lazy stack overflow: pc=%" PRIuPTR, - cel_containerof(instr, _cel_Instr, data) - interp->instr_ptr); - _cel_Interpretable_Throw(interp); - } - *interp->lazy_stack_top = next; - ++interp->lazy_stack_top; - return _cel_Interpretable_ShortJump(instr, instr->lazy_call.jump); -} - -CEL_ATTRIBUTE_NODISCARD -static inline const _cel_Instr* cel_nonnull -_cel_Interpretable_LazyReturn(_cel_Interpretable* cel_nonnull interp, - const _cel_InstrData* cel_nonnull instr) { - if (CEL_UNLIKELY(instr->lazy_return.slot) >= interp->slots_len) { - cel_InternalStatusF( - interp->status, "cel: bad slot: pc=%" PRIuPTR, - cel_containerof(instr, _cel_Instr, data) - interp->instr_ptr); - _cel_Interpretable_Throw(interp); - } - if (CEL_UNLIKELY(interp->lazy_stack_top == interp->lazy_stack_base)) { - cel_InternalStatusF( - interp->status, "cel: lazy stack underflow: pc=%" PRIuPTR, - cel_containerof(instr, _cel_Instr, data) - interp->instr_ptr); - _cel_Interpretable_Throw(interp); - } - _cel_InterpretableSlot* slot = &interp->slots[instr->lazy_call.slot]; - if (CEL_UNLIKELY(slot->active)) { - cel_InternalStatusF( - interp->status, "cel: slot reused: pc=%" PRIuPTR, - cel_containerof(instr, _cel_Instr, data) - interp->instr_ptr); - _cel_Interpretable_Throw(interp); - } - slot->value = *_cel_Interpretable_Top(interp, instr); - slot->active = true; - --interp->lazy_stack_top; - return *interp->lazy_stack_top; -} - -static inline void _cel_Interpretable_LazyEnter( - _cel_Interpretable* cel_nonnull interp, - const _cel_InstrData* cel_nonnull instr) { - CEL_ASSERT_LT(instr->lazy_enter.slot, interp->slots_len); - if (CEL_UNLIKELY(interp->slots[instr->lazy_enter.slot].active)) { - cel_InternalStatusF( - interp->status, "cel: slot reused: pc=%" PRIuPTR, - cel_containerof(instr, _cel_Instr, data) - interp->instr_ptr); - _cel_Interpretable_Throw(interp); - } -} - -static inline void _cel_Interpretable_LazyLeave( - _cel_Interpretable* cel_nonnull interp, - const _cel_InstrData* cel_nonnull instr) { - CEL_ASSERT_GE(instr->lazy_leave.slot, 0); - CEL_ASSERT_LT(instr->lazy_leave.slot, interp->slots_len); - CEL_ASSERT_LE(instr->lazy_leave.slot + instr->lazy_leave.num_slots, - interp->slots_len); - for (uint32_t i = 0; i < instr->lazy_leave.num_slots; ++i) { - interp->slots[instr->lazy_leave.slot + i].active = false; - } -} - -#if defined(__GNUC__) || defined(__clang__) -static inline void _cel_Interpretable_ComputedGoto( - _cel_Interpretable* const cel_nonnull interp, - cel_Value* const cel_nonnull result) { - static const void* const dispatch_table[] = { - [_cel_InstrKind_kUnreachable] = &&INSTR_UNREACHABLE, - [_cel_InstrKind_kNullConst] = &&INSTR_NULL_CONST, - [_cel_InstrKind_kFalseConst] = &&INSTR_FALSE_CONST, - [_cel_InstrKind_kTrueConst] = &&INSTR_TRUE_CONST, - [_cel_InstrKind_kIntConst] = &&INSTR_INT_CONST, - [_cel_InstrKind_kUintConst] = &&INSTR_UINT_CONST, - [_cel_InstrKind_kDoubleConst] = &&INSTR_DOUBLE_CONST, - [_cel_InstrKind_kBytesConst] = &&INSTR_BYTES_CONST, - [_cel_InstrKind_kStringConst] = &&INSTR_STRING_CONST, - [_cel_InstrKind_kDurationConst] = &&INSTR_DURATION_CONST, - [_cel_InstrKind_kTimestampConst] = &&INSTR_TIMESTAMP_CONST, - [_cel_InstrKind_kIdent] = &&INSTR_IDENT, - [_cel_InstrKind_kIdentJump] = &&INSTR_IDENT_JUMP, - [_cel_InstrKind_kContIdent] = &&INSTR_CONT_IDENT, - [_cel_InstrKind_kContIdentJump] = &&INSTR_CONT_IDENT_JUMP, - [_cel_InstrKind_kJump] = &&INSTR_JUMP, - [_cel_InstrKind_kHas] = &&INSTR_HAS, - [_cel_InstrKind_kMessageHas] = &&INSTR_MESSAGE_HAS, - [_cel_InstrKind_kSelect] = &&INSTR_SELECT, - [_cel_InstrKind_kMessageSelect] = &&INSTR_MESSAGE_SELECT, - [_cel_InstrKind_kAdd] = &&INSTR_ADD, - [_cel_InstrKind_kSubtract] = &&INSTR_SUBTRACT, - [_cel_InstrKind_kMultiply] = &&INSTR_MULTIPLY, - [_cel_InstrKind_kDivide] = &&INSTR_DIVIDE, - [_cel_InstrKind_kModulo] = &&INSTR_MODULO, - [_cel_InstrKind_kLogicalNot] = &&INSTR_LOGICAL_NOT, - [_cel_InstrKind_kNegate] = &&INSTR_NEGATE, - [_cel_InstrKind_kLogicalAnd] = &&INSTR_LOGICAL_AND, - [_cel_InstrKind_kLogicalOr] = &&INSTR_LOGICAL_OR, - [_cel_InstrKind_kEquals] = &&INSTR_EQUALS, - [_cel_InstrKind_kNotEquals] = &&INSTR_NOT_EQUALS, - [_cel_InstrKind_kLess] = &&INSTR_LESS, - [_cel_InstrKind_kLessEquals] = &&INSTR_LESS_EQUALS, - [_cel_InstrKind_kGreater] = &&INSTR_GREATER, - [_cel_InstrKind_kGreaterEquals] = &&INSTR_GREATER_EQUALS, - [_cel_InstrKind_kCondJump] = &&INSTR_COND_JUMP, - [_cel_InstrKind_kTrileanJump] = &&INSTR_TRILEAN_JUMP, - [_cel_InstrKind_kErrorJump] = &&INSTR_ERROR_JUMP, - [_cel_InstrKind_kList] = &&INSTR_LIST, - [_cel_InstrKind_kKeyJump] = &&INSTR_KEY_JUMP, - [_cel_InstrKind_kMap] = &&INSTR_MAP, - [_cel_InstrKind_kCallBool] = &&INSTR_CALL_BOOL, - [_cel_InstrKind_kCallInt] = &&INSTR_CALL_INT, - [_cel_InstrKind_kCallUint] = &&INSTR_CALL_UINT, - [_cel_InstrKind_kCallDouble] = &&INSTR_CALL_DOUBLE, - [_cel_InstrKind_kCallBytes] = &&INSTR_CALL_BYTES, - [_cel_InstrKind_kCallString] = &&INSTR_CALL_STRING, - [_cel_InstrKind_kCallTimestamp] = &&INSTR_CALL_TIMESTAMP, - [_cel_InstrKind_kCallDuration] = &&INSTR_CALL_DURATION, - [_cel_InstrKind_kCallSize] = &&INSTR_CALL_SIZE, - [_cel_InstrKind_kCallContainsString] = &&INSTR_CALL_CONTAINS_STRING, - [_cel_InstrKind_kCallStartsWithString] = &&INSTR_CALL_STARTS_WITH_STRING, - [_cel_InstrKind_kCallEndsWithString] = &&INSTR_CALL_ENDS_WITH_STRING, - [_cel_InstrKind_kCallRegexExpMatch] = &&INSTR_CALL_REGEX_EXP_MATCH, - [_cel_InstrKind_kIndex] = &&INSTR_INDEX, - [_cel_InstrKind_kIn] = &&INSTR_IN, - [_cel_InstrKind_kLazyCall] = &&INSTR_LAZY_CALL, - [_cel_InstrKind_kLazyReturn] = &&INSTR_LAZY_RETURN, - [_cel_InstrKind_kLazyEnter] = &&INSTR_LAZY_ENTER, - [_cel_InstrKind_kLazyLeave] = &&INSTR_LAZY_LEAVE, - [_cel_InstrKind_kExit] = &&INSTR_EXIT, - }; -#define DISPATCH_INSTR() goto* dispatch_table[instr->kind] -#define NEXT_INSTR() ++instr -#define DISPATCH_NEXT_INSTR() \ - NEXT_INSTR(); \ - DISPATCH_INSTR() - const _cel_Instr* instr = interp->instr_ptr; - DISPATCH_INSTR(); -INSTR_UNREACHABLE: - _cel_Interpretable_Unreachable(interp, &instr->data); -INSTR_NULL_CONST: - _cel_Interpretable_NullConst(interp, &instr->data); - DISPATCH_NEXT_INSTR(); -INSTR_FALSE_CONST: - _cel_Interpretable_FalseConst(interp, &instr->data); - DISPATCH_NEXT_INSTR(); -INSTR_TRUE_CONST: - _cel_Interpretable_TrueConst(interp, &instr->data); - DISPATCH_NEXT_INSTR(); -INSTR_INT_CONST: - _cel_Interpretable_IntConst(interp, &instr->data); - DISPATCH_NEXT_INSTR(); -INSTR_UINT_CONST: - _cel_Interpretable_UintConst(interp, &instr->data); - DISPATCH_NEXT_INSTR(); -INSTR_DOUBLE_CONST: - _cel_Interpretable_DoubleConst(interp, &instr->data); - DISPATCH_NEXT_INSTR(); -INSTR_BYTES_CONST: - _cel_Interpretable_BytesConst(interp, &instr->data); - DISPATCH_NEXT_INSTR(); -INSTR_STRING_CONST: - _cel_Interpretable_StringConst(interp, &instr->data); - DISPATCH_NEXT_INSTR(); -INSTR_DURATION_CONST: - _cel_Interpretable_DurationConst(interp, &instr->data); - DISPATCH_NEXT_INSTR(); -INSTR_TIMESTAMP_CONST: - _cel_Interpretable_TimestampConst(interp, &instr->data); - DISPATCH_NEXT_INSTR(); -INSTR_IDENT: - _cel_Interpretable_Ident(interp, &instr->data); - DISPATCH_NEXT_INSTR(); -INSTR_IDENT_JUMP: - instr = _cel_Interpretable_IdentJump(interp, &instr->data); - DISPATCH_INSTR(); -INSTR_CONT_IDENT: - _cel_Interpretable_ContIdent(interp, &instr->data); - DISPATCH_NEXT_INSTR(); -INSTR_CONT_IDENT_JUMP: - instr = _cel_Interpretable_ContIdentJump(interp, &instr->data); - DISPATCH_INSTR(); -INSTR_JUMP: - instr = _cel_Interpretable_Jump(interp, &instr->data); - DISPATCH_INSTR(); -INSTR_HAS: - _cel_Interpretable_Has(interp, &instr->data); - DISPATCH_NEXT_INSTR(); -INSTR_MESSAGE_HAS: - _cel_Interpretable_MessageHas(interp, &instr->data); - DISPATCH_NEXT_INSTR(); -INSTR_SELECT: - _cel_Interpretable_Select(interp, &instr->data); - DISPATCH_NEXT_INSTR(); -INSTR_MESSAGE_SELECT: - _cel_Interpretable_MessageSelect(interp, &instr->data); - DISPATCH_NEXT_INSTR(); -INSTR_ADD: - _cel_Interpretable_Add(interp, &instr->data); - DISPATCH_NEXT_INSTR(); -INSTR_SUBTRACT: - _cel_Interpretable_Subtract(interp, &instr->data); - DISPATCH_NEXT_INSTR(); -INSTR_MULTIPLY: - _cel_Interpretable_Multiply(interp, &instr->data); - DISPATCH_NEXT_INSTR(); -INSTR_DIVIDE: - _cel_Interpretable_Divide(interp, &instr->data); - DISPATCH_NEXT_INSTR(); -INSTR_MODULO: - _cel_Interpretable_Modulo(interp, &instr->data); - DISPATCH_NEXT_INSTR(); -INSTR_LOGICAL_NOT: - _cel_Interpretable_LogicalNot(interp, &instr->data); - DISPATCH_NEXT_INSTR(); -INSTR_NEGATE: - _cel_Interpretable_Negate(interp, &instr->data); - DISPATCH_NEXT_INSTR(); -INSTR_LOGICAL_AND: - _cel_Interpretable_LogicalAnd(interp, &instr->data); - DISPATCH_NEXT_INSTR(); -INSTR_LOGICAL_OR: - _cel_Interpretable_LogicalOr(interp, &instr->data); - DISPATCH_NEXT_INSTR(); -INSTR_EQUALS: - _cel_Interpretable_Equals(interp, &instr->data); - DISPATCH_NEXT_INSTR(); -INSTR_NOT_EQUALS: - _cel_Interpretable_NotEquals(interp, &instr->data); - DISPATCH_NEXT_INSTR(); -INSTR_LESS: - _cel_Interpretable_Less(interp, &instr->data); - DISPATCH_NEXT_INSTR(); -INSTR_LESS_EQUALS: - _cel_Interpretable_LessEquals(interp, &instr->data); - DISPATCH_NEXT_INSTR(); -INSTR_GREATER: - _cel_Interpretable_Greater(interp, &instr->data); - DISPATCH_NEXT_INSTR(); -INSTR_GREATER_EQUALS: - _cel_Interpretable_GreaterEquals(interp, &instr->data); - DISPATCH_NEXT_INSTR(); -INSTR_COND_JUMP: - instr = _cel_Interpretable_CondJump(interp, &instr->data); - DISPATCH_INSTR(); -INSTR_TRILEAN_JUMP: - instr = _cel_Interpretable_TrileanJump(interp, &instr->data); - DISPATCH_INSTR(); -INSTR_ERROR_JUMP: - instr = _cel_Interpretable_ErrorJump(interp, &instr->data); - DISPATCH_INSTR(); -INSTR_LIST: - _cel_Interpretable_List(interp, &instr->data); - DISPATCH_NEXT_INSTR(); -INSTR_KEY_JUMP: - instr = _cel_Interpretable_KeyJump(interp, &instr->data); - DISPATCH_INSTR(); -INSTR_MAP: - _cel_Interpretable_Map(interp, &instr->data); - DISPATCH_NEXT_INSTR(); -INSTR_CALL_BOOL: - _cel_Interpretable_CallBool(interp, &instr->data); - DISPATCH_NEXT_INSTR(); -INSTR_CALL_INT: - _cel_Interpretable_CallInt(interp, &instr->data); - DISPATCH_NEXT_INSTR(); -INSTR_CALL_UINT: - _cel_Interpretable_CallUint(interp, &instr->data); - DISPATCH_NEXT_INSTR(); -INSTR_CALL_DOUBLE: - _cel_Interpretable_CallDouble(interp, &instr->data); - DISPATCH_NEXT_INSTR(); -INSTR_CALL_BYTES: - _cel_Interpretable_CallBytes(interp, &instr->data); - DISPATCH_NEXT_INSTR(); -INSTR_CALL_STRING: - _cel_Interpretable_CallString(interp, &instr->data); - DISPATCH_NEXT_INSTR(); -INSTR_CALL_TIMESTAMP: - _cel_Interpretable_CallTimestamp(interp, &instr->data); - DISPATCH_NEXT_INSTR(); -INSTR_CALL_DURATION: - _cel_Interpretable_CallDuration(interp, &instr->data); - DISPATCH_NEXT_INSTR(); -INSTR_CALL_SIZE: - _cel_Interpretable_CallSize(interp, &instr->data); - DISPATCH_NEXT_INSTR(); -INSTR_CALL_CONTAINS_STRING: - _cel_Interpretable_CallContainsString(interp, &instr->data); - DISPATCH_NEXT_INSTR(); -INSTR_CALL_STARTS_WITH_STRING: - _cel_Interpretable_CallStartsWithString(interp, &instr->data); - DISPATCH_NEXT_INSTR(); -INSTR_CALL_ENDS_WITH_STRING: - _cel_Interpretable_CallEndsWithString(interp, &instr->data); - DISPATCH_NEXT_INSTR(); -INSTR_CALL_REGEX_EXP_MATCH: - _cel_Interpretable_CallRegexExpMatch(interp, &instr->data); - DISPATCH_NEXT_INSTR(); -INSTR_INDEX: - _cel_Interpretable_Index(interp, &instr->data); - DISPATCH_NEXT_INSTR(); -INSTR_IN: - _cel_Interpretable_In(interp, &instr->data); - DISPATCH_NEXT_INSTR(); -INSTR_LAZY_CALL: - instr = _cel_Interpretable_LazyCall(interp, &instr->data); - DISPATCH_INSTR(); -INSTR_LAZY_RETURN: - instr = _cel_Interpretable_LazyReturn(interp, &instr->data); - DISPATCH_INSTR(); -INSTR_LAZY_ENTER: - _cel_Interpretable_LazyEnter(interp, &instr->data); - DISPATCH_NEXT_INSTR(); -INSTR_LAZY_LEAVE: - _cel_Interpretable_LazyLeave(interp, &instr->data); - DISPATCH_NEXT_INSTR(); -INSTR_EXIT: - return; -#undef DISPATCH_NEXT_INSTR -#undef NEXT_INSTR -#undef DISPATCH_INSTR -} -#endif - -_CEL_ATTRIBUTE_UNUSED -static inline void _cel_Interpretable_Switch( - _cel_Interpretable* const cel_nonnull interp, - cel_Value* const cel_nonnull result) { - const _cel_Instr* instr = interp->instr_ptr; - while (true) { - CEL_ASSERT_GE(instr, interp->instr_ptr); - CEL_ASSERT_LT(instr, interp->instr_ptr + interp->instr_len); - switch (instr->kind) { - case _cel_InstrKind_kUnreachable: - _cel_Interpretable_Unreachable(interp, &instr->data); - case _cel_InstrKind_kNullConst: - _cel_Interpretable_NullConst(interp, &instr->data); - ++instr; - break; - case _cel_InstrKind_kFalseConst: - _cel_Interpretable_FalseConst(interp, &instr->data); - ++instr; - break; - case _cel_InstrKind_kTrueConst: - _cel_Interpretable_TrueConst(interp, &instr->data); - ++instr; - break; - case _cel_InstrKind_kIntConst: - _cel_Interpretable_IntConst(interp, &instr->data); - ++instr; - break; - case _cel_InstrKind_kUintConst: - _cel_Interpretable_UintConst(interp, &instr->data); - ++instr; - break; - case _cel_InstrKind_kDoubleConst: - _cel_Interpretable_DoubleConst(interp, &instr->data); - ++instr; - break; - case _cel_InstrKind_kBytesConst: - _cel_Interpretable_BytesConst(interp, &instr->data); - ++instr; - break; - case _cel_InstrKind_kStringConst: - _cel_Interpretable_StringConst(interp, &instr->data); - ++instr; - break; - case _cel_InstrKind_kDurationConst: - _cel_Interpretable_DurationConst(interp, &instr->data); - ++instr; - break; - case _cel_InstrKind_kTimestampConst: - _cel_Interpretable_TimestampConst(interp, &instr->data); - ++instr; - break; - case _cel_InstrKind_kIdent: - _cel_Interpretable_Ident(interp, &instr->data); - ++instr; - break; - case _cel_InstrKind_kIdentJump: - instr = _cel_Interpretable_IdentJump(interp, &instr->data); - break; - case _cel_InstrKind_kContIdent: - _cel_Interpretable_ContIdent(interp, &instr->data); - ++instr; - break; - case _cel_InstrKind_kContIdentJump: - instr = _cel_Interpretable_ContIdentJump(interp, &instr->data); - break; - case _cel_InstrKind_kJump: - instr = _cel_Interpretable_Jump(interp, &instr->data); - break; - case _cel_InstrKind_kHas: - _cel_Interpretable_Has(interp, &instr->data); - ++instr; - break; - case _cel_InstrKind_kMessageHas: - _cel_Interpretable_MessageHas(interp, &instr->data); - ++instr; - break; - case _cel_InstrKind_kSelect: - _cel_Interpretable_Select(interp, &instr->data); - ++instr; - break; - case _cel_InstrKind_kMessageSelect: - _cel_Interpretable_MessageSelect(interp, &instr->data); - ++instr; - break; - case _cel_InstrKind_kAdd: - _cel_Interpretable_Add(interp, &instr->data); - ++instr; - break; - case _cel_InstrKind_kSubtract: - _cel_Interpretable_Subtract(interp, &instr->data); - ++instr; - break; - case _cel_InstrKind_kMultiply: - _cel_Interpretable_Multiply(interp, &instr->data); - ++instr; - break; - case _cel_InstrKind_kDivide: - _cel_Interpretable_Divide(interp, &instr->data); - ++instr; - break; - case _cel_InstrKind_kModulo: - _cel_Interpretable_Modulo(interp, &instr->data); - ++instr; - break; - case _cel_InstrKind_kLogicalNot: - _cel_Interpretable_LogicalNot(interp, &instr->data); - ++instr; - break; - case _cel_InstrKind_kNegate: - _cel_Interpretable_Negate(interp, &instr->data); - ++instr; - break; - case _cel_InstrKind_kLogicalAnd: - _cel_Interpretable_LogicalAnd(interp, &instr->data); - ++instr; - break; - case _cel_InstrKind_kLogicalOr: - _cel_Interpretable_LogicalOr(interp, &instr->data); - ++instr; - break; - case _cel_InstrKind_kEquals: - _cel_Interpretable_Equals(interp, &instr->data); - ++instr; - break; - case _cel_InstrKind_kNotEquals: - _cel_Interpretable_NotEquals(interp, &instr->data); - ++instr; - break; - case _cel_InstrKind_kLess: - _cel_Interpretable_Less(interp, &instr->data); - ++instr; - break; - case _cel_InstrKind_kLessEquals: - _cel_Interpretable_LessEquals(interp, &instr->data); - ++instr; - break; - case _cel_InstrKind_kGreater: - _cel_Interpretable_Greater(interp, &instr->data); - ++instr; - break; - case _cel_InstrKind_kGreaterEquals: - _cel_Interpretable_GreaterEquals(interp, &instr->data); - ++instr; - break; - case _cel_InstrKind_kCondJump: - instr = _cel_Interpretable_CondJump(interp, &instr->data); - break; - case _cel_InstrKind_kTrileanJump: - instr = _cel_Interpretable_TrileanJump(interp, &instr->data); - break; - case _cel_InstrKind_kErrorJump: - instr = _cel_Interpretable_ErrorJump(interp, &instr->data); - break; - case _cel_InstrKind_kList: - _cel_Interpretable_List(interp, &instr->data); - ++instr; - break; - case _cel_InstrKind_kKeyJump: - instr = _cel_Interpretable_KeyJump(interp, &instr->data); - break; - case _cel_InstrKind_kMap: - _cel_Interpretable_Map(interp, &instr->data); - ++instr; - break; - case _cel_InstrKind_kCallBool: - _cel_Interpretable_CallBool(interp, &instr->data); - ++instr; - break; - case _cel_InstrKind_kCallInt: - _cel_Interpretable_CallInt(interp, &instr->data); - ++instr; - break; - case _cel_InstrKind_kCallUint: - _cel_Interpretable_CallUint(interp, &instr->data); - ++instr; - break; - case _cel_InstrKind_kCallDouble: - _cel_Interpretable_CallDouble(interp, &instr->data); - ++instr; - break; - case _cel_InstrKind_kCallBytes: - _cel_Interpretable_CallBytes(interp, &instr->data); - ++instr; - break; - case _cel_InstrKind_kCallString: - _cel_Interpretable_CallString(interp, &instr->data); - ++instr; - break; - case _cel_InstrKind_kCallTimestamp: - _cel_Interpretable_CallTimestamp(interp, &instr->data); - ++instr; - break; - case _cel_InstrKind_kCallDuration: - _cel_Interpretable_CallDuration(interp, &instr->data); - ++instr; - break; - case _cel_InstrKind_kCallSize: - _cel_Interpretable_CallSize(interp, &instr->data); - ++instr; - break; - case _cel_InstrKind_kCallContainsString: - _cel_Interpretable_CallContainsString(interp, &instr->data); - ++instr; - break; - case _cel_InstrKind_kCallStartsWithString: - _cel_Interpretable_CallStartsWithString(interp, &instr->data); - ++instr; - break; - case _cel_InstrKind_kCallEndsWithString: - _cel_Interpretable_CallEndsWithString(interp, &instr->data); - ++instr; - break; - case _cel_InstrKind_kCallRegexExpMatch: - _cel_Interpretable_CallRegexExpMatch(interp, &instr->data); - ++instr; - break; - case _cel_InstrKind_kIndex: - _cel_Interpretable_Index(interp, &instr->data); - ++instr; - break; - case _cel_InstrKind_kIn: - _cel_Interpretable_In(interp, &instr->data); - ++instr; - break; - case _cel_InstrKind_kLazyCall: - instr = _cel_Interpretable_LazyCall(interp, &instr->data); - break; - case _cel_InstrKind_kLazyReturn: - instr = _cel_Interpretable_LazyReturn(interp, &instr->data); - break; - case _cel_InstrKind_kLazyEnter: - _cel_Interpretable_LazyEnter(interp, &instr->data); - ++instr; - break; - case _cel_InstrKind_kLazyLeave: - _cel_Interpretable_LazyLeave(interp, &instr->data); - ++instr; - break; - case _cel_InstrKind_kExit: - return; - default: - CEL_UNREACHABLE(); - } - } -} - -void _cel_Interpretable_Initialize( - _cel_Interpretable* cel_nonnull interp, const cel_Program* cel_nonnull prog, - cel_Value* cel_nonnull value_stack_base, size_t value_stack_size, - _cel_InterpretableSlot* cel_nonnull slots, size_t num_slots, - const _cel_Instr * cel_nonnull * cel_nonnull lazy_stack_base, - size_t lazy_stack_size) { - CEL_ASSERT_NOT_NULL(interp); - CEL_ASSERT_NOT_NULL(prog); - CEL_ASSERT_NOT_NULL(value_stack_base); - CEL_ASSERT_GE(value_stack_size, 1); - - memset(interp, 0, sizeof(*interp)); - interp->alloc = prog->rt->alloc; - interp->def_pool = prog->rt->def_pool; - interp->wkts = &prog->rt->wkts; - interp->instr_ptr = _cel_Array_Data(&prog->instrs); - interp->instr_len = _cel_Array_Size(&prog->instrs); - interp->strings_table_ptr = _cel_Array_Data(&prog->strings_table); - interp->strings_table_len = _cel_Array_Size(&prog->strings_table); - interp->candidate_names_ptr = _cel_Array_Data(&prog->candidate_names_table); - interp->candidate_names_len = _cel_Array_Size(&prog->candidate_names_table); - interp->value_stack_base = interp->value_stack_top = value_stack_base; - interp->value_stack_end = value_stack_base + value_stack_size; - interp->context.alloc = interp->alloc; - interp->context.def_pool = interp->def_pool; - interp->context.well_known_types = interp->wkts; - interp->slots = slots; - interp->slots_len = num_slots; - interp->lazy_stack_base = interp->lazy_stack_top = lazy_stack_base; - interp->lazy_stack_end = lazy_stack_base + lazy_stack_size; -} - -CEL_ATTRIBUTE_NOINLINE -bool _cel_Interpretable_Execute( - _cel_Interpretable* const volatile cel_nonnull interp, - cel_Value* const volatile cel_nonnull result) { - CEL_ASSERT_NOT_NULL(interp); - CEL_ASSERT_NOT_NULL(result); - - switch (_cel_setjmp(interp->jmp)) { - case 0: { - // Under GCC and clang, we can use computed gotos. This is faster than the - // switch alternative. On other compilers we fallback to the switch - // implementation. -#if defined(__GNUC__) || defined(__clang__) - _cel_Interpretable_ComputedGoto(interp, result); -#else - _cel_Interpretable_Switch(interp, result); -#endif - CEL_ASSERT(cel_Status_Ok(interp->status)); - CEL_ASSERT(interp->value_stack_top == interp->value_stack_base + 1); - *result = *(--interp->value_stack_top); - return true; - } - case 1: { - CEL_ASSERT_NOT(cel_Status_Ok(interp->status)); - interp->value_stack_top = interp->value_stack_base; - return false; - } - default: - CEL_UNREACHABLE(); - } -} diff --git a/cel-c/src/runtime/interpreter.c b/cel-c/src/runtime/interpreter.c deleted file mode 100644 index a6ec209..0000000 --- a/cel-c/src/runtime/interpreter.c +++ /dev/null @@ -1,2065 +0,0 @@ -// Copyright 2025 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "cel-c/src/runtime/interpreter.h" - -#include -#include -#include - -#include "cel-c/alloc.h" -#include "cel-c/assert.h" -#include "cel-c/ast.h" -#include "cel-c/ast_traverse.h" -#include "cel-c/ast_visitor.h" -#include "cel-c/config.h" -#include "cel-c/constant.h" -#include "cel-c/hash.h" -#include "cel-c/operators.h" -#include "cel-c/ref.h" -#include "cel-c/status.h" -#include "cel-c/string_view.h" -#include "cel-c/type.h" -#include "cel-c/well_known_types.h" -#include "cel-c/src/array.h" -#include "cel-c/src/container.h" -#include "cel-c/src/deque.h" -#include "cel-c/src/flat_hash_map.h" -#include "cel-c/src/runtime/instr.h" -#include "cel-c/src/runtime/program.h" -#include "cel-c/src/runtime/runtime.h" -#include "cel-c/src/setjmp.h" -#include "cel-c/src/string.h" -#include "upb/reflection/def.h" - -typedef struct { - const cel_IdentExpr* cel_nullability_unknown expr; - // Starting PC. - uint32_t start_pc; -} _cel_InterpreterNspaceVarIdent; - -typedef struct { - const cel_SelectExpr* cel_nonnull expr; - // Starting PC. - uint32_t ident_pc; - uint32_t select_pc; -} _cel_InterpreterNspaceVarSelect; - -typedef struct { - _cel_InterpreterNspaceVarIdent ident; - _cel_Array(_cel_InterpreterNspaceVarSelect) selects; - _cel_String name; -} _cel_InterpreterNspaceVar; - -static void _cel_InterpreterNspaceVar_Construct( - _cel_InterpreterNspaceVar* cel_nonnull nspace_var) { - memset(nspace_var, 0, sizeof(*nspace_var)); - _cel_Array_Construct(&nspace_var->selects); - _cel_String_Construct(&nspace_var->name); -} - -static void _cel_InterpreterNspaceVar_Destruct( - _cel_InterpreterNspaceVar* cel_nonnull nspace_var, - cel_Allocator* cel_nonnull alloc) { - _cel_Array_Destruct(&nspace_var->selects, alloc); - _cel_String_Destruct(&nspace_var->name, alloc); -} - -typedef struct { - const cel_BinaryExpr* cel_nonnull node; - uint32_t pc; - bool cond; -} _cel_InterpreterBinaryCond; - -typedef struct { - const cel_TernaryExpr* cel_nonnull node; - uint32_t trilean_jump_pc; - uint32_t jump_pc; -} _cel_InterpreterTernaryCond; - -typedef struct { - // cel_BinaryExpr or cel_TernaryExpr - union { - struct { - const cel_Expr* cel_nonnull node; - }; - _cel_InterpreterBinaryCond binary; - _cel_InterpreterTernaryCond ternary; - }; -} _cel_InterpreterCond; - -typedef struct { - // One for each element of the list. Each is an _cel_ErrorJumpInstr. - _cel_Array(uint32_t) pcs; -} _cel_InterpreterList; - -typedef struct { - // One for each key and value of the map. The key is an _cel_Foo and the value - // is an _cel_ErrorJumpInstr. - _cel_Array(uint32_t) pcs; -} _cel_InterpreterMap; - -typedef struct { - uint32_t current; - uint32_t max; -} _cel_InterpreterValueStackBounds; - -static CEL_INLINE void _cel_InterpreterValueStackBounds_Construct( - _cel_InterpreterValueStackBounds* cel_nonnull bounds) { - bounds->current = 0; - bounds->max = 0; -} - -static CEL_INLINE void _cel_InterpreterValueStackBounds_Add( - _cel_InterpreterValueStackBounds* cel_nonnull bounds, uint32_t n) { - CEL_ASSERT_LE(n, UINT32_MAX - bounds->current); - - bounds->current += n; - - if (bounds->current > bounds->max) { - bounds->max = bounds->current; - } -} - -static CEL_INLINE void _cel_InterpreterValueStackBounds_Subtract( - _cel_InterpreterValueStackBounds* cel_nonnull bounds, uint32_t n) { - CEL_ASSERT_LE(n, bounds->current); - - bounds->current -= n; -} - -static CEL_INLINE void _cel_InterpreterValueStackBounds_Increment( - _cel_InterpreterValueStackBounds* cel_nonnull bounds) { - _cel_InterpreterValueStackBounds_Add(bounds, 1); -} - -static CEL_INLINE void _cel_InterpreterValueStackBounds_Decrement( - _cel_InterpreterValueStackBounds* cel_nonnull bounds) { - _cel_InterpreterValueStackBounds_Subtract(bounds, 1); -} - -typedef struct { - // Name of the bound variable. - cel_StringView name; - // When variable names shadow each other, we need to know the prev slot index - // so we can restore it in _cel_Interpreter::slot_map. - int32_t prev_slot; - // The slot index, also the index into _cel_Interpreter::slots. - uint32_t index; - // PC for the jump we insert before assembling the subexpression. It is filled - // in to jump over the subexpression. - uint32_t guard_pc; - // PC for the first instruction in the subexpression. - uint32_t pc; - // Current value stack size for the initExpr of this comprehension. - _cel_InterpreterValueStackBounds value_stack_bounds; -} _cel_InterpreterSlot; - -typedef struct { - cel_AstVisitor visitor; - - cel_AstTraverser* cel_nonnull traverser; - const cel_Runtime* cel_nonnull rt; - cel_Allocator* cel_nonnull alloc; - const upb_DefPool* cel_nonnull def_pool; - const cel_WellKnownTypes* cel_nonnull wkts; - cel_Status* cel_nonnull status; - - cel_Program* cel_nullable prog; - - // Mapping between strings, bytes, idents and their index in - // `prog->string_pool`. - _cel_FlatHashMap(cel_StringView, uint32_t) string_pool_indices; - - _cel_FlatHashMap(cel_StringView, uint32_t) candidate_names_indices; - - _cel_InterpreterNspaceVar nspace_var; - - _cel_Array(_cel_InterpreterCond) conds; - - _cel_Array(_cel_InterpreterList) lists; - - _cel_Array(_cel_InterpreterMap) maps; - - _cel_Deque(_cel_InterpreterSlot) slots; - _cel_FlatHashMap(cel_StringView, uint32_t) slot_map; - _cel_Array(uint32_t) slot_stack; - - const cel_ComprehensionExpr* cel_nullable root_bind; - - _cel_InterpreterValueStackBounds value_stack_bounds; - _cel_Array(_cel_InterpreterValueStackBounds* cel_nonnull) - value_stack_bounds_stack; - - _cel_jmp_buf jmp; -} _cel_Interpreter; - -CEL_ATTRIBUTE_NODISCARD -static uint32_t _cel_Interpreter_PC(const _cel_Interpreter* cel_nonnull interp, - const _cel_Instr* cel_nonnull instr) { - return (uint32_t)(instr - _cel_Array_Data(&interp->prog->instrs)); -} - -CEL_ATTRIBUTE_NODISCARD -static uint32_t _cel_Interpreter_NextPC( - const _cel_Interpreter* cel_nonnull interp) { - return (uint32_t)_cel_Array_Size(&interp->prog->instrs); -} - -CEL_ATTRIBUTE_NODISCARD -static _cel_Instr* _cel_Interpreter_InstrAt( - const _cel_Interpreter* cel_nonnull interp, uint32_t pc) { - return _cel_Array_MutableData(&interp->prog->instrs) + pc; -} - -CEL_ATTRIBUTE_NODISCARD -static CEL_INLINE _cel_Interpreter* cel_nonnull -_cel_Interpreter_FromAstVisitor(cel_AstVisitor* cel_nonnull visitor) { - return cel_containerof(visitor, _cel_Interpreter, visitor); -} - -CEL_ATTRIBUTE_NODISCARD -static _cel_Instr* cel_nonnull _cel_Interpreter_AppendInstrN( - _cel_Interpreter* cel_nonnull interp, size_t count) { - _cel_Instr* instr = - _cel_Array_Append(&interp->prog->instrs, interp->alloc, count); - if (CEL_UNLIKELY(instr == cel_nullptr)) { - cel_OutOfMemoryStatus(interp->status); - _cel_longjmp(interp->jmp); - } - return instr; -} - -CEL_ATTRIBUTE_NODISCARD -static _cel_Instr* cel_nonnull -_cel_Interpreter_AppendInstr(_cel_Interpreter* cel_nonnull interp) { - return _cel_Interpreter_AppendInstrN(interp, 1); -} - -CEL_ATTRIBUTE_NODISCARD -static _cel_InterpreterCond* cel_nonnull -_cel_Interpreter_PushCond(_cel_Interpreter* cel_nonnull interp) { - _cel_InterpreterCond* cond = _cel_Array_Push(&interp->conds, interp->alloc); - if (CEL_UNLIKELY(cond == cel_nullptr)) { - cel_OutOfMemoryStatus(interp->status); - _cel_longjmp(interp->jmp); - } - return cond; -} - -CEL_ATTRIBUTE_NODISCARD -static _cel_InterpreterCond* cel_nonnull -_cel_Interpreter_TopCond(_cel_Interpreter* cel_nonnull interp) { - if (_cel_Array_Empty(&interp->conds)) { - cel_InternalStatus(interp->status, - cel_StringView_From("cel: cond stack empty")); - _cel_longjmp(interp->jmp); - } - return _cel_Array_MutableBack(&interp->conds); -} - -CEL_ATTRIBUTE_NODISCARD -static _cel_InterpreterCond* cel_nullable -_cel_Interpreter_PeekCond(_cel_Interpreter* cel_nonnull interp) { - if (_cel_Array_Empty(&interp->conds)) { - return cel_nullptr; - } - return _cel_Array_MutableBack(&interp->conds); -} - -static void _cel_Interpreter_PopCond(_cel_Interpreter* cel_nonnull interp) { - if (_cel_Array_Empty(&interp->conds)) { - cel_InternalStatus(interp->status, - cel_StringView_From("cel: cond stack empty")); - _cel_longjmp(interp->jmp); - } - _cel_Array_Pop(&interp->conds); -} - -CEL_ATTRIBUTE_NODISCARD -static _cel_InterpreterList* cel_nonnull -_cel_Interpreter_PushList(_cel_Interpreter* cel_nonnull interp) { - _cel_InterpreterList* list = _cel_Array_Push(&interp->lists, interp->alloc); - if (CEL_UNLIKELY(list == cel_nullptr)) { - cel_OutOfMemoryStatus(interp->status); - _cel_longjmp(interp->jmp); - } - return list; -} - -CEL_ATTRIBUTE_NODISCARD -static _cel_InterpreterList* cel_nonnull -_cel_Interpreter_TopList(_cel_Interpreter* cel_nonnull interp) { - if (_cel_Array_Empty(&interp->lists)) { - cel_InternalStatus(interp->status, - cel_StringView_From("cel: list stack empty")); - _cel_longjmp(interp->jmp); - } - return _cel_Array_MutableBack(&interp->lists); -} - -static void _cel_Interpreter_PopList(_cel_Interpreter* cel_nonnull interp) { - if (_cel_Array_Empty(&interp->lists)) { - cel_InternalStatus(interp->status, - cel_StringView_From("cel: list stack empty")); - _cel_longjmp(interp->jmp); - } - _cel_Array_Pop(&interp->lists); -} - -CEL_ATTRIBUTE_NODISCARD -static _cel_InterpreterMap* cel_nonnull -_cel_Interpreter_PushMap(_cel_Interpreter* cel_nonnull interp) { - _cel_InterpreterMap* list = _cel_Array_Push(&interp->maps, interp->alloc); - if (CEL_UNLIKELY(list == cel_nullptr)) { - cel_OutOfMemoryStatus(interp->status); - _cel_longjmp(interp->jmp); - } - return list; -} - -CEL_ATTRIBUTE_NODISCARD -static _cel_InterpreterMap* cel_nonnull -_cel_Interpreter_TopMap(_cel_Interpreter* cel_nonnull interp) { - if (_cel_Array_Empty(&interp->maps)) { - cel_InternalStatus(interp->status, - cel_StringView_From("cel: map stack empty")); - _cel_longjmp(interp->jmp); - } - return _cel_Array_MutableBack(&interp->maps); -} - -static void _cel_Interpreter_PopMap(_cel_Interpreter* cel_nonnull interp) { - if (_cel_Array_Empty(&interp->maps)) { - cel_InternalStatus(interp->status, - cel_StringView_From("cel: map stack empty")); - _cel_longjmp(interp->jmp); - } - _cel_Array_Pop(&interp->maps); -} - -CEL_ATTRIBUTE_NODISCARD -static _cel_InterpreterSlot* cel_nonnull _cel_Interpreter_NewSlot( - _cel_Interpreter* cel_nonnull interp, cel_StringView name) { - uint32_t slot_index = (uint32_t)_cel_Deque_Size(&interp->slots); - _cel_InterpreterSlot* slot = - _cel_Deque_PushBack(&interp->slots, interp->alloc); - if (CEL_UNLIKELY(slot == cel_nullptr)) { - cel_OutOfMemoryStatus(interp->status); - _cel_longjmp(interp->jmp); - } - slot->index = slot_index; - if (slot_index + 1 > interp->prog->max_slot_size) { - interp->prog->max_slot_size = slot_index + 1; - } - slot->name = name; - slot->pc = 0; - slot->guard_pc = 0; - slot->prev_slot = -1; - _cel_InterpreterValueStackBounds_Construct(&slot->value_stack_bounds); - return slot; -} - -static void _cel_Interpreter_PushSlot(_cel_Interpreter* cel_nonnull interp, - _cel_InterpreterSlot* cel_nonnull slot) { - uint32_t* index = _cel_Array_Push(&interp->slot_stack, interp->alloc); - if (CEL_UNLIKELY(slot == cel_nullptr)) { - cel_OutOfMemoryStatus(interp->status); - _cel_longjmp(interp->jmp); - } - *index = slot->index; -} - -CEL_ATTRIBUTE_NODISCARD -static _cel_InterpreterSlot* cel_nonnull -_cel_Interpreter_TopSlot(_cel_Interpreter* cel_nonnull interp) { - if (_cel_Array_Empty(&interp->slot_stack)) { - cel_InternalStatus(interp->status, - cel_StringView_From("cel: slot stack empty")); - _cel_longjmp(interp->jmp); - } - const uint32_t* index = _cel_Array_Back(&interp->slot_stack); - return _cel_Deque_MutableAt(&interp->slots, *index); -} - -static void _cel_Interpreter_PopSlot(_cel_Interpreter* cel_nonnull interp) { - if (_cel_Array_Empty(&interp->slot_stack)) { - cel_InternalStatus(interp->status, - cel_StringView_From("cel: slot stack empty")); - _cel_longjmp(interp->jmp); - } - _cel_Array_Pop(&interp->slot_stack); -} - -static void _cel_Interpreter_PushValueStackBounds( - _cel_Interpreter* cel_nonnull interp, - _cel_InterpreterValueStackBounds* cel_nonnull bounds) { - _cel_InterpreterValueStackBounds** bounds_ptr = - _cel_Array_Push(&interp->value_stack_bounds_stack, interp->alloc); - if (CEL_UNLIKELY(bounds_ptr == cel_nullptr)) { - cel_OutOfMemoryStatus(interp->status); - _cel_longjmp(interp->jmp); - } - *bounds_ptr = bounds; -} - -CEL_ATTRIBUTE_NODISCARD -static _cel_InterpreterValueStackBounds* cel_nonnull -_cel_Interpreter_TopValueStackBounds(_cel_Interpreter* cel_nonnull interp) { - if (_cel_Array_Empty(&interp->value_stack_bounds_stack)) { - cel_InternalStatus( - interp->status, - cel_StringView_From("cel: value stack bounds stack empty")); - _cel_longjmp(interp->jmp); - } - return *_cel_Array_Back(&interp->value_stack_bounds_stack); -} - -static void _cel_Interpreter_PopValueStackBounds( - _cel_Interpreter* cel_nonnull interp) { - if (_cel_Array_Empty(&interp->value_stack_bounds_stack)) { - cel_InternalStatus( - interp->status, - cel_StringView_From("cel: value stack bounds stack empty")); - _cel_longjmp(interp->jmp); - } - _cel_Array_Pop(&interp->value_stack_bounds_stack); -} - -CEL_ATTRIBUTE_NODISCARD -static uint32_t _cel_Interpreter_DeleteSlots( - _cel_Interpreter* cel_nonnull interp) { - uint32_t size = (uint32_t)_cel_Deque_Size(&interp->slots); - _cel_Deque_Clear(&interp->slots, interp->alloc); - return size; -} - -static void _cel_Interpreter_IncrementValueStackSizeN( - _cel_Interpreter* cel_nonnull interp, uint32_t n) { - _cel_InterpreterValueStackBounds_Add( - _cel_Interpreter_TopValueStackBounds(interp), n); -} - -static void _cel_Interpreter_IncrementValueStackSize( - _cel_Interpreter* cel_nonnull interp) { - _cel_InterpreterValueStackBounds_Increment( - _cel_Interpreter_TopValueStackBounds(interp)); -} - -static void _cel_Interpreter_DecrementValueStackSizeN( - _cel_Interpreter* cel_nonnull interp, uint32_t n) { - _cel_InterpreterValueStackBounds_Subtract( - _cel_Interpreter_TopValueStackBounds(interp), n); -} - -static void _cel_Interpreter_DecrementValueStackSize( - _cel_Interpreter* cel_nonnull interp) { - _cel_InterpreterValueStackBounds_Decrement( - _cel_Interpreter_TopValueStackBounds(interp)); -} - -static void _cel_Interpreter_PreVisitExpr(cel_AstVisitor* cel_nonnull visitor, - const cel_Expr* cel_nonnull expr) { - cel_ExprKind kind = cel_Expr_Kind(expr); - switch (kind) { - case cel_ExprKind_kUnspecified: - CEL_ATTRIBUTE_FALLTHROUGH; - case cel_ExprKind_kIdent: - CEL_ATTRIBUTE_FALLTHROUGH; - case cel_ExprKind_kConst: - CEL_ATTRIBUTE_FALLTHROUGH; - case cel_ExprKind_kSelect: - CEL_ATTRIBUTE_FALLTHROUGH; - case cel_ExprKind_kBinary: - CEL_ATTRIBUTE_FALLTHROUGH; - case cel_ExprKind_kUnary: - CEL_ATTRIBUTE_FALLTHROUGH; - case cel_ExprKind_kTernary: - CEL_ATTRIBUTE_FALLTHROUGH; - case cel_ExprKind_kListElement: - CEL_ATTRIBUTE_FALLTHROUGH; - case cel_ExprKind_kList: - CEL_ATTRIBUTE_FALLTHROUGH; - case cel_ExprKind_kMapEntry: - CEL_ATTRIBUTE_FALLTHROUGH; - case cel_ExprKind_kMap: - CEL_ATTRIBUTE_FALLTHROUGH; - case cel_ExprKind_kCallArg: - CEL_ATTRIBUTE_FALLTHROUGH; - case cel_ExprKind_kCall: - CEL_ATTRIBUTE_FALLTHROUGH; - case cel_ExprKind_kComprehension: - break; - default: - // For now, reject other AST node kinds. - cel_InvalidArgumentStatusF( - _cel_Interpreter_FromAstVisitor(visitor)->status, - "cel: unsupported AST node kind: %d", kind); - _cel_longjmp(_cel_Interpreter_FromAstVisitor(visitor)->jmp); - } -} - -static void _cel_Interpreter_VisitUnspecifiedExpr( - cel_AstVisitor* cel_nonnull visitor, - const cel_UnspecifiedExpr* cel_nonnull expr) { - _cel_Interpreter* interp = _cel_Interpreter_FromAstVisitor(visitor); - // Reject unspecified AST nodes, they are only created when errors occur. - cel_InvalidArgumentStatus( - interp->status, - cel_StringView_From("cel: unexpected unspecified AST node kind")); - _cel_longjmp(interp->jmp); -} - -CEL_ATTRIBUTE_NODISCARD -static cel_StringView _cel_Interpreter_InternedString( - const _cel_Interpreter* cel_nonnull interp, uint32_t index) { - return _cel_String_ToStringView( - _cel_Array_At(&interp->prog->strings_table, index)); -} - -CEL_ATTRIBUTE_NODISCARD -static uint32_t _cel_Interpreter_InternString( - _cel_Interpreter* cel_nonnull interp, cel_StringView string) { - _cel_FlatHashMapNode(interp->string_pool_indices) node = - _cel_FlatHashMap_Find(&interp->string_pool_indices, &string); - if (node == cel_nullptr) { - uint32_t index = (uint32_t)_cel_Array_Size(&interp->prog->strings_table); - _cel_String* string_ptr = - _cel_Array_Push(&interp->prog->strings_table, interp->alloc); - if (CEL_UNLIKELY(string_ptr == cel_nullptr)) { - cel_OutOfMemoryStatus(interp->status); - _cel_longjmp(interp->jmp); - } - _cel_String_Construct(string_ptr); - if (!_cel_String_Assign(string_ptr, interp->alloc, string)) { - cel_OutOfMemoryStatus(interp->status); - _cel_longjmp(interp->jmp); - } - if (!_cel_String_Stabilize(string_ptr, interp->alloc)) { - cel_OutOfMemoryStatus(interp->status); - _cel_longjmp(interp->jmp); - } - string = _cel_String_ToStringView(string_ptr); - _cel_FlatHashMapMutableNode(interp->string_pool_indices) mutable_node; - if (!_cel_FlatHashMap_Insert(&interp->string_pool_indices, interp->alloc, - &string, &mutable_node)) { - cel_OutOfMemoryStatus(interp->status); - _cel_longjmp(interp->jmp); - } - mutable_node->val = index; - return index; - } - return node->val; -} - -static void _cel_Interpreter_ValidateIdentExpr( - _cel_Interpreter* cel_nonnull interp, - const cel_IdentExpr* cel_nonnull expr) { - cel_StringView name = cel_IdentExpr_Name(expr); - if (CEL_UNLIKELY(cel_StringView_Empty(name))) { - cel_InvalidArgumentStatusF( - interp->status, "cel: ident expr AST node is missing name: id=%" PRIi64, - cel_Expr_Id(cel_Expr_UpCast(expr))); - _cel_longjmp(interp->jmp); - } -} - -static void _cel_Interpreter_ValidateSelectExpr( - _cel_Interpreter* cel_nonnull interp, - const cel_SelectExpr* cel_nonnull expr) { - const cel_Expr* operand = cel_SelectExpr_Operand(expr); - if (CEL_UNLIKELY(operand == cel_nullptr)) { - cel_InvalidArgumentStatusF( - interp->status, - "cel: select expr AST node is missing operand: id=%" PRIi64, - cel_Expr_Id(cel_Expr_UpCast(expr))); - _cel_longjmp(interp->jmp); - } - cel_StringView field = cel_SelectExpr_Field(expr); - if (CEL_UNLIKELY(cel_StringView_Empty(field))) { - cel_InvalidArgumentStatusF( - interp->status, - "cel: select expr AST node is missing field: id=%" PRIi64, - cel_Expr_Id(cel_Expr_UpCast(expr))); - _cel_longjmp(interp->jmp); - } -} - -static void _cel_Interpreter_PlanIdent(_cel_Interpreter* cel_nonnull interp, - cel_StringView name, - bool jump_if_found) { - // TODO: fix namespaced identifier lookup - - if (_cel_Container_Empty(&interp->rt->container)) { - int32_t index = _cel_Interpreter_InternString(interp, name); - if (CEL_UNLIKELY(index == -1)) { - cel_OutOfMemoryStatus(interp->status); - _cel_longjmp(interp->jmp); - } - _cel_Instr* instr = _cel_Interpreter_AppendInstr(interp); - if (CEL_UNLIKELY(instr == cel_nullptr)) { - cel_OutOfMemoryStatus(interp->status); - _cel_longjmp(interp->jmp); - } - instr->data.ident.name.indirect = (uint32_t)index; - instr->kind = - jump_if_found ? _cel_InstrKind_kIdentJump : _cel_InstrKind_kIdent; - } else { - _cel_FlatHashMapNode(interp->candidate_names_indices) node = - _cel_FlatHashMap_Find(&interp->candidate_names_indices, &name); - uint32_t candidate_names_index; - if (node == cel_nullptr) { - candidate_names_index = - (uint32_t)_cel_Array_Size(&interp->prog->candidate_names_table); - _cel_CandidateNames* candidate_names = - _cel_Array_Push(&interp->prog->candidate_names_table, interp->alloc); - if (CEL_UNLIKELY(candidate_names == cel_nullptr)) { - cel_OutOfMemoryStatus(interp->status); - _cel_longjmp(interp->jmp); - } - memset(candidate_names, 0, sizeof(*candidate_names)); - candidate_names->size = _cel_Container_Count(&interp->rt->container) + 1; - candidate_names->data = (uint32_t*)cel_Allocator_Malloc( - interp->alloc, sizeof(uint32_t) * candidate_names->size, cel_nullptr); - if (CEL_UNLIKELY(candidate_names->data == cel_nullptr)) { - _cel_Array_Pop(&interp->prog->candidate_names_table); - cel_OutOfMemoryStatus(interp->status); - _cel_longjmp(interp->jmp); - } - _cel_String candidate_name; - _cel_String_Construct(&candidate_name); - _cel_ContainerIterator cont_iter = - _cel_Container_Iterate(&interp->rt->container); - for (size_t i = 0; i < candidate_names->size - 1; ++i) { - _cel_String_Clear(&candidate_name); - CEL_ASSERT(_cel_ContainerIterator_HasNext(&cont_iter)); - cel_StringView prefix = _cel_ContainerIterator_Next(&cont_iter); - _cel_String_Reserve( - &candidate_name, interp->alloc, - cel_StringView_Size(prefix) + 1 + cel_StringView_Size(name)); - if (!_cel_String_Append(&candidate_name, interp->alloc, prefix) || - !_cel_String_PushBack(&candidate_name, interp->alloc, '.') || - !_cel_String_Append(&candidate_name, interp->alloc, name)) { - _cel_String_Destruct(&candidate_name, interp->alloc); - cel_Allocator_FreeSized(interp->alloc, candidate_names->data, - candidate_names->size * sizeof(uint32_t)); - _cel_Array_Pop(&interp->prog->candidate_names_table); - cel_OutOfMemoryStatus(interp->status); - _cel_longjmp(interp->jmp); - } - uint32_t string_index = _cel_Interpreter_InternString( - interp, _cel_String_ToStringView(&candidate_name)); - candidate_names->data[i] = string_index; - } - uint32_t string_index = _cel_Interpreter_InternString(interp, name); - candidate_names->data[candidate_names->size - 1] = string_index; - name = _cel_Interpreter_InternedString(interp, string_index); - _cel_FlatHashMapMutableNode(interp->candidate_names_indices) mutable_node; - if (!_cel_FlatHashMap_Insert(&interp->candidate_names_indices, - interp->alloc, &name, &mutable_node)) { - cel_OutOfMemoryStatus(interp->status); - _cel_longjmp(interp->jmp); - } - mutable_node->val = candidate_names_index; - } else { - candidate_names_index = node->val; - } - _cel_Instr* instr = _cel_Interpreter_AppendInstr(interp); - instr->data.cont_ident.candidate_names = candidate_names_index; - instr->kind = jump_if_found ? _cel_InstrKind_kContIdentJump - : _cel_InstrKind_kContIdent; - } -} - -static void _cel_Interpreter_VisitIdentExpr(cel_AstVisitor* cel_nonnull visitor, - const cel_IdentExpr* cel_nonnull - expr) { - _cel_Interpreter* interp = _cel_Interpreter_FromAstVisitor(visitor); - _cel_Interpreter_ValidateIdentExpr(interp, expr); - cel_StringView name = cel_IdentExpr_Name(expr); - _cel_FlatHashMapNode(interp->slot_map) slot_node; - slot_node = _cel_FlatHashMap_Find(&interp->slot_map, &name); - if (slot_node != cel_nullptr) { - // Identifier belongs to a comprehension. - _cel_Instr* lazy_call = _cel_Interpreter_AppendInstr(interp); - lazy_call->kind = _cel_InstrKind_kLazyCall; - lazy_call->data.lazy_call.slot = slot_node->val; - const _cel_InterpreterSlot* slot = - _cel_Deque_At(&interp->slots, slot_node->val); - lazy_call->data.lazy_call.jump = - (int32_t)slot->pc - (int32_t)_cel_Interpreter_PC(interp, lazy_call); - // Account for the max value stack size of the subexpression in the current - // expression. - _cel_Interpreter_IncrementValueStackSizeN(interp, - slot->value_stack_bounds.max); - _cel_Interpreter_DecrementValueStackSizeN(interp, - slot->value_stack_bounds.max); - } else { - _cel_Interpreter_PlanIdent(interp, name, - /*jump_if_found=*/false); - } - _cel_Interpreter_IncrementValueStackSize(interp); -} - -static void _cel_Interpreter_VisitConstExpr(cel_AstVisitor* cel_nonnull visitor, - const cel_ConstExpr* cel_nonnull - expr) { - _cel_Interpreter* interp = _cel_Interpreter_FromAstVisitor(visitor); - const cel_Constant* value = cel_ConstExpr_Value(expr); - const cel_ConstantKind kind = cel_Constant_Kind(value); - switch (kind) { - case cel_ConstantKind_kNull: { - _cel_Instr* instr = _cel_Interpreter_AppendInstr(interp); - instr->kind = _cel_InstrKind_kNullConst; - } break; - case cel_ConstantKind_kBool: { - _cel_Instr* instr = _cel_Interpreter_AppendInstr(interp); - instr->kind = cel_Constant_GetBool(value) ? _cel_InstrKind_kTrueConst - : _cel_InstrKind_kFalseConst; - } break; - case cel_ConstantKind_kInt: { - _cel_Instr* instr = _cel_Interpreter_AppendInstr(interp); - instr->data.int_const.value = cel_Constant_GetInt(value); - instr->kind = _cel_InstrKind_kIntConst; - } break; - case cel_ConstantKind_kUint: { - _cel_Instr* instr = _cel_Interpreter_AppendInstr(interp); - instr->data.uint_const.value = cel_Constant_GetUint(value); - instr->kind = _cel_InstrKind_kUintConst; - } break; - case cel_ConstantKind_kDouble: { - _cel_Instr* instr = _cel_Interpreter_AppendInstr(interp); - instr->data.double_const.value = cel_Constant_GetDouble(value); - instr->kind = _cel_InstrKind_kDoubleConst; - } break; - case cel_ConstantKind_kBytes: { - uint32_t index = - _cel_Interpreter_InternString(interp, cel_Constant_GetBytes(value)); - _cel_Instr* instr = _cel_Interpreter_AppendInstr(interp); - instr->data.bytes_const.value.indirect = index; - instr->kind = _cel_InstrKind_kBytesConst; - } break; - case cel_ConstantKind_kString: { - uint32_t index = - _cel_Interpreter_InternString(interp, cel_Constant_GetString(value)); - _cel_Instr* instr = _cel_Interpreter_AppendInstr(interp); - instr->data.string_const.value.indirect = index; - instr->kind = _cel_InstrKind_kStringConst; - } break; - case cel_ConstantKind_kDuration: { - _cel_Instr* instr = _cel_Interpreter_AppendInstr(interp); - instr->data.duration_const.value = cel_Constant_GetDuration(value); - instr->kind = _cel_InstrKind_kDurationConst; - } break; - case cel_ConstantKind_kTimestamp: { - _cel_Instr* instr = _cel_Interpreter_AppendInstr(interp); - instr->data.timestamp_const.value = cel_Constant_GetTimestamp(value); - instr->kind = _cel_InstrKind_kTimestampConst; - } break; - default: - cel_InvalidArgumentStatusF( - _cel_Interpreter_FromAstVisitor(visitor)->status, - "cel: const expr AST node has unspecified value: id=%" PRIi64, - cel_Expr_Id(cel_Expr_UpCast(expr))); - _cel_longjmp(interp->jmp); - } - _cel_Interpreter_IncrementValueStackSize(interp); -} - -typedef struct { - const cel_IdentExpr* cel_nullable ident; - size_t select_depth; -} _cel_InterpreterSelectIdentExpr; - -CEL_ATTRIBUTE_NODISCARD -static _cel_InterpreterSelectIdentExpr _cel_Intepreter_GetSelectIdentExpr( - const cel_SelectExpr* cel_nonnull expr) { - _cel_InterpreterSelectIdentExpr result; - result.ident = cel_nullptr; - result.select_depth = 0; - while (true) { - const cel_Expr* operand = cel_SelectExpr_Operand(expr); - if (operand == cel_nullptr) { - result.select_depth = 0; - return result; - } - switch (cel_Expr_Kind(operand)) { - case cel_ExprKind_kIdent: - result.ident = cel_IdentExpr_DownCast(operand); - return result; - case cel_ExprKind_kSelect: - expr = cel_SelectExpr_DownCast(operand); - ++result.select_depth; - break; - default: - result.select_depth = 0; - return result; - } - } -} - -static void _cel_Intepreter_CollectNspaceVarSelects( - _cel_Interpreter* cel_nonnull interp, - const cel_SelectExpr* cel_nonnull expr) { - { - _cel_InterpreterNspaceVarSelect* select = - _cel_Array_Push(&interp->nspace_var.selects, interp->alloc); - if (CEL_UNLIKELY(select == cel_nullptr)) { - cel_OutOfMemoryStatus(interp->status); - _cel_longjmp(interp->jmp); - } - select->expr = expr; - select->ident_pc = 0; - select->select_pc = 0; - } - while (true) { - const cel_Expr* operand = cel_SelectExpr_Operand(expr); - CEL_ASSERT_NOT_NULL(operand); - switch (cel_Expr_Kind(operand)) { - case cel_ExprKind_kIdent: - return; - case cel_ExprKind_kSelect: { - _cel_InterpreterNspaceVarSelect* select = - _cel_Array_Push(&interp->nspace_var.selects, interp->alloc); - if (CEL_UNLIKELY(select == cel_nullptr)) { - cel_OutOfMemoryStatus(interp->status); - _cel_longjmp(interp->jmp); - } - expr = select->expr = cel_SelectExpr_DownCast(operand); - select->ident_pc = 0; - select->select_pc = 0; - break; - } - default: - CEL_UNREACHABLE(); - } - } -} - -CEL_ATTRIBUTE_NODISCARD -static bool _cel_Interpreter_GetNspaceVar(_cel_Interpreter* cel_nonnull interp, - const cel_SelectExpr* cel_nonnull - expr) { - // Check if this is the first select expr in a chain of `foo.bar.baz`, such - // that this is `baz`. - const cel_Expr* parent = cel_Expr_Parent(cel_Expr_UpCast(expr)); - if (parent == cel_nullptr || cel_Expr_Kind(parent) != cel_ExprKind_kSelect) { - _cel_InterpreterSelectIdentExpr select_ident_expr = - _cel_Intepreter_GetSelectIdentExpr(expr); - if (select_ident_expr.ident != cel_nullptr) { - // First select in a chain of select(s) and a single ident. - const cel_Ref* ident_operand_ref = - cel_Expr_Ref(cel_Expr_UpCast(select_ident_expr.ident)); - if (ident_operand_ref == cel_nullptr) { - _cel_Array_Clear(&interp->nspace_var.selects); - interp->nspace_var.ident.expr = select_ident_expr.ident; - interp->nspace_var.ident.start_pc = 0; - _cel_Array_Reserve(&interp->nspace_var.selects, interp->alloc, - select_ident_expr.select_depth + 1); - _cel_Intepreter_CollectNspaceVarSelects(interp, expr); - return true; - } - } - } - return false; -} - -static void _cel_Interpreter_PlanSelectExpr( - _cel_Interpreter* cel_nonnull interp, - const cel_SelectExpr* cel_nonnull expr) { - cel_StringView field_name = cel_SelectExpr_Field(expr); - const cel_Expr* operand = cel_SelectExpr_Operand(expr); - const cel_Type* operand_type = - operand != cel_nullptr ? cel_Expr_Type(operand) : cel_DynType; - const upb_FieldDef* field = cel_nullptr; - if (cel_Type_IsStruct(operand_type)) { - cel_StringView operand_type_name = - cel_StructType_Name(cel_StructType_DownCast(operand_type)); - const upb_MessageDef* operand_message = - upb_DefPool_FindMessageByNameWithSize( - interp->def_pool, cel_StringView_Data(operand_type_name), - cel_StringView_Size(operand_type_name)); - if (operand_message != cel_nullptr) { - field = upb_MessageDef_FindFieldByNameWithSize( - operand_message, cel_StringView_Data(field_name), - cel_StringView_Size(field_name)); - } - if (field != cel_nullptr) { - _cel_Instr* instr = _cel_Interpreter_AppendInstr(interp); - if (cel_SelectExpr_TestOnly(expr)) { - instr->kind = _cel_InstrKind_kMessageHas; - instr->data.message_has.field = field; - } else { - instr->kind = _cel_InstrKind_kMessageSelect; - instr->data.message_select.field = field; - } - return; - } - } - uint32_t string_index = _cel_Interpreter_InternString(interp, field_name); - _cel_Instr* instr = _cel_Interpreter_AppendInstr(interp); - if (cel_SelectExpr_TestOnly(expr)) { - instr->kind = _cel_InstrKind_kHas; - instr->data.has.field.indirect = (uint32_t)string_index; - } else { - instr->kind = _cel_InstrKind_kSelect; - instr->data.select.field.indirect = (uint32_t)string_index; - } -} - -static void _cel_Interpreter_SetIdentJump(_cel_Instr* ident_jump, - bool missing_error, - int32_t found_jump, - int32_t missing_jump) { - CEL_ASSERT_NE(found_jump, 0); - CEL_ASSERT_NE(missing_jump, 0); - - switch (ident_jump->kind) { - case _cel_InstrKind_kIdentJump: - ident_jump->data.ident_jump.missing_error = missing_error ? 1 : 0; - ident_jump->data.ident_jump.found_jump = found_jump; - ident_jump->data.ident_jump.missing_jump = missing_jump; - break; - case _cel_InstrKind_kContIdentJump: - ident_jump->data.cont_ident_jump.missing_error = missing_error ? 1 : 0; - ident_jump->data.cont_ident_jump.found_jump = found_jump; - ident_jump->data.cont_ident_jump.missing_jump = missing_jump; - break; - default: - CEL_UNREACHABLE(); - } -} - -static void _cel_Interpreter_BuildIdentName(_cel_Interpreter* interp, - size_t selects_num, - size_t selects_count) { - CEL_ASSERT_GE(selects_count, selects_num); - - _cel_InterpreterNspaceVarSelect* const selects = - _cel_Array_MutableData(&interp->nspace_var.selects); - _cel_String_Clear(&interp->nspace_var.name); - if (!_cel_String_Append(&interp->nspace_var.name, interp->alloc, - cel_IdentExpr_Name(interp->nspace_var.ident.expr))) { - cel_OutOfMemoryStatus(interp->status); - _cel_longjmp(interp->jmp); - } - for (size_t i = 0; i < selects_num; ++i) { - if (!_cel_String_PushBack(&interp->nspace_var.name, interp->alloc, '.') || - !_cel_String_Append( - &interp->nspace_var.name, interp->alloc, - cel_SelectExpr_Field(selects[selects_count - i - 1].expr))) { - cel_OutOfMemoryStatus(interp->status); - _cel_longjmp(interp->jmp); - } - } -} - -static void _cel_Interpreter_PreVisitSelectExpr( - cel_AstVisitor* cel_nonnull visitor, - const cel_SelectExpr* cel_nonnull expr) { - _cel_Interpreter* interp = _cel_Interpreter_FromAstVisitor(visitor); - if (_cel_Interpreter_GetNspaceVar(interp, expr)) { - // If we are dealing with namespaced variables, only under parse-only - // expressions, detect that here. If that is the case, we skip traversing - // further down the subtree and handle it all here. - _cel_InterpreterNspaceVarSelect* const selects = - _cel_Array_MutableData(&interp->nspace_var.selects); - const size_t selects_count = _cel_Array_Size(&interp->nspace_var.selects); - CEL_ASSERT_GT(selects_count, 0); - { - _cel_Interpreter_ValidateIdentExpr(interp, interp->nspace_var.ident.expr); - for (size_t i = selects_count; i > 0; --i) { - _cel_Interpreter_ValidateSelectExpr(interp, selects[i - 1].expr); - } - } - - // Idents. - for (size_t i = selects_count; i > 0; --i) { - _cel_Interpreter_BuildIdentName(interp, i, selects_count); - selects[i - 1].ident_pc = _cel_Interpreter_NextPC(interp); - _cel_Interpreter_PlanIdent( - interp, _cel_String_ToStringView(&interp->nspace_var.name), - /*jump_if_found=*/true); - } - _cel_Interpreter_BuildIdentName(interp, 0, selects_count); - interp->nspace_var.ident.start_pc = _cel_Interpreter_NextPC(interp); - _cel_Interpreter_PlanIdent( - interp, _cel_String_ToStringView(&interp->nspace_var.name), - /*jump_if_found=*/true); - - // Selects. - const uint32_t first_select_pc = _cel_Interpreter_NextPC(interp); - for (size_t i = selects_count; i > 0; --i) { - selects[i - 1].select_pc = _cel_Interpreter_NextPC(interp); - _cel_Interpreter_PlanSelectExpr(interp, selects[i - 1].expr); - } - - // Jumps. - const uint32_t last_pc = _cel_Interpreter_NextPC(interp); - uint32_t select_pc; - uint32_t ident_pc = selects[selects_count - 1].ident_pc; - _cel_Instr* ident_jump = _cel_Interpreter_InstrAt(interp, ident_pc); - _cel_Interpreter_SetIdentJump(ident_jump, /*missing_error=*/false, - last_pc - ident_pc, 1); - for (size_t i = selects_count - 1; i > 0; --i) { - ident_pc = selects[i - 1].ident_pc; - ident_jump = _cel_Interpreter_InstrAt(interp, ident_pc); - select_pc = selects[selects_count - 1 - i].select_pc; - _cel_Interpreter_SetIdentJump(ident_jump, /*missing_error=*/false, - select_pc - ident_pc, 1); - } - ident_pc = interp->nspace_var.ident.start_pc; - ident_jump = _cel_Interpreter_InstrAt(interp, ident_pc); - _cel_Interpreter_SetIdentJump(ident_jump, /*missing_error=*/true, - first_select_pc - ident_pc, - last_pc - ident_pc); - - _cel_Interpreter_IncrementValueStackSize(interp); - cel_AstTraverser_StepOut(interp->traverser); - } else { - _cel_Interpreter_ValidateSelectExpr(interp, expr); - } -} - -static void _cel_Interpreter_PostVisitSelectExpr( - cel_AstVisitor* cel_nonnull visitor, - const cel_SelectExpr* cel_nonnull expr) { - _cel_Interpreter* interp = _cel_Interpreter_FromAstVisitor(visitor); - _cel_Interpreter_PlanSelectExpr(interp, expr); -} - -static void _cel_Interpreter_PreVisitBinaryExpr( - cel_AstVisitor* cel_nonnull visitor, - const cel_BinaryExpr* cel_nonnull expr) { - _cel_Interpreter* interp = _cel_Interpreter_FromAstVisitor(visitor); - switch (cel_BinaryExpr_Op(expr)) { - case cel_BinaryOp_kAdd: - CEL_ATTRIBUTE_FALLTHROUGH; - case cel_BinaryOp_kSubtract: - CEL_ATTRIBUTE_FALLTHROUGH; - case cel_BinaryOp_kMultiply: - CEL_ATTRIBUTE_FALLTHROUGH; - case cel_BinaryOp_kDivide: - CEL_ATTRIBUTE_FALLTHROUGH; - case cel_BinaryOp_kModulo: - break; - case cel_BinaryOp_kLogicalAnd: { - _cel_InterpreterCond* cond = _cel_Interpreter_PushCond(interp); - cond->binary.node = expr; - // pc is filled in _cel_Interpreter_PostVisitBinaryExprLeft. - cond->binary.pc = 0; - cond->binary.cond = false; - } break; - case cel_BinaryOp_kLogicalOr: { - _cel_InterpreterCond* cond = _cel_Interpreter_PushCond(interp); - cond->binary.node = expr; - // pc is filled in _cel_Interpreter_PostVisitBinaryExprLeft. - cond->binary.pc = 0; - cond->binary.cond = true; - } break; - case cel_BinaryOp_kEquals: - CEL_ATTRIBUTE_FALLTHROUGH; - case cel_BinaryOp_kNotEquals: - CEL_ATTRIBUTE_FALLTHROUGH; - case cel_BinaryOp_kLess: - CEL_ATTRIBUTE_FALLTHROUGH; - case cel_BinaryOp_kLessEquals: - CEL_ATTRIBUTE_FALLTHROUGH; - case cel_BinaryOp_kGreater: - CEL_ATTRIBUTE_FALLTHROUGH; - case cel_BinaryOp_kGreaterEquals: - CEL_ATTRIBUTE_FALLTHROUGH; - case cel_BinaryOp_kIndex: - CEL_ATTRIBUTE_FALLTHROUGH; - case cel_BinaryOp_kIn: - break; - default: - // For now, reject other AST node kinds. - cel_InvalidArgumentStatusF(interp->status, - "cel: unsupported binary expr operator: %d", - cel_BinaryExpr_Op(expr)); - _cel_longjmp(interp->jmp); - } - if (cel_BinaryExpr_Left(expr) == cel_nullptr) { - cel_InvalidArgumentStatusF( - interp->status, "cel: binary expr missing left operand: %" PRId64, - cel_Expr_Id(cel_Expr_UpCast(expr))); - _cel_longjmp(interp->jmp); - } - if (cel_BinaryExpr_Right(expr) == cel_nullptr) { - cel_InvalidArgumentStatusF( - interp->status, "cel: binary expr missing right operand: %" PRId64, - cel_Expr_Id(cel_Expr_UpCast(expr))); - _cel_longjmp(interp->jmp); - } -} - -static void _cel_Interpreter_PostVisitBinaryExpr( - cel_AstVisitor* cel_nonnull visitor, - const cel_BinaryExpr* cel_nonnull expr) { - _cel_Interpreter* interp = _cel_Interpreter_FromAstVisitor(visitor); - _cel_Instr* instr = _cel_Interpreter_AppendInstr(interp); - switch (cel_BinaryExpr_Op(expr)) { - case cel_BinaryOp_kAdd: - instr->kind = _cel_InstrKind_kAdd; - break; - case cel_BinaryOp_kSubtract: - instr->kind = _cel_InstrKind_kSubtract; - break; - case cel_BinaryOp_kMultiply: - instr->kind = _cel_InstrKind_kMultiply; - break; - case cel_BinaryOp_kDivide: - instr->kind = _cel_InstrKind_kDivide; - break; - case cel_BinaryOp_kModulo: - instr->kind = _cel_InstrKind_kModulo; - break; - case cel_BinaryOp_kLogicalAnd: { - instr->kind = _cel_InstrKind_kLogicalAnd; - _cel_InterpreterCond* cond = _cel_Interpreter_TopCond(interp); - CEL_ASSERT_EQ(cel_Expr_Kind(cond->node), cel_ExprKind_kBinary); - _cel_InterpreterBinaryCond* binary_cond = &cond->binary; - CEL_ASSERT_GT(binary_cond->pc, 0); - _cel_Instr* jump_instr = - _cel_Interpreter_InstrAt(interp, binary_cond->pc); - CEL_ASSERT_EQ(jump_instr->kind, _cel_InstrKind_kCondJump); - jump_instr->data.cond_jump.jump = (int32_t)((instr - jump_instr) + 1); - _cel_Interpreter_PopCond(interp); - } break; - case cel_BinaryOp_kLogicalOr: { - instr->kind = _cel_InstrKind_kLogicalOr; - _cel_InterpreterCond* cond = _cel_Interpreter_TopCond(interp); - CEL_ASSERT_EQ(cel_Expr_Kind(cond->node), cel_ExprKind_kBinary); - _cel_InterpreterBinaryCond* binary_cond = &cond->binary; - CEL_ASSERT_GT(binary_cond->pc, 0); - _cel_Instr* jump_instr = - _cel_Interpreter_InstrAt(interp, binary_cond->pc); - CEL_ASSERT_EQ(jump_instr->kind, _cel_InstrKind_kCondJump); - jump_instr->data.cond_jump.jump = (int32_t)((instr - jump_instr) + 1); - _cel_Interpreter_PopCond(interp); - } break; - case cel_BinaryOp_kEquals: - instr->kind = _cel_InstrKind_kEquals; - break; - case cel_BinaryOp_kNotEquals: - instr->kind = _cel_InstrKind_kNotEquals; - break; - case cel_BinaryOp_kLess: - instr->kind = _cel_InstrKind_kLess; - break; - case cel_BinaryOp_kLessEquals: - instr->kind = _cel_InstrKind_kLessEquals; - break; - case cel_BinaryOp_kGreater: - instr->kind = _cel_InstrKind_kGreater; - break; - case cel_BinaryOp_kGreaterEquals: - instr->kind = _cel_InstrKind_kGreaterEquals; - break; - case cel_BinaryOp_kIndex: - instr->kind = _cel_InstrKind_kIndex; - break; - case cel_BinaryOp_kIn: - instr->kind = _cel_InstrKind_kIn; - break; - default: - CEL_UNREACHABLE(); - } - _cel_Interpreter_DecrementValueStackSize(interp); -} - -static void _cel_Interpreter_PostVisitBinaryExprLeft( - cel_AstVisitor* cel_nonnull visitor, const cel_Expr* cel_nonnull expr) { - _cel_Interpreter* interp = _cel_Interpreter_FromAstVisitor(visitor); - _cel_InterpreterCond* cond = _cel_Interpreter_PeekCond(interp); - if (cond == cel_nullptr || - cel_Expr_Kind(cond->node) != cel_ExprKind_kBinary) { - return; - } - _cel_InterpreterBinaryCond* binary_cond = &cond->binary; - if (cel_Expr_UpCast(binary_cond->node) != cel_Expr_Parent(expr)) { - return; - } - _cel_Instr* cond_jump = _cel_Interpreter_AppendInstr(interp); - cond_jump->kind = _cel_InstrKind_kCondJump; - // jump is filled out in _cel_Interpreter_PostVisitBinaryExpr. - cond_jump->data.cond_jump.jump = 0; - cond_jump->data.cond_jump.cond = binary_cond->cond; - switch (cel_BinaryExpr_Op(cel_BinaryExpr_DownCast(cel_Expr_Parent(expr)))) { - case cel_BinaryOp_kLogicalAnd: - cond_jump->data.cond_jump.cond = false; - break; - case cel_BinaryOp_kLogicalOr: - cond_jump->data.cond_jump.cond = true; - break; - default: - CEL_UNREACHABLE(); - } - binary_cond->pc = _cel_Interpreter_PC(interp, cond_jump); -} - -static void _cel_Interpreter_PostVisitUnaryExpr( - cel_AstVisitor* cel_nonnull visitor, - const cel_UnaryExpr* cel_nonnull expr) { - _cel_Interpreter* interp = _cel_Interpreter_FromAstVisitor(visitor); - _cel_Instr* instr = _cel_Interpreter_AppendInstr(interp); - switch (cel_UnaryExpr_Op(expr)) { - case cel_UnaryOp_kLogicalNot: - instr->kind = _cel_InstrKind_kLogicalNot; - break; - case cel_UnaryOp_kNegate: - instr->kind = _cel_InstrKind_kNegate; - break; - default: - CEL_UNREACHABLE(); - } -} - -static void _cel_Interpreter_PreVisitUnaryExpr( - cel_AstVisitor* cel_nonnull visitor, - const cel_UnaryExpr* cel_nonnull expr) { - _cel_Interpreter* interp = _cel_Interpreter_FromAstVisitor(visitor); - switch (cel_UnaryExpr_Op(expr)) { - case cel_UnaryOp_kLogicalNot: - CEL_ATTRIBUTE_FALLTHROUGH; - case cel_UnaryOp_kNegate: - break; - default: - // For now, reject other AST node kinds. - cel_InvalidArgumentStatusF(interp->status, - "cel: unsupported unary expr operator: %d", - cel_UnaryExpr_Op(expr)); - _cel_longjmp(interp->jmp); - } - if (cel_UnaryExpr_Arg(expr) == cel_nullptr) { - cel_InvalidArgumentStatusF(interp->status, - "cel: unary expr missing operand: %" PRId64, - cel_Expr_Id(cel_Expr_UpCast(expr))); - _cel_longjmp(interp->jmp); - } -} - -static void _cel_Interpreter_PreVisitTernaryExpr( - cel_AstVisitor* cel_nonnull visitor, - const cel_TernaryExpr* cel_nonnull expr) { - _cel_Interpreter* interp = _cel_Interpreter_FromAstVisitor(visitor); - switch (cel_TernaryExpr_Op(expr)) { - case cel_TernaryOp_kConditional: - break; - default: - // For now, reject other AST node kinds. - cel_InvalidArgumentStatusF(interp->status, - "cel: unsupported ternary expr operator: %d", - cel_TernaryExpr_Op(expr)); - _cel_longjmp(interp->jmp); - } - if (cel_TernaryExpr_Condition(expr) == cel_nullptr) { - cel_InvalidArgumentStatusF(interp->status, - "cel: ternary expr missing condition: %" PRId64, - cel_Expr_Id(cel_Expr_UpCast(expr))); - _cel_longjmp(interp->jmp); - } - if (cel_TernaryExpr_IfTrue(expr) == cel_nullptr) { - cel_InvalidArgumentStatusF(interp->status, - "cel: ternary expr missing if-true: %" PRId64, - cel_Expr_Id(cel_Expr_UpCast(expr))); - _cel_longjmp(interp->jmp); - } - if (cel_TernaryExpr_IfFalse(expr) == cel_nullptr) { - cel_InvalidArgumentStatusF(interp->status, - "cel: ternary expr missing if-false: %" PRId64, - cel_Expr_Id(cel_Expr_UpCast(expr))); - _cel_longjmp(interp->jmp); - } - _cel_InterpreterCond* cond = _cel_Interpreter_PushCond(interp); - cond->ternary.node = expr; - // Set in _cel_Interpreter_PostVisitTernaryExprCondition. - cond->ternary.trilean_jump_pc = 0; - // Set in _cel_Interpreter_PostVisitTernaryExprIfTrue. - cond->ternary.jump_pc = 0; -} - -static void _cel_Interpreter_PostVisitTernaryExpr( - cel_AstVisitor* cel_nonnull visitor, - const cel_TernaryExpr* cel_nonnull expr) { - _cel_Interpreter* interp = _cel_Interpreter_FromAstVisitor(visitor); - _cel_InterpreterCond* cond = _cel_Interpreter_TopCond(interp); - CEL_ASSERT_EQ(cel_Expr_Kind(cond->node), cel_ExprKind_kTernary); - _cel_InterpreterTernaryCond* ternary_cond = &cond->ternary; - _cel_Instr* trilean_jump = - _cel_Interpreter_InstrAt(interp, ternary_cond->trilean_jump_pc); - CEL_ASSERT_EQ(trilean_jump->kind, _cel_InstrKind_kTrileanJump); - trilean_jump->data.trilean_jump.error_jump = - _cel_Interpreter_NextPC(interp) - - _cel_Interpreter_PC(interp, trilean_jump); - _cel_Instr* jump = _cel_Interpreter_InstrAt(interp, ternary_cond->jump_pc); - CEL_ASSERT_EQ(jump->kind, _cel_InstrKind_kJump); - jump->data.jump.jump = - _cel_Interpreter_NextPC(interp) - _cel_Interpreter_PC(interp, jump); - _cel_Interpreter_PopCond(interp); -} - -static void _cel_Interpreter_PostVisitTernaryExprCondition( - cel_AstVisitor* cel_nonnull visitor, const cel_Expr* cel_nonnull expr) { - _cel_Interpreter* interp = _cel_Interpreter_FromAstVisitor(visitor); - _cel_InterpreterCond* cond = _cel_Interpreter_TopCond(interp); - CEL_ASSERT_EQ(cel_Expr_Kind(cond->node), cel_ExprKind_kTernary); - _cel_InterpreterTernaryCond* ternary_cond = &cond->ternary; - _cel_Instr* trilean_jump = _cel_Interpreter_AppendInstr(interp); - trilean_jump->kind = _cel_InstrKind_kTrileanJump; - // false_jump is set in _cel_Interpreter_PostVisitTernaryExprIfTrue. - trilean_jump->data.trilean_jump.false_jump = 0; - // error_jump is set in _cel_Interpreter_PostVisitTernaryExpr. - trilean_jump->data.trilean_jump.error_jump = 0; - ternary_cond->trilean_jump_pc = _cel_Interpreter_PC(interp, trilean_jump); - _cel_Interpreter_DecrementValueStackSize(interp); -} - -static void _cel_Interpreter_PostVisitTernaryExprIfTrue( - cel_AstVisitor* cel_nonnull visitor, const cel_Expr* cel_nonnull expr) { - _cel_Interpreter* interp = _cel_Interpreter_FromAstVisitor(visitor); - _cel_InterpreterCond* cond = _cel_Interpreter_TopCond(interp); - CEL_ASSERT_EQ(cel_Expr_Kind(cond->node), cel_ExprKind_kTernary); - _cel_InterpreterTernaryCond* ternary_cond = &cond->ternary; - _cel_Instr* jump = _cel_Interpreter_AppendInstr(interp); - _cel_Instr* trilean_jump = - _cel_Interpreter_InstrAt(interp, ternary_cond->trilean_jump_pc); - CEL_ASSERT_EQ(trilean_jump->kind, _cel_InstrKind_kTrileanJump); - trilean_jump->data.trilean_jump.false_jump = - _cel_Interpreter_NextPC(interp) - - _cel_Interpreter_PC(interp, trilean_jump); - jump->kind = _cel_InstrKind_kJump; - // Set in _cel_Interpreter_PostVisitTernaryExpr. - jump->data.jump.jump = 0; - ternary_cond->jump_pc = _cel_Interpreter_PC(interp, jump); - _cel_Interpreter_DecrementValueStackSize(interp); -} - -static void _cel_Interpreter_PreVisitListExpr( - cel_AstVisitor* cel_nonnull visitor, const cel_ListExpr* cel_nonnull expr) { - _cel_Interpreter* interp = _cel_Interpreter_FromAstVisitor(visitor); - size_t num_elements = cel_ListExpr_Elements(expr, cel_nullptr, cel_nullptr); - if (num_elements > (size_t)INT32_MAX) { - // TODO: allow this to be configurable - cel_InvalidArgumentStatusF(interp->status, - "cel: list expr too large: %" PRId64, - cel_Expr_Id(cel_Expr_UpCast(expr))); - _cel_longjmp(interp->jmp); - } - _cel_InterpreterList* list = _cel_Interpreter_PushList(interp); - _cel_Array_Construct(&list->pcs); - if (!_cel_Array_Reserve(&list->pcs, interp->alloc, num_elements)) { - cel_OutOfMemoryStatus(interp->status); - _cel_longjmp(interp->jmp); - } -} - -static void _cel_Interpreter_PostVisitListExpr( - cel_AstVisitor* cel_nonnull visitor, const cel_ListExpr* cel_nonnull expr) { - _cel_Interpreter* interp = _cel_Interpreter_FromAstVisitor(visitor); - _cel_Instr* instr = _cel_Interpreter_AppendInstr(interp); - instr->kind = _cel_InstrKind_kList; - size_t element_count = cel_ListExpr_Elements(expr, cel_nullptr, cel_nullptr); - instr->data.list.count = (uint32_t)element_count; - _cel_InterpreterList* list = _cel_Interpreter_TopList(interp); - CEL_ASSERT_EQ(_cel_Array_Size(&list->pcs), element_count); - for (size_t i = 0; i < element_count; ++i) { - uint32_t pc = *_cel_Array_At(&list->pcs, i); - _cel_Instr* error_jump = _cel_Interpreter_InstrAt(interp, pc); - CEL_ASSERT_EQ(error_jump->kind, _cel_InstrKind_kErrorJump); - error_jump->data.error_jump.jump = _cel_Interpreter_NextPC(interp) - - _cel_Interpreter_PC(interp, error_jump); - error_jump->data.error_jump.pop = (uint32_t)i; - } - _cel_Array_Destruct(&list->pcs, interp->alloc); - _cel_Interpreter_PopList(interp); - if (element_count > 0) { - _cel_Interpreter_DecrementValueStackSizeN(interp, element_count - 1); - } else { - _cel_Interpreter_IncrementValueStackSize(interp); - } -} - -static void _cel_Interpreter_PreVisitListElementExpr( - cel_AstVisitor* cel_nonnull visitor, - const cel_ListElementExpr* cel_nonnull expr) { - _cel_Interpreter* interp = _cel_Interpreter_FromAstVisitor(visitor); - if (cel_ListElementExpr_Value(expr) == cel_nullptr) { - cel_InvalidArgumentStatusF(interp->status, - "cel: list element expr missing value: %" PRId64, - cel_Expr_Id(cel_Expr_UpCast(expr))); - _cel_longjmp(interp->jmp); - } - if (cel_ListElementExpr_Optional(expr)) { - cel_InvalidArgumentStatusF( - interp->status, - "cel: list element expr optional is not yet implemented: %" PRId64, - cel_Expr_Id(cel_Expr_UpCast(expr))); - _cel_longjmp(interp->jmp); - } -} - -static void _cel_Interpreter_PostVisitListElementExpr( - cel_AstVisitor* cel_nonnull visitor, - const cel_ListElementExpr* cel_nonnull expr) { - _cel_Interpreter* interp = _cel_Interpreter_FromAstVisitor(visitor); - _cel_InterpreterList* list = _cel_Interpreter_TopList(interp); - _cel_Instr* instr = _cel_Interpreter_AppendInstr(interp); - instr->kind = _cel_InstrKind_kErrorJump; - // Set in _cel_Interpreter_PostVisitListExpr. - instr->data.error_jump.jump = 0; - instr->data.error_jump.pop = 0; - uint32_t* pc = _cel_Array_Push(&list->pcs, interp->alloc); - if (pc == cel_nullptr) { - cel_OutOfMemoryStatus(interp->status); - _cel_longjmp(interp->jmp); - } - *pc = _cel_Interpreter_PC(interp, instr); -} - -static void _cel_Interpreter_PreVisitMapExpr( - cel_AstVisitor* cel_nonnull visitor, const cel_MapExpr* cel_nonnull expr) { - _cel_Interpreter* interp = _cel_Interpreter_FromAstVisitor(visitor); - size_t num_entries = cel_MapExpr_Entries(expr, cel_nullptr, cel_nullptr); - if (num_entries > (size_t)INT32_MAX) { - // TODO: allow this to be configurable - cel_InvalidArgumentStatusF(interp->status, - "cel: map expr too large: %" PRId64, - cel_Expr_Id(cel_Expr_UpCast(expr))); - _cel_longjmp(interp->jmp); - } - _cel_InterpreterMap* map = _cel_Interpreter_PushMap(interp); - _cel_Array_Construct(&map->pcs); - if (!_cel_Array_Reserve(&map->pcs, interp->alloc, num_entries * 2)) { - cel_OutOfMemoryStatus(interp->status); - _cel_longjmp(interp->jmp); - } -} - -static void _cel_Interpreter_PostVisitMapExpr( - cel_AstVisitor* cel_nonnull visitor, const cel_MapExpr* cel_nonnull expr) { - _cel_Interpreter* interp = _cel_Interpreter_FromAstVisitor(visitor); - _cel_Instr* instr = _cel_Interpreter_AppendInstr(interp); - instr->kind = _cel_InstrKind_kMap; - size_t entries_count = cel_MapExpr_Entries(expr, cel_nullptr, cel_nullptr); - instr->data.map.count = (uint32_t)entries_count; - _cel_InterpreterMap* map = _cel_Interpreter_TopMap(interp); - CEL_ASSERT_EQ(_cel_Array_Size(&map->pcs), entries_count * 2); - for (size_t i = 0; i < entries_count; ++i) { - uint32_t key_pc = *_cel_Array_At(&map->pcs, i * 2); - uint32_t value_pc = *_cel_Array_At(&map->pcs, i * 2 + 1); - _cel_Instr* key_jump = _cel_Interpreter_InstrAt(interp, key_pc); - CEL_ASSERT_EQ(key_jump->kind, _cel_InstrKind_kKeyJump); - key_jump->data.key_jump.jump = - _cel_Interpreter_NextPC(interp) - _cel_Interpreter_PC(interp, key_jump); - key_jump->data.key_jump.pop = (uint32_t)(i * 2); - _cel_Instr* error_jump = _cel_Interpreter_InstrAt(interp, value_pc); - CEL_ASSERT_EQ(error_jump->kind, _cel_InstrKind_kErrorJump); - error_jump->data.error_jump.jump = _cel_Interpreter_NextPC(interp) - - _cel_Interpreter_PC(interp, error_jump); - error_jump->data.error_jump.pop = (uint32_t)(i * 2 + 1); - } - _cel_Array_Destruct(&map->pcs, interp->alloc); - _cel_Interpreter_PopMap(interp); - if (entries_count > 0) { - _cel_Interpreter_DecrementValueStackSizeN(interp, entries_count * 2 - 1); - } else { - _cel_Interpreter_IncrementValueStackSize(interp); - } -} - -static void _cel_Interpreter_PreVisitMapEntryExpr( - cel_AstVisitor* cel_nonnull visitor, - const cel_MapEntryExpr* cel_nonnull expr) { - _cel_Interpreter* interp = _cel_Interpreter_FromAstVisitor(visitor); - if (cel_MapEntryExpr_Key(expr) == cel_nullptr) { - cel_InvalidArgumentStatusF(interp->status, - "cel: map entry expr missing key: %" PRId64, - cel_Expr_Id(cel_Expr_UpCast(expr))); - _cel_longjmp(interp->jmp); - } - if (cel_MapEntryExpr_Value(expr) == cel_nullptr) { - cel_InvalidArgumentStatusF(interp->status, - "cel: map entry expr missing value: %" PRId64, - cel_Expr_Id(cel_Expr_UpCast(expr))); - _cel_longjmp(interp->jmp); - } - if (cel_MapEntryExpr_Optional(expr)) { - cel_InvalidArgumentStatusF( - interp->status, - "cel: map entry expr optional is not yet implemented: %" PRId64, - cel_Expr_Id(cel_Expr_UpCast(expr))); - _cel_longjmp(interp->jmp); - } -} - -static void _cel_Interpreter_PostVisitMapEntryExprKey( - cel_AstVisitor* cel_nonnull visitor, const cel_Expr* cel_nonnull expr) { - _cel_Interpreter* interp = _cel_Interpreter_FromAstVisitor(visitor); - _cel_InterpreterMap* map = _cel_Interpreter_TopMap(interp); - _cel_Instr* instr = _cel_Interpreter_AppendInstr(interp); - instr->kind = _cel_InstrKind_kKeyJump; - // Set in _cel_Interpreter_PostVisitMapExpr. - instr->data.key_jump.jump = 0; - instr->data.key_jump.pop = 0; - uint32_t* pc = _cel_Array_Push(&map->pcs, interp->alloc); - if (pc == cel_nullptr) { - cel_OutOfMemoryStatus(interp->status); - _cel_longjmp(interp->jmp); - } - *pc = _cel_Interpreter_PC(interp, instr); -} - -static void _cel_Interpreter_PostVisitMapEntryExprValue( - cel_AstVisitor* cel_nonnull visitor, const cel_Expr* cel_nonnull expr) { - _cel_Interpreter* interp = _cel_Interpreter_FromAstVisitor(visitor); - _cel_InterpreterMap* map = _cel_Interpreter_TopMap(interp); - _cel_Instr* instr = _cel_Interpreter_AppendInstr(interp); - instr->kind = _cel_InstrKind_kErrorJump; - // Set in _cel_Interpreter_PostVisitMapExpr. - instr->data.key_jump.jump = 0; - instr->data.key_jump.pop = 0; - uint32_t* pc = _cel_Array_Push(&map->pcs, interp->alloc); - if (pc == cel_nullptr) { - cel_OutOfMemoryStatus(interp->status); - _cel_longjmp(interp->jmp); - } - *pc = _cel_Interpreter_PC(interp, instr); -} - -static void _cel_Interpreter_PreVisitCallArgExpr( - cel_AstVisitor* cel_nonnull visitor, - const cel_CallArgExpr* cel_nonnull expr) { - _cel_Interpreter* interp = _cel_Interpreter_FromAstVisitor(visitor); - if (cel_CallArgExpr_Value(expr) == cel_nullptr) { - cel_InvalidArgumentStatusF(interp->status, - "cel: call arg expr missing value: %" PRId64, - cel_Expr_Id(cel_Expr_UpCast(expr))); - _cel_longjmp(interp->jmp); - } -} - -static void _cel_Interpreter_PostVisitCallExpr( - cel_AstVisitor* cel_nonnull visitor, const cel_CallExpr* cel_nonnull expr) { - _cel_Interpreter* interp = _cel_Interpreter_FromAstVisitor(visitor); - uint32_t index = - _cel_Interpreter_InternString(interp, cel_CallExpr_Function(expr)); - _cel_Instr* instr = _cel_Interpreter_AppendInstr(interp); - instr->data.call.name = index; - instr->data.call.args = cel_CallExpr_Args(expr, cel_nullptr, cel_nullptr) + - (cel_CallExpr_Target(expr) != 0); - cel_StringView fn_name = - _cel_Interpreter_InternedString(interp, instr->data.call.name); - bool found = false; - if (instr->data.call.args == 1) { - if (cel_StringView_Equals(fn_name, cel_StringView_From("int"))) { - instr->kind = _cel_InstrKind_kCallInt; - found = true; - } else if (cel_StringView_Equals(fn_name, cel_StringView_From("uint"))) { - instr->kind = _cel_InstrKind_kCallUint; - found = true; - } else if (cel_StringView_Equals(fn_name, cel_StringView_From("bool"))) { - instr->kind = _cel_InstrKind_kCallBool; - found = true; - } else if (cel_StringView_Equals(fn_name, cel_StringView_From("double"))) { - instr->kind = _cel_InstrKind_kCallDouble; - found = true; - } else if (cel_StringView_Equals(fn_name, cel_StringView_From("bytes"))) { - instr->kind = _cel_InstrKind_kCallBytes; - found = true; - } else if (cel_StringView_Equals(fn_name, cel_StringView_From("string"))) { - instr->kind = _cel_InstrKind_kCallString; - found = true; - } else if (cel_StringView_Equals(fn_name, - cel_StringView_From("timestamp"))) { - instr->kind = _cel_InstrKind_kCallTimestamp; - found = true; - } else if (cel_StringView_Equals(fn_name, - cel_StringView_From("duration"))) { - instr->kind = _cel_InstrKind_kCallDuration; - found = true; - } else if (cel_StringView_Equals(fn_name, cel_StringView_From("size"))) { - instr->kind = _cel_InstrKind_kCallSize; - found = true; - } - } else if (instr->data.call.args == 2) { - if (cel_StringView_Equals(fn_name, cel_StringView_From("contains"))) { - instr->kind = _cel_InstrKind_kCallContainsString; - found = true; - } else if (cel_StringView_Equals(fn_name, - cel_StringView_From("startsWith"))) { - instr->kind = _cel_InstrKind_kCallStartsWithString; - found = true; - } else if (cel_StringView_Equals(fn_name, - cel_StringView_From("endsWith"))) { - instr->kind = _cel_InstrKind_kCallEndsWithString; - found = true; - } else if (cel_StringView_Equals(fn_name, cel_StringView_From("matches"))) { - instr->kind = _cel_InstrKind_kCallRegexExpMatch; - found = true; - } - } - - if (!found) { - cel_InvalidArgumentStatusF(interp->status, - "cel: function with name " CEL_STRINGVIEW_FMT - " taking %d args not found", - CEL_STRINGVIEW_ARGS(fn_name), - instr->data.call.args); - _cel_longjmp(interp->jmp); - } - - if (instr->data.call.args == 0) { - _cel_Interpreter_IncrementValueStackSize(interp); - } else { - for (size_t i = 1; i < instr->data.call.args; ++i) { - _cel_Interpreter_DecrementValueStackSize(interp); - } - } -} - -CEL_ATTRIBUTE_NODISCARD -static bool _cel_Interpreter_IsBind( - const cel_ComprehensionExpr* cel_nonnull expr) { - if (!cel_StringView_Equals(cel_ComprehensionExpr_IterVar(expr), - cel_StringView_From("#unused"))) { - return false; - } - if (!cel_StringView_Empty(cel_ComprehensionExpr_IterVar2(expr))) { - return false; - } - cel_StringView accu_var = cel_ComprehensionExpr_AccuVar(expr); - if (cel_StringView_Empty(accu_var)) { - return false; - } - const cel_Expr* iter_range = cel_ComprehensionExpr_IterRange(expr); - if (iter_range == cel_nullptr || - cel_Expr_Kind(iter_range) != cel_ExprKind_kList) { - return false; - } - const cel_Expr* loop_condition = cel_ComprehensionExpr_LoopCondition(expr); - if (loop_condition == cel_nullptr || - cel_Expr_Kind(loop_condition) != cel_ExprKind_kConst) { - return false; - } - const cel_Constant* loop_condition_constant = - cel_ConstExpr_Value(cel_ConstExpr_DownCast(loop_condition)); - if (cel_Constant_Kind(loop_condition_constant) != cel_ConstantKind_kBool || - cel_Constant_GetBool(loop_condition_constant)) { - return false; - } - const cel_Expr* loop_step = cel_ComprehensionExpr_LoopStep(expr); - if (loop_step == cel_nullptr || - cel_Expr_Kind(loop_step) != cel_ExprKind_kIdent || - !cel_StringView_Equals( - cel_IdentExpr_Name(cel_IdentExpr_DownCast(loop_step)), accu_var)) { - return false; - } - return true; -} - -static void _cel_Interpreter_PreVisitComprehensionExpr( - cel_AstVisitor* cel_nonnull visitor, - const cel_ComprehensionExpr* cel_nonnull expr) { - _cel_Interpreter* interp = _cel_Interpreter_FromAstVisitor(visitor); - if (cel_StringView_Empty(cel_ComprehensionExpr_IterVar(expr))) { - cel_InvalidArgumentStatusF( - interp->status, "cel: comprehension expr missing iter var: %" PRId64, - cel_Expr_Id(cel_Expr_UpCast(expr))); - _cel_longjmp(interp->jmp); - } - if (cel_ComprehensionExpr_IterRange(expr) == cel_nullptr) { - cel_InvalidArgumentStatusF( - interp->status, "cel: comprehension expr missing iter range: %" PRId64, - cel_Expr_Id(cel_Expr_UpCast(expr))); - _cel_longjmp(interp->jmp); - } - if (cel_StringView_Empty(cel_ComprehensionExpr_AccuVar(expr))) { - cel_InvalidArgumentStatusF( - interp->status, "cel: comprehension expr missing accu var: %" PRId64, - cel_Expr_Id(cel_Expr_UpCast(expr))); - _cel_longjmp(interp->jmp); - } - if (cel_ComprehensionExpr_AccuInit(expr) == cel_nullptr) { - cel_InvalidArgumentStatusF( - interp->status, "cel: comprehension expr missing iter range: %" PRId64, - cel_Expr_Id(cel_Expr_UpCast(expr))); - _cel_longjmp(interp->jmp); - } - if (cel_ComprehensionExpr_LoopCondition(expr) == cel_nullptr) { - cel_InvalidArgumentStatusF( - interp->status, - "cel: comprehension expr missing loop condition: %" PRId64, - cel_Expr_Id(cel_Expr_UpCast(expr))); - _cel_longjmp(interp->jmp); - } - if (cel_ComprehensionExpr_LoopStep(expr) == cel_nullptr) { - cel_InvalidArgumentStatusF( - interp->status, "cel: comprehension expr missing loop step: %" PRId64, - cel_Expr_Id(cel_Expr_UpCast(expr))); - _cel_longjmp(interp->jmp); - } - if (cel_ComprehensionExpr_Result(expr) == cel_nullptr) { - cel_InvalidArgumentStatusF( - interp->status, "cel: comprehension expr missing result: %" PRId64, - cel_Expr_Id(cel_Expr_UpCast(expr))); - _cel_longjmp(interp->jmp); - } - - // We only support cel.bind comprehensions currently. - if (!_cel_Interpreter_IsBind(expr)) { - cel_InvalidArgumentStatusF( - interp->status, - "cel: comprehension expr does not resemble cel.bind: %" PRId64, - cel_Expr_Id(cel_Expr_UpCast(expr))); - _cel_longjmp(interp->jmp); - } - - // Keep track of the outer most cel.bind. - if (interp->root_bind == cel_nullptr) { - interp->root_bind = expr; - } - - _cel_InterpreterSlot* slot = - _cel_Interpreter_NewSlot(interp, cel_ComprehensionExpr_AccuVar(expr)); - _cel_Interpreter_PushSlot(interp, slot); -} - -static void _cel_Interpreter_PostVisitComprehensionExpr( - cel_AstVisitor* cel_nonnull visitor, - const cel_ComprehensionExpr* cel_nonnull expr) { - _cel_Interpreter* interp = _cel_Interpreter_FromAstVisitor(visitor); - _cel_Interpreter_PopSlot(interp); - if (interp->root_bind == expr) { - _cel_Instr* lazy_enter = _cel_Interpreter_AppendInstr(interp); - lazy_enter->kind = _cel_InstrKind_kLazyLeave; - // At the moment only cel.bind comprehensions are implemented. So we always - // start at slot 0 when clearing. - lazy_enter->data.lazy_leave.slot = 0; - lazy_enter->data.lazy_leave.num_slots = - _cel_Interpreter_DeleteSlots(interp); - interp->root_bind = cel_nullptr; - } -} - -static void _cel_Interpreter_PreVisitComprehensionExprIterRange( - cel_AstVisitor* cel_nonnull visitor, const cel_Expr* cel_nonnull expr) { - _cel_Interpreter* interp = _cel_Interpreter_FromAstVisitor(visitor); - cel_AstTraverser_StepOut(interp->traverser); -} - -static void _cel_Interpreter_PreVisitComprehensionExprAccuInit( - cel_AstVisitor* cel_nonnull visitor, const cel_Expr* cel_nonnull expr) { - _cel_Interpreter* interp = _cel_Interpreter_FromAstVisitor(visitor); - _cel_InterpreterSlot* slot = _cel_Interpreter_TopSlot(interp); - _cel_Instr* instr = _cel_Interpreter_AppendInstr(interp); - instr->kind = _cel_InstrKind_kJump; - instr->data.jump.jump = 0; - slot->guard_pc = _cel_Interpreter_PC(interp, instr); - slot->pc = _cel_Interpreter_NextPC(interp); - _cel_Interpreter_PushValueStackBounds(interp, &slot->value_stack_bounds); -} - -static void _cel_Interpreter_PostVisitComprehensionExprAccuInit( - cel_AstVisitor* cel_nonnull visitor, const cel_Expr* cel_nonnull expr) { - _cel_Interpreter* interp = _cel_Interpreter_FromAstVisitor(visitor); - _cel_InterpreterSlot* slot = _cel_Interpreter_TopSlot(interp); - _cel_Instr* lazy_return = _cel_Interpreter_AppendInstr(interp); - lazy_return->kind = _cel_InstrKind_kLazyReturn; - lazy_return->data.lazy_return.slot = slot->index; - _cel_Instr* jump = _cel_Interpreter_InstrAt(interp, slot->guard_pc); - CEL_ASSERT_EQ(jump->kind, _cel_InstrKind_kJump); - jump->data.jump.jump = _cel_Interpreter_NextPC(interp) - slot->guard_pc; - _cel_Interpreter_PopValueStackBounds(interp); -} - -static void _cel_Interpreter_PreVisitComprehensionExprLoopCondition( - cel_AstVisitor* cel_nonnull visitor, const cel_Expr* cel_nonnull expr) { - _cel_Interpreter* interp = _cel_Interpreter_FromAstVisitor(visitor); - cel_AstTraverser_StepOut(interp->traverser); -} - -static void _cel_Interpreter_PreVisitComprehensionExprLoopStep( - cel_AstVisitor* cel_nonnull visitor, const cel_Expr* cel_nonnull expr) { - _cel_Interpreter* interp = _cel_Interpreter_FromAstVisitor(visitor); - cel_AstTraverser_StepOut(interp->traverser); -} - -static void _cel_Interpreter_PreVisitComprehensionExprResult( - cel_AstVisitor* cel_nonnull visitor, const cel_Expr* cel_nonnull expr) { - _cel_Interpreter* interp = _cel_Interpreter_FromAstVisitor(visitor); - _cel_InterpreterSlot* slot = _cel_Interpreter_TopSlot(interp); - _cel_FlatHashMapNode(interp->slot_map) prev_slot; - prev_slot = _cel_FlatHashMap_Find(&interp->slot_map, &slot->name); - if (prev_slot != cel_nullptr) { - slot->prev_slot = (int32_t)prev_slot->val; - } - _cel_FlatHashMapMutableNode(interp->slot_map) slot_node; - if (!_cel_FlatHashMap_Insert(&interp->slot_map, interp->alloc, &slot->name, - &slot_node)) { - if (slot_node == cel_nullptr) { - cel_OutOfMemoryStatus(interp->status); - _cel_longjmp(interp->jmp); - } - CEL_ASSERT_NE(slot->prev_slot, -1); - } - slot_node->val = slot->index; -#ifndef NDEBUG - _cel_Instr* lazy_enter = _cel_Interpreter_AppendInstr(interp); - lazy_enter->kind = _cel_InstrKind_kLazyEnter; - lazy_enter->data.lazy_enter.slot = slot->index; -#endif -} - -static void _cel_Interpreter_PostVisitComprehensionExprResult( - cel_AstVisitor* cel_nonnull visitor, const cel_Expr* cel_nonnull expr) { - _cel_Interpreter* interp = _cel_Interpreter_FromAstVisitor(visitor); - _cel_InterpreterSlot* slot = _cel_Interpreter_TopSlot(interp); - _cel_FlatHashMapMutableNode(interp->slot_map) prev_slot; - prev_slot = _cel_FlatHashMap_MutableFind(&interp->slot_map, &slot->name); - CEL_ASSERT_NOT_NULL(prev_slot); - if (slot->prev_slot != -1) { - prev_slot->val = slot->prev_slot; - } else { - _cel_FlatHashMap_Erase(&interp->slot_map, prev_slot); - } -} - -static const cel_AstVisitorVTable _cel_InterpreterVTable = { - .PreVisitExpr = &_cel_Interpreter_PreVisitExpr, - .VisitUnspecifiedExpr = &_cel_Interpreter_VisitUnspecifiedExpr, - .VisitIdentExpr = &_cel_Interpreter_VisitIdentExpr, - .VisitConstExpr = &_cel_Interpreter_VisitConstExpr, - .PreVisitSelectExpr = &_cel_Interpreter_PreVisitSelectExpr, - .PostVisitSelectExpr = &_cel_Interpreter_PostVisitSelectExpr, - .PreVisitBinaryExpr = &_cel_Interpreter_PreVisitBinaryExpr, - .PostVisitBinaryExpr = &_cel_Interpreter_PostVisitBinaryExpr, - .PostVisitBinaryExprLeft = &_cel_Interpreter_PostVisitBinaryExprLeft, - .PreVisitUnaryExpr = &_cel_Interpreter_PreVisitUnaryExpr, - .PostVisitUnaryExpr = &_cel_Interpreter_PostVisitUnaryExpr, - .PreVisitTernaryExpr = &_cel_Interpreter_PreVisitTernaryExpr, - .PostVisitTernaryExpr = &_cel_Interpreter_PostVisitTernaryExpr, - .PostVisitCallExpr = &_cel_Interpreter_PostVisitCallExpr, - .PreVisitCallArgExpr = &_cel_Interpreter_PreVisitCallArgExpr, - .PostVisitTernaryExprCondition = - &_cel_Interpreter_PostVisitTernaryExprCondition, - .PostVisitTernaryExprIfTrue = &_cel_Interpreter_PostVisitTernaryExprIfTrue, - .PreVisitListExpr = &_cel_Interpreter_PreVisitListExpr, - .PostVisitListExpr = &_cel_Interpreter_PostVisitListExpr, - .PreVisitListElementExpr = &_cel_Interpreter_PreVisitListElementExpr, - .PostVisitListElementExpr = &_cel_Interpreter_PostVisitListElementExpr, - .PreVisitMapExpr = &_cel_Interpreter_PreVisitMapExpr, - .PostVisitMapExpr = &_cel_Interpreter_PostVisitMapExpr, - .PreVisitMapEntryExpr = &_cel_Interpreter_PreVisitMapEntryExpr, - .PostVisitMapEntryExprKey = &_cel_Interpreter_PostVisitMapEntryExprKey, - .PostVisitMapEntryExprValue = &_cel_Interpreter_PostVisitMapEntryExprValue, - .PreVisitComprehensionExpr = &_cel_Interpreter_PreVisitComprehensionExpr, - .PostVisitComprehensionExpr = &_cel_Interpreter_PostVisitComprehensionExpr, - .PreVisitComprehensionExprIterRange = - &_cel_Interpreter_PreVisitComprehensionExprIterRange, - .PreVisitComprehensionExprAccuInit = - &_cel_Interpreter_PreVisitComprehensionExprAccuInit, - .PostVisitComprehensionExprAccuInit = - &_cel_Interpreter_PostVisitComprehensionExprAccuInit, - .PreVisitComprehensionExprLoopCondition = - &_cel_Interpreter_PreVisitComprehensionExprLoopCondition, - .PreVisitComprehensionExprLoopStep = - &_cel_Interpreter_PreVisitComprehensionExprLoopStep, - .PreVisitComprehensionExprResult = - &_cel_Interpreter_PreVisitComprehensionExprResult, - .PostVisitComprehensionExprResult = - &_cel_Interpreter_PostVisitComprehensionExprResult, -}; - -static size_t _cel_Interpreter_StringViewHasher(const void* cel_nonnull key) { - return cel_HashState_Finalize(cel_HashState_Combine( - cel_HashState_Initialize(), *(const cel_StringView*)key)); -} - -static bool _cel_Interpreter_StringViewEqualer(const void* cel_nonnull lhs, - const void* cel_nonnull rhs) { - return cel_StringView_Equals(*(const cel_StringView*)lhs, - *(const cel_StringView*)rhs); -} - -static void _cel_Interpreter_Construct(_cel_Interpreter* cel_nonnull interp, - const cel_Runtime* cel_nonnull rt, - cel_Status* cel_nonnull status) { - memset(interp, 0, sizeof(*interp)); - interp->visitor.vtable = &_cel_InterpreterVTable; - interp->rt = _cel_Runtime_ConstRef(rt); - interp->alloc = rt->alloc; - interp->def_pool = rt->def_pool; - interp->wkts = &rt->wkts; - interp->status = status; - interp->root_bind = cel_nullptr; - _cel_FlatHashMap_Construct(&interp->string_pool_indices, - &_cel_Interpreter_StringViewHasher, - &_cel_Interpreter_StringViewEqualer); - _cel_FlatHashMap_Construct(&interp->candidate_names_indices, - &_cel_Interpreter_StringViewHasher, - &_cel_Interpreter_StringViewEqualer); - _cel_InterpreterNspaceVar_Construct(&interp->nspace_var); - _cel_Array_Construct(&interp->conds); - _cel_Array_Construct(&interp->lists); - _cel_Array_Construct(&interp->maps); - _cel_Deque_Construct(&interp->slots); - _cel_FlatHashMap_Construct(&interp->slot_map, - &_cel_Interpreter_StringViewHasher, - &_cel_Interpreter_StringViewEqualer); - _cel_Array_Construct(&interp->slot_stack); - _cel_Array_Construct(&interp->value_stack_bounds_stack); -} - -static void _cel_Interpreter_Destruct(_cel_Interpreter* cel_nonnull interp) { - cel_AstTraverser_Delete(interp->traverser); - _cel_Array_Destruct(&interp->value_stack_bounds_stack, interp->alloc); - _cel_Array_Destruct(&interp->slot_stack, interp->alloc); - _cel_FlatHashMap_Destruct(&interp->slot_map, interp->alloc); - _cel_Deque_Destruct(&interp->slots, interp->alloc); - _cel_Array_Destruct(&interp->conds, interp->alloc); - for (size_t i = 0; i < _cel_Array_Size(&interp->lists); ++i) { - _cel_Array_Destruct(&_cel_Array_MutableAt(&interp->lists, i)->pcs, - interp->alloc); - } - _cel_Array_Destruct(&interp->lists, interp->alloc); - for (size_t i = 0; i < _cel_Array_Size(&interp->maps); ++i) { - _cel_Array_Destruct(&_cel_Array_MutableAt(&interp->maps, i)->pcs, - interp->alloc); - } - _cel_Array_Destruct(&interp->maps, interp->alloc); - _cel_InterpreterNspaceVar_Destruct(&interp->nspace_var, interp->alloc); - _cel_FlatHashMap_Destruct(&interp->candidate_names_indices, interp->alloc); - _cel_FlatHashMap_Destruct(&interp->string_pool_indices, interp->alloc); - // interp->prog is only non-null when planning failed, call cel_Program_Delete - // to avoid hitting a debug assert as we hold the only reference - cel_Program_Delete(interp->prog); - _cel_Runtime_Unref(interp->rt); -} - -static void _cel_Interpreter_DirectInstrs( - _cel_Interpreter* cel_nonnull interp) { - const size_t instr_len = _cel_Array_Size(&interp->prog->instrs); - _cel_Instr* instr_ptr = _cel_Array_MutableData(&interp->prog->instrs); - for (size_t i = 0; i < instr_len; ++instr_ptr, ++i) { - switch (instr_ptr->kind) { - case _cel_InstrKind_kIdent: - instr_ptr->data.ident.name.direct = - _cel_PackedStringView_FromStringView( - _cel_Interpreter_InternedString( - interp, instr_ptr->data.ident.name.indirect)); - break; - case _cel_InstrKind_kBytesConst: - instr_ptr->data.bytes_const.value.direct = - _cel_PackedStringView_FromStringView( - _cel_Interpreter_InternedString( - interp, instr_ptr->data.bytes_const.value.indirect)); - break; - case _cel_InstrKind_kStringConst: - instr_ptr->data.string_const.value.direct = - _cel_PackedStringView_FromStringView( - _cel_Interpreter_InternedString( - interp, instr_ptr->data.string_const.value.indirect)); - break; - case _cel_InstrKind_kHas: - instr_ptr->data.has.field.direct = _cel_PackedStringView_FromStringView( - _cel_Interpreter_InternedString( - interp, instr_ptr->data.has.field.indirect)); - break; - case _cel_InstrKind_kSelect: - instr_ptr->data.select.field.direct = - _cel_PackedStringView_FromStringView( - _cel_Interpreter_InternedString( - interp, instr_ptr->data.select.field.indirect)); - break; - default: - break; - } - } -} - -cel_Program* cel_nullable _cel_Interpreter_Compile( - const cel_Runtime* cel_nonnull rt, const cel_Ast* cel_nonnull ast, - cel_Status* cel_nonnull status) { - CEL_ASSERT_NOT_NULL(rt); - CEL_ASSERT_NOT_NULL(ast); - CEL_ASSERT(cel_Status_Ok(status)); - - if (cel_Ast_Expr(ast) == cel_nullptr) { - cel_InvalidArgumentStatus(status, cel_StringView_From("cel: AST is empty")); - return cel_nullptr; - } - - _cel_Interpreter interp; - _cel_Interpreter* volatile interp_ptr = &interp; - _cel_Interpreter_Construct(&interp, rt, status); - - cel_Program* prog = _cel_Program_New(rt); - if (CEL_UNLIKELY(prog == cel_nullptr)) { - cel_OutOfMemoryStatus(status); - _cel_Interpreter_Destruct(&interp); - return cel_nullptr; - } - interp.prog = prog; - - cel_AstTraverser* traverser = cel_AstTraverser_New(ast, &interp.visitor); - if (CEL_UNLIKELY(traverser == cel_nullptr)) { - cel_OutOfMemoryStatus(status); - _cel_Interpreter_Destruct(&interp); - return cel_nullptr; - } - interp.traverser = traverser; - if (_cel_setjmp(interp_ptr->jmp)) { - CEL_ASSERT_NOT(cel_Status_Ok(interp_ptr->status)); - _cel_Interpreter_Destruct(&interp); - return cel_nullptr; - } - - _cel_Interpreter_PushValueStackBounds(interp_ptr, - &interp_ptr->value_stack_bounds); - - while (cel_AstTraverser_Traverse(traverser, status) && - cel_Status_Ok(status)) { - } - if (cel_Status_Ok(status)) { - prog->max_stack_size = interp.value_stack_bounds.max; - _cel_Instr* instr = _cel_Interpreter_AppendInstr(&interp); - if (CEL_UNLIKELY(instr == cel_nullptr)) { - _cel_Interpreter_Destruct(&interp); - return cel_nullptr; - } - instr->kind = _cel_InstrKind_kExit; - _cel_Array_ShrinkToFit(&prog->instrs, interp.alloc); - _cel_Array_ShrinkToFit(&prog->strings_table, interp.alloc); - _cel_Array_ShrinkToFit(&prog->candidate_names_table, interp.alloc); - // We only needed pointer stability for strings in the string pool with - // _cel_Interpreter. Now that planning is complete, we can forgo pointer - // stability in the name of less memory usage. - _cel_String* string_pool_ptr = _cel_Array_MutableData(&prog->strings_table); - size_t string_pool_len = _cel_Array_Size(&prog->strings_table); - for (; string_pool_len > 0; ++string_pool_ptr, --string_pool_len) { - _cel_String_Destabilize(string_pool_ptr, interp.alloc); - } - // Now that we have destablized strings, we can convert instructions from - // their indirect references to direct. - _cel_Interpreter_DirectInstrs(&interp); - - interp.prog = cel_nullptr; - } else { - prog = cel_nullptr; - } - _cel_Interpreter_Destruct(&interp); - return prog; -} diff --git a/cel-c/src/runtime/program.c b/cel-c/src/runtime/program.c deleted file mode 100644 index 231d878..0000000 --- a/cel-c/src/runtime/program.c +++ /dev/null @@ -1,98 +0,0 @@ -// Copyright 2025 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "cel-c/src/runtime/program.h" - -#include -#include - -#include "cel-c/alloc.h" -#include "cel-c/assert.h" -#include "cel-c/config.h" -#include "cel-c/src/arc.h" -#include "cel-c/src/array.h" -#include "cel-c/src/runtime/activation.h" -#include "cel-c/src/runtime/runtime.h" -#include "cel-c/src/string.h" - -cel_ProgramOptions* cel_nonnull -cel_ProgramOptions_Default(cel_ProgramOptions* cel_nonnull opts) { - CEL_ASSERT_NOT_NULL(opts); - - memset(opts, 0, sizeof(*opts)); - return opts; -} - -void cel_Program_Delete(cel_Program* cel_nullable prog) { - CEL_ASSERT(prog == cel_nullptr || !prog->deleted); - - if (prog != cel_nullptr) { - prog->deleted = true; - _cel_Program_Unref(prog); - } -} - -cel_Activation* cel_nullable -cel_Program_Activate(const cel_Program* cel_nonnull program, - const cel_VariableResolver* cel_nonnull var_resolver, - const cel_ActivationOptions* cel_nullable opts) { - CEL_ASSERT_NOT_NULL(program); - CEL_ASSERT_NOT_NULL(var_resolver); - CEL_USED(opts); - - return _cel_Activation_New(program, var_resolver); -} - -cel_Program* cel_nullable _cel_Program_New(const cel_Runtime* cel_nonnull rt) { - CEL_ASSERT_NOT_NULL(rt); - - cel_Program* prog = (cel_Program*)cel_Allocator_Malloc( - rt->alloc, sizeof(cel_Program), cel_nullptr); - if (CEL_UNLIKELY(prog == cel_nullptr)) { - return cel_nullptr; - } - memset(prog, 0, sizeof(*prog)); - prog->rt = _cel_Runtime_ConstRef(rt); - _cel_AtomicRefCount_Initialize(&prog->rc); - _cel_Array_Construct(&prog->instrs); - _cel_Array_Construct(&prog->strings_table); - _cel_Array_Construct(&prog->candidate_names_table); - return prog; -} - -void _cel_Program_Delete(cel_Program* cel_nonnull prog) { - CEL_ASSERT_NOT_NULL(prog); - CEL_ASSERT(_cel_AtomicRefCount_Expired(&prog->rc)); - CEL_ASSERT(prog->deleted); - - const cel_Runtime* rt = prog->rt; - cel_Allocator* alloc = rt->alloc; - _cel_CandidateNames* candidate_names_ptr = - _cel_Array_MutableData(&prog->candidate_names_table); - size_t candidate_names_len = _cel_Array_Size(&prog->candidate_names_table); - for (; candidate_names_len > 0; - ++candidate_names_ptr, --candidate_names_len) { - _cel_CandidateNames_Destruct(candidate_names_ptr, alloc); - } - _cel_Array_Destruct(&prog->candidate_names_table, alloc); - _cel_String* string_ptr = _cel_Array_MutableData(&prog->strings_table); - size_t string_len = _cel_Array_Size(&prog->strings_table); - for (; string_len > 0; ++string_ptr, --string_len) { - _cel_String_Destruct(string_ptr, alloc); - } - _cel_Array_Destruct(&prog->strings_table, alloc); - _cel_Array_Destruct(&prog->instrs, alloc); - cel_Allocator_FreeSized(alloc, prog, sizeof(*prog)); - _cel_Runtime_Unref(rt); -} diff --git a/cel-c/src/runtime/runtime.c b/cel-c/src/runtime/runtime.c deleted file mode 100644 index d2f6222..0000000 --- a/cel-c/src/runtime/runtime.c +++ /dev/null @@ -1,133 +0,0 @@ -// Copyright 2025 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "cel-c/src/runtime/runtime.h" - -#include - -#include "cel-c/alloc.h" -#include "cel-c/assert.h" -#include "cel-c/ast.h" -#include "cel-c/config.h" -#include "cel-c/program.h" -#include "cel-c/status.h" -#include "cel-c/well_known_types.h" -#include "cel-c/src/arc.h" -#include "cel-c/src/container.h" -#include "cel-c/src/runtime/interpreter.h" -#include "cel-c/src/string.h" -#include "upb/reflection/def.h" - -cel_RuntimeOptions* cel_nonnull -cel_RuntimeOptions_Default(cel_RuntimeOptions* cel_nonnull opts) { - CEL_ASSERT_NOT_NULL(opts); - - memset(opts, 0, sizeof(*opts)); - return opts; -} - -cel_Runtime* cel_nullable cel_Runtime_New( - cel_Allocator* cel_nonnull alloc, const upb_DefPool* cel_nonnull def_pool, - const cel_RuntimeOptions* cel_nullable opts, - cel_Status* cel_nonnull status) { - CEL_ASSERT_NOT_NULL(alloc); - CEL_ASSERT_NOT_NULL(def_pool); - CEL_ASSERT_NOT_NULL(status); - CEL_ASSERT(cel_Status_Ok(status)); - - cel_Runtime* rt = (cel_Runtime*)cel_Allocator_Malloc( - alloc, sizeof(cel_Runtime), cel_nullptr); - if (CEL_UNLIKELY(rt == cel_nullptr)) { - cel_OutOfMemoryStatus(status); - return cel_nullptr; - } - memset(rt, 0, sizeof(*rt)); - if (opts != cel_nullptr) { - rt->opts = *opts; - } else { - opts = cel_RuntimeOptions_Default(&rt->opts); - } - rt->alloc = alloc; - rt->def_pool = def_pool; - if (!cel_WellKnownTypes_Initialize(&rt->wkts, def_pool, status)) { - cel_Allocator_FreeSized(alloc, rt, sizeof(*rt)); - return cel_nullptr; - } - _cel_Container_Construct(&rt->container); - if (!_cel_Container_Update(&rt->container, rt->opts.container, rt->alloc)) { - _cel_Container_Destruct(&rt->container, rt->alloc); - cel_Allocator_FreeSized(alloc, rt, sizeof(*rt)); - return cel_nullptr; - } - rt->opts.container = _cel_String_ToStringView(&rt->container.name); - _cel_AtomicRefCount_Initialize(&rt->rc); - return rt; -} - -void cel_Runtime_Delete(cel_Runtime* cel_nullable rt) { - CEL_ASSERT(rt == cel_nullptr || !rt->deleted); - - if (rt != cel_nullptr) { - rt->deleted = true; - _cel_Runtime_Unref(rt); - } -} - -cel_Allocator* cel_nonnull -cel_Runtime_Allocator(const cel_Runtime* cel_nonnull rt) { - CEL_ASSERT_NOT_NULL(rt); - - return rt->alloc; -} - -const cel_RuntimeOptions* cel_nonnull -cel_Runtime_Options(const cel_Runtime* cel_nonnull rt) { - CEL_ASSERT_NOT_NULL(rt); - - return &rt->opts; -} - -const upb_DefPool* cel_nonnull -cel_Runtime_DefPool(const cel_Runtime* cel_nonnull rt) { - CEL_ASSERT_NOT_NULL(rt); - - return rt->def_pool; -} - -const cel_WellKnownTypes* cel_nonnull -cel_Runtime_WellKnownTypes(const cel_Runtime* cel_nonnull rt) { - CEL_ASSERT_NOT_NULL(rt); - - return &rt->wkts; -} - -cel_Program* cel_nullable cel_Runtime_Compile( - const cel_Runtime* cel_nonnull runtime, const cel_Ast* cel_nonnull ast, - const cel_ProgramOptions* cel_nullable opts, - cel_Status* cel_nonnull status) { - CEL_ASSERT_NOT_NULL(runtime); - CEL_ASSERT_NOT_NULL(ast); - CEL_ASSERT(cel_Status_Ok(status)); - - return _cel_Interpreter_Compile(runtime, ast, status); -} - -void _cel_Runtime_Delete(cel_Runtime* cel_nonnull rt) { - CEL_ASSERT_NOT_NULL(rt); - CEL_ASSERT(_cel_AtomicRefCount_Expired(&rt->rc)); - CEL_ASSERT(rt->deleted); - - _cel_Container_Destruct(&rt->container, rt->alloc); - cel_Allocator_FreeSized(rt->alloc, rt, sizeof(*rt)); -} diff --git a/cel-c/src/struct_value.c b/cel-c/src/struct_value.c deleted file mode 100644 index d62379d..0000000 --- a/cel-c/src/struct_value.c +++ /dev/null @@ -1,248 +0,0 @@ -// Copyright 2025 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include -#include -#include -#include - -#include "cel-c/assert.h" -#include "cel-c/config.h" -#include "cel-c/status.h" -#include "cel-c/string_view.h" -#include "cel-c/value.h" -#include "cel-c/src/array.h" -#include "cel-c/src/sort.h" -#include "upb/reflection/def.h" - -typedef struct { - cel_StringView key; - cel_Value value; -} _cel_StructValueField; - -static int _cel_StructValueField_Compare( - const void* cel_nullability_unknown lhs, - const void* cel_nullability_unknown rhs) { - return cel_StringView_Compare(((const _cel_StructValueField*)lhs)->key, - ((const _cel_StructValueField*)rhs)->key); -} - -static bool _cel_StructValue_EqualsSlow( - const cel_StructValue* cel_nonnull struct_value, - const cel_ValueContext* cel_nonnull context, - const cel_StructValue* cel_nonnull other, cel_Value* cel_nonnull result, - cel_Status* cel_nonnull status) { - cel_StructValueIterator* lhs_iter = - cel_StructValue_NewIterator(struct_value, context, status); - if (CEL_UNLIKELY(lhs_iter == cel_nullptr)) { - CEL_ASSERT(!cel_Status_Ok(status)); - return false; - } - cel_StructValueIterator* rhs_iter = - cel_StructValue_NewIterator(other, context, status); - if (CEL_UNLIKELY(rhs_iter == cel_nullptr)) { - CEL_ASSERT(!cel_Status_Ok(status)); - cel_StructValueIterator_Delete(lhs_iter); - return false; - } - size_t lhs_size; - size_t rhs_size; - bool lhs_has_size; - bool rhs_has_size; - lhs_has_size = cel_StructValueIterator_Remaining(lhs_iter, &lhs_size); - rhs_has_size = cel_StructValueIterator_Remaining(rhs_iter, &rhs_size); - if (lhs_has_size && rhs_has_size) { - if (lhs_size != rhs_size) { - cel_Value_SetFalse(result); - cel_StructValueIterator_Delete(rhs_iter); - cel_StructValueIterator_Delete(lhs_iter); - return true; - } - if (lhs_size == 0) { - cel_Value_SetTrue(result); - cel_StructValueIterator_Delete(rhs_iter); - cel_StructValueIterator_Delete(lhs_iter); - return true; - } - } - _cel_Array(_cel_StructValueField) lhs_fields; - _cel_Array_Construct(&lhs_fields); - if (lhs_has_size) { - _cel_Array_Reserve(&lhs_fields, context->alloc, lhs_size); - } - _cel_Array(_cel_StructValueField) rhs_fields; - _cel_Array_Construct(&rhs_fields); - if (rhs_has_size) { - _cel_Array_Reserve(&rhs_fields, context->alloc, rhs_size); - } - bool ok = true; - bool lhs_next = true; - bool rhs_next = true; - while (true) { - if (lhs_next) { - cel_StructValueKey lhs_field_key; - _cel_StructValueField lhs_field; - lhs_next = cel_StructValueIterator_Next(lhs_iter, context, &lhs_field_key, - &lhs_field.value, status); - if (!lhs_next && !cel_Status_Ok(status)) { - ok = false; - break; - } - if (lhs_next) { - _cel_StructValueField* lhs_field_ptr = - _cel_Array_Push(&lhs_fields, context->alloc); - if (CEL_UNLIKELY(lhs_field_ptr == cel_nullptr)) { - cel_OutOfMemoryStatus(status); - ok = false; - break; - } - lhs_field_ptr->value = lhs_field.value; - switch (cel_StructValueKey_Kind(&lhs_field_key)) { - case cel_StructValueKeyKind_kName: - lhs_field_ptr->key = cel_StructValueKey_GetName(&lhs_field_key); - break; - case cel_StructValueKeyKind_kDef: - lhs_field_ptr->key = cel_StringView_FromString( - upb_FieldDef_Name(cel_StructValueKey_GetDef(&lhs_field_key))); - break; - default: - CEL_UNREACHABLE(); - } - } - } - if (rhs_next) { - cel_StructValueKey rhs_field_key; - _cel_StructValueField rhs_field; - rhs_next = cel_StructValueIterator_Next(rhs_iter, context, &rhs_field_key, - &rhs_field.value, status); - if (!rhs_next && !cel_Status_Ok(status)) { - ok = false; - break; - } - if (rhs_next) { - _cel_StructValueField* rhs_field_ptr = - _cel_Array_Push(&rhs_fields, context->alloc); - if (CEL_UNLIKELY(rhs_field_ptr == cel_nullptr)) { - cel_OutOfMemoryStatus(status); - ok = false; - break; - } - rhs_field_ptr->value = rhs_field.value; - switch (cel_StructValueKey_Kind(&rhs_field_key)) { - case cel_StructValueKeyKind_kName: - rhs_field_ptr->key = cel_StructValueKey_GetName(&rhs_field_key); - break; - case cel_StructValueKeyKind_kDef: - rhs_field_ptr->key = cel_StringView_FromString( - upb_FieldDef_Name(cel_StructValueKey_GetDef(&rhs_field_key))); - break; - default: - CEL_UNREACHABLE(); - } - } - } - if (!lhs_next || !rhs_next) { - break; - } - } - if (ok) { - if (lhs_next || rhs_next) { - cel_Value_SetFalse(result); - } else { - const size_t lhs_fields_size = _cel_Array_Size(&lhs_fields); - const size_t rhs_fields_size = _cel_Array_Size(&rhs_fields); - if (lhs_fields_size != rhs_fields_size) { - cel_Value_SetFalse(result); - } else { - _cel_StructValueField* lhs_fields_data = - _cel_Array_MutableData(&lhs_fields); - _cel_StructValueField* rhs_fields_data = - _cel_Array_MutableData(&rhs_fields); - _cel_Sort(lhs_fields_data, lhs_fields_size, - sizeof(_cel_StructValueField), - &_cel_StructValueField_Compare); - _cel_Sort(rhs_fields_data, rhs_fields_size, - sizeof(_cel_StructValueField), - &_cel_StructValueField_Compare); - for (size_t i = 0; i < lhs_fields_size; ++i) { - if (!cel_StringView_Equals(lhs_fields_data[i].key, - rhs_fields_data[i].key)) { - cel_Value_SetFalse(result); - goto done; - } - if (!cel_Value_Equals(&lhs_fields_data[i].value, context, - &rhs_fields_data[i].value, result, status)) { - ok = false; - goto done; - } - if (!cel_Value_IsTrue(result)) { - goto done; - } - } - cel_Value_SetTrue(result); - } - } - } -done: - _cel_Array_Destruct(&rhs_fields, context->alloc); - _cel_Array_Destruct(&lhs_fields, context->alloc); - cel_StructValueIterator_Delete(rhs_iter); - cel_StructValueIterator_Delete(lhs_iter); - return ok; -} - -bool cel_StructValue_Equals(const cel_StructValue* cel_nonnull struct_value, - const cel_ValueContext* cel_nonnull context, - const cel_StructValue* cel_nonnull other, - cel_Value* cel_nonnull result, - cel_Status* cel_nonnull status) { - CEL_ASSERT_NOT_NULL(struct_value); - CEL_ASSERT_NOT_NULL(context); - CEL_ASSERT_NOT_NULL(other); - CEL_ASSERT_NOT_NULL(result); - CEL_ASSERT_NOT_NULL(status); - - if (CEL_UNLIKELY(!cel_Status_Ok(status))) { - return false; - } - - if (cel_StringView_Equals(cel_StructValue_TypeName(struct_value), - cel_StructValue_TypeName(other))) { - if (struct_value->vtable->Equals != cel_nullptr) { - if ((*struct_value->vtable->Equals)(struct_value->vtable, - struct_value->content, context, other, - result, status)) { - return true; - } - if (CEL_UNLIKELY(!cel_Status_Ok(status))) { - return false; - } - } - if (other->vtable->Equals != cel_nullptr && - other->vtable->Equals != struct_value->vtable->Equals) { - if ((*other->vtable->Equals)(other->vtable, other->content, context, - struct_value, result, status)) { - return true; - } - if (CEL_UNLIKELY(!cel_Status_Ok(status))) { - return false; - } - } - return _cel_StructValue_EqualsSlow(struct_value, context, other, result, - status); - } - - cel_Value_SetFalse(result); - return true; -} diff --git a/cel-c/src/utf8.c b/cel-c/src/utf8.c deleted file mode 100644 index dfa56ab..0000000 --- a/cel-c/src/utf8.c +++ /dev/null @@ -1,228 +0,0 @@ -// Copyright 2025 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "cel-c/src/utf8.h" - -#include // IWYU pragma: keep -#include -#include - -#include "cel-c/assert.h" -#include "cel-c/config.h" -#include "cel-c/src/uchar.h" // IWYU pragma: keep -#include "cel-c/src/unicode.h" -#include "upb/base/string_view.h" - -#define _cel_kUtf8RuneSelf 0x80 - -#define _cel_kUtf8Low 0x80 -#define _cel_kUtf8High 0xbf - -#define _cel_kUtf8MaskX 0x3f -#define _cel_kUtf8Mask2 0x1f -#define _cel_kUtf8Mask3 0xf -#define _cel_kUtf8Mask4 0x7 - -#define _cel_kUtf8TX 0x80 -#define _cel_kUtf8T2 0xc0 -#define _cel_kUtf8T3 0xe0 -#define _cel_kUtf8T4 0xf0 - -#define _cel_kUtf8XX 0xf1 -#define _cel_kUtf8AS 0xf0 -#define _cel_kUtf8S1 0x02 -#define _cel_kUtf8S2 0x13 -#define _cel_kUtf8S3 0x03 -#define _cel_kUtf8S4 0x23 -#define _cel_kUtf8S5 0x34 -#define _cel_kUtf8S6 0x04 -#define _cel_kUtf8S7 0x44 - -// NOLINTBEGIN -// clang-format off -static const uint8_t _cel_kUtf8Leading[256] = { - _cel_kUtf8AS, _cel_kUtf8AS, _cel_kUtf8AS, _cel_kUtf8AS, _cel_kUtf8AS, _cel_kUtf8AS, _cel_kUtf8AS, _cel_kUtf8AS, _cel_kUtf8AS, _cel_kUtf8AS, _cel_kUtf8AS, _cel_kUtf8AS, _cel_kUtf8AS, _cel_kUtf8AS, _cel_kUtf8AS, _cel_kUtf8AS, // 0x00-0x0F - _cel_kUtf8AS, _cel_kUtf8AS, _cel_kUtf8AS, _cel_kUtf8AS, _cel_kUtf8AS, _cel_kUtf8AS, _cel_kUtf8AS, _cel_kUtf8AS, _cel_kUtf8AS, _cel_kUtf8AS, _cel_kUtf8AS, _cel_kUtf8AS, _cel_kUtf8AS, _cel_kUtf8AS, _cel_kUtf8AS, _cel_kUtf8AS, // 0x10-0x1F - _cel_kUtf8AS, _cel_kUtf8AS, _cel_kUtf8AS, _cel_kUtf8AS, _cel_kUtf8AS, _cel_kUtf8AS, _cel_kUtf8AS, _cel_kUtf8AS, _cel_kUtf8AS, _cel_kUtf8AS, _cel_kUtf8AS, _cel_kUtf8AS, _cel_kUtf8AS, _cel_kUtf8AS, _cel_kUtf8AS, _cel_kUtf8AS, // 0x20-0x2F - _cel_kUtf8AS, _cel_kUtf8AS, _cel_kUtf8AS, _cel_kUtf8AS, _cel_kUtf8AS, _cel_kUtf8AS, _cel_kUtf8AS, _cel_kUtf8AS, _cel_kUtf8AS, _cel_kUtf8AS, _cel_kUtf8AS, _cel_kUtf8AS, _cel_kUtf8AS, _cel_kUtf8AS, _cel_kUtf8AS, _cel_kUtf8AS, // 0x30-0x3F - _cel_kUtf8AS, _cel_kUtf8AS, _cel_kUtf8AS, _cel_kUtf8AS, _cel_kUtf8AS, _cel_kUtf8AS, _cel_kUtf8AS, _cel_kUtf8AS, _cel_kUtf8AS, _cel_kUtf8AS, _cel_kUtf8AS, _cel_kUtf8AS, _cel_kUtf8AS, _cel_kUtf8AS, _cel_kUtf8AS, _cel_kUtf8AS, // 0x40-0x4F - _cel_kUtf8AS, _cel_kUtf8AS, _cel_kUtf8AS, _cel_kUtf8AS, _cel_kUtf8AS, _cel_kUtf8AS, _cel_kUtf8AS, _cel_kUtf8AS, _cel_kUtf8AS, _cel_kUtf8AS, _cel_kUtf8AS, _cel_kUtf8AS, _cel_kUtf8AS, _cel_kUtf8AS, _cel_kUtf8AS, _cel_kUtf8AS, // 0x50-0x5F - _cel_kUtf8AS, _cel_kUtf8AS, _cel_kUtf8AS, _cel_kUtf8AS, _cel_kUtf8AS, _cel_kUtf8AS, _cel_kUtf8AS, _cel_kUtf8AS, _cel_kUtf8AS, _cel_kUtf8AS, _cel_kUtf8AS, _cel_kUtf8AS, _cel_kUtf8AS, _cel_kUtf8AS, _cel_kUtf8AS, _cel_kUtf8AS, // 0x60-0x6F - _cel_kUtf8AS, _cel_kUtf8AS, _cel_kUtf8AS, _cel_kUtf8AS, _cel_kUtf8AS, _cel_kUtf8AS, _cel_kUtf8AS, _cel_kUtf8AS, _cel_kUtf8AS, _cel_kUtf8AS, _cel_kUtf8AS, _cel_kUtf8AS, _cel_kUtf8AS, _cel_kUtf8AS, _cel_kUtf8AS, _cel_kUtf8AS, // 0x70-0x7F - _cel_kUtf8XX, _cel_kUtf8XX, _cel_kUtf8XX, _cel_kUtf8XX, _cel_kUtf8XX, _cel_kUtf8XX, _cel_kUtf8XX, _cel_kUtf8XX, _cel_kUtf8XX, _cel_kUtf8XX, _cel_kUtf8XX, _cel_kUtf8XX, _cel_kUtf8XX, _cel_kUtf8XX, _cel_kUtf8XX, _cel_kUtf8XX, // 0x80-0x8F - _cel_kUtf8XX, _cel_kUtf8XX, _cel_kUtf8XX, _cel_kUtf8XX, _cel_kUtf8XX, _cel_kUtf8XX, _cel_kUtf8XX, _cel_kUtf8XX, _cel_kUtf8XX, _cel_kUtf8XX, _cel_kUtf8XX, _cel_kUtf8XX, _cel_kUtf8XX, _cel_kUtf8XX, _cel_kUtf8XX, _cel_kUtf8XX, // 0x90-0x9F - _cel_kUtf8XX, _cel_kUtf8XX, _cel_kUtf8XX, _cel_kUtf8XX, _cel_kUtf8XX, _cel_kUtf8XX, _cel_kUtf8XX, _cel_kUtf8XX, _cel_kUtf8XX, _cel_kUtf8XX, _cel_kUtf8XX, _cel_kUtf8XX, _cel_kUtf8XX, _cel_kUtf8XX, _cel_kUtf8XX, _cel_kUtf8XX, // 0xA0-0xAF - _cel_kUtf8XX, _cel_kUtf8XX, _cel_kUtf8XX, _cel_kUtf8XX, _cel_kUtf8XX, _cel_kUtf8XX, _cel_kUtf8XX, _cel_kUtf8XX, _cel_kUtf8XX, _cel_kUtf8XX, _cel_kUtf8XX, _cel_kUtf8XX, _cel_kUtf8XX, _cel_kUtf8XX, _cel_kUtf8XX, _cel_kUtf8XX, // 0xB0-0xBF - _cel_kUtf8XX, _cel_kUtf8XX, _cel_kUtf8S1, _cel_kUtf8S1, _cel_kUtf8S1, _cel_kUtf8S1, _cel_kUtf8S1, _cel_kUtf8S1, _cel_kUtf8S1, _cel_kUtf8S1, _cel_kUtf8S1, _cel_kUtf8S1, _cel_kUtf8S1, _cel_kUtf8S1, _cel_kUtf8S1, _cel_kUtf8S1, // 0xC0-0xCF - _cel_kUtf8S1, _cel_kUtf8S1, _cel_kUtf8S1, _cel_kUtf8S1, _cel_kUtf8S1, _cel_kUtf8S1, _cel_kUtf8S1, _cel_kUtf8S1, _cel_kUtf8S1, _cel_kUtf8S1, _cel_kUtf8S1, _cel_kUtf8S1, _cel_kUtf8S1, _cel_kUtf8S1, _cel_kUtf8S1, _cel_kUtf8S1, // 0xD0-0xDF - _cel_kUtf8S2, _cel_kUtf8S3, _cel_kUtf8S3, _cel_kUtf8S3, _cel_kUtf8S3, _cel_kUtf8S3, _cel_kUtf8S3, _cel_kUtf8S3, _cel_kUtf8S3, _cel_kUtf8S3, _cel_kUtf8S3, _cel_kUtf8S3, _cel_kUtf8S3, _cel_kUtf8S4, _cel_kUtf8S3, _cel_kUtf8S3, // 0xE0-0xEF - _cel_kUtf8S5, _cel_kUtf8S6, _cel_kUtf8S6, _cel_kUtf8S6, _cel_kUtf8S7, _cel_kUtf8XX, _cel_kUtf8XX, _cel_kUtf8XX, _cel_kUtf8XX, _cel_kUtf8XX, _cel_kUtf8XX, _cel_kUtf8XX, _cel_kUtf8XX, _cel_kUtf8XX, _cel_kUtf8XX, _cel_kUtf8XX, // 0xF0-0xFF -}; -// clang-format on -// NOLINTEND - -static const uint8_t _cel_kUtf8Accept[32] = { - _cel_kUtf8Low, _cel_kUtf8High, - 0xa0, _cel_kUtf8High, - _cel_kUtf8Low, 0x9f, - 0x90, _cel_kUtf8High, - _cel_kUtf8Low, 0x8f, - 0x0, 0x0, - 0x0, 0x0, - 0x0, 0x0, - 0x0, 0x0, - 0x0, 0x0, - 0x0, 0x0, - 0x0, 0x0, - 0x0, 0x0, - 0x0, 0x0, - 0x0, 0x0, - 0x0, 0x0, -}; - -static void _cel_Utf8_DecodeResult(char32_t pnt, size_t units, - CEL_NULLABLE(char32_t*) out_pnt, - CEL_NULLABLE(size_t*) out_units) { - if (out_pnt != cel_nullptr) { - *out_pnt = pnt; - } - if (out_units != cel_nullptr) { - *out_units = units; - } -} - -static void _cel_Utf8_DecodeFailed(CEL_NULLABLE(char32_t*) pnt, - CEL_NULLABLE(size_t*) units) { - _cel_Utf8_DecodeResult(_cel_Unicode_kReplacementChar, 1, pnt, units); -} - -void _cel_Utf8_Decode(upb_StringView str, CEL_NULLABLE(char32_t*) pnt, - CEL_NULLABLE(size_t*) units) { - CEL_ASSERT_NOT_NULL(str.data); - CEL_ASSERT_GT(str.size, 0); - CEL_ASSERT(pnt != cel_nullptr || units != cel_nullptr); - CEL_NONNULL(const char*) data = str.data; - size_t len = str.size; - const uint8_t b = (uint8_t)(*data++); - --len; - if (b < _cel_kUtf8RuneSelf) { - _cel_Utf8_DecodeResult(b, 1, pnt, units); - return; - } - const uint8_t leading = _cel_kUtf8Leading[b]; - if (CEL_UNLIKELY(leading == _cel_kUtf8XX)) { - _cel_Utf8_DecodeFailed(pnt, units); - return; - } - const size_t size = ((size_t)(leading & 7)) - 1; - CEL_ASSERT(size >= 1 && size <= 3); - if (CEL_UNLIKELY(size > len)) { - _cel_Utf8_DecodeFailed(pnt, units); - return; - } - const uint8_t* const accept = &_cel_kUtf8Accept[(leading >> 4) * 2]; - const uint8_t b1 = (uint8_t)(*data++); - if (CEL_UNLIKELY(b1 < accept[0] || b1 > accept[1])) { - _cel_Utf8_DecodeFailed(pnt, units); - return; - } - if (size == 1) { - _cel_Utf8_DecodeResult((((char32_t)(b & _cel_kUtf8Mask2)) << 6) | - ((char32_t)(b1 & _cel_kUtf8MaskX)), - 2, pnt, units); - return; - } - const uint8_t b2 = (uint8_t)(*data++); - if (CEL_UNLIKELY(b2 < _cel_kUtf8Low || b2 > _cel_kUtf8High)) { - _cel_Utf8_DecodeFailed(pnt, units); - return; - } - if (size == 2) { - _cel_Utf8_DecodeResult((((char32_t)(b & _cel_kUtf8Mask3)) << 12) | - (((char32_t)(b1 & _cel_kUtf8MaskX)) << 6) | - ((char32_t)(b2 & _cel_kUtf8MaskX)), - 3, pnt, units); - return; - } - const uint8_t b3 = (uint8_t)(*data++); - if (CEL_UNLIKELY(b3 < _cel_kUtf8Low || b3 > _cel_kUtf8High)) { - _cel_Utf8_DecodeFailed(pnt, units); - return; - } - CEL_ASSERT_EQ(size, 3); - _cel_Utf8_DecodeResult((((char32_t)(b & _cel_kUtf8Mask4)) << 18) | - (((char32_t)(b1 & _cel_kUtf8MaskX)) << 12) | - (((char32_t)(b2 & _cel_kUtf8MaskX)) << 6) | - ((char32_t)(b3 & _cel_kUtf8MaskX)), - 4, pnt, units); -} - -size_t _cel_Utf8_Encode(char32_t pnt, CEL_NONNULL(char*) str, size_t len) { - CEL_ASSERT_NOT_NULL(str); - CEL_ASSERT_GT(len, 0); - if (CEL_UNLIKELY(!_cel_Unicode_IsValid(pnt))) { - pnt = _cel_Unicode_kReplacementChar; - } - size_t units; - if (pnt <= 0x7f) { - CEL_ASSERT_GE(len, 1); - *str = (char)((uint8_t)pnt); - units = 1; - } else if (pnt <= 0x7ff) { - CEL_ASSERT_GE(len, 2); - *str++ = (char)(_cel_kUtf8T2 | ((uint8_t)(pnt >> 6))); - *str = (char)(_cel_kUtf8TX | (((uint8_t)pnt) & _cel_kUtf8MaskX)); - units = 2; - } else if (pnt <= 0xffff) { - CEL_ASSERT_GE(len, 3); - *str++ = (char)(_cel_kUtf8T3 | ((uint8_t)(pnt >> 12))); - *str++ = (char)(_cel_kUtf8TX | (((uint8_t)(pnt >> 6)) & _cel_kUtf8MaskX)); - *str = (char)(_cel_kUtf8TX | (((uint8_t)pnt) & _cel_kUtf8MaskX)); - units = 3; - } else { - CEL_ASSERT_GE(len, 4); - *str++ = (char)(_cel_kUtf8T4 | ((uint8_t)(pnt >> 18))); - *str++ = (char)(_cel_kUtf8TX | (((uint8_t)(pnt >> 12)) & _cel_kUtf8MaskX)); - *str++ = (char)(_cel_kUtf8TX | (((uint8_t)(pnt >> 6)) & _cel_kUtf8MaskX)); - *str = (char)(_cel_kUtf8TX | (((uint8_t)pnt) & _cel_kUtf8MaskX)); - units = 4; - } - return units; -} - -size_t _cel_Utf8_DecodedSize(upb_StringView str) { - size_t pnts = 0; - size_t units; - while (str.size > 0) { - _cel_Utf8_Decode(str, cel_nullptr, &units); - ++pnts; - str.data += units; - str.size -= units; - } - return pnts; -} - -bool _cel_Utf8_IsValid(upb_StringView str) { - char32_t pnt; - size_t units; - while (str.size > 0) { - _cel_Utf8_Decode(str, &pnt, &units); - if (pnt == _cel_Unicode_kReplacementChar && units == 1) { - return false; - } - str.data += units; - str.size -= units; - } - return true; -} diff --git a/cel-c/src/value.c b/cel-c/src/value.c deleted file mode 100644 index a9b73fc..0000000 --- a/cel-c/src/value.c +++ /dev/null @@ -1,734 +0,0 @@ -// Copyright 2025 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "cel-c/value.h" - -#include -#include -#include - -#include "cel-c/assert.h" -#include "cel-c/config.h" -#include "cel-c/duration.h" -#include "cel-c/error.h" -#include "cel-c/error_code.h" -#include "cel-c/status.h" -#include "cel-c/string_view.h" -#include "cel-c/timestamp.h" -#include "cel-c/type.h" -#include "cel-c/value_kind.h" -#include "cel-c/src/any.h" -#include "cel-c/duration.h" -#include "cel-c/src/parsed_map_field_value.h" -#include "cel-c/src/parsed_message_value.h" -#include "cel-c/src/parsed_repeated_field_value.h" -#include "cel-c/timestamp.h" -#include "upb/base/descriptor_constants.h" -#include "upb/message/array.h" -#include "upb/message/message.h" -#include "upb/reflection/def.h" -#include "upb/reflection/message.h" - -#define _cel_kDoubleToIntMax ((double)(int64_t)INT64_MAX) -#define _cel_kDoubleToIntMin ((double)(int64_t)INT64_MIN) -#define _cel_kDoubleToUintMin ((double)(uint64_t)0) -#define _cel_kDoubleToUintMax ((double)(uint64_t)UINT64_MAX) - -const cel_Value cel_NullValue = { - .data = - { - .v = {(char)0}, - }, - .kind = cel_ValueKind_kNull, - .padding = {(char)0}, -}; - -const cel_Value cel_FalseValue = { - .data = - { - .bl = false, - }, - .kind = cel_ValueKind_kBool, - .padding = {(char)0}, -}; - -const cel_Value cel_TrueValue = { - .data = - { - .bl = true, - }, - .kind = cel_ValueKind_kBool, - .padding = {(char)0}, -}; - -cel_StringView cel_Value_TypeName(const cel_Value* cel_nonnull value) { - CEL_ASSERT_NOT(cel_Value_IsError(value)); - CEL_ASSERT_NOT(cel_Value_IsUnknown(value)); - - switch (cel_Value_Kind(value)) { - case cel_ValueKind_kNull: - return cel_StringView_From("null_type"); - case cel_ValueKind_kBool: - return cel_StringView_From("bool"); - case cel_ValueKind_kInt: - return cel_StringView_From("int"); - case cel_ValueKind_kUint: - return cel_StringView_From("uint"); - case cel_ValueKind_kDouble: - return cel_StringView_From("double"); - case cel_ValueKind_kString: - return cel_StringView_From("string"); - case cel_ValueKind_kBytes: - return cel_StringView_From("bytes"); - case cel_ValueKind_kDuration: - return cel_StringView_From("google.protobuf.Duration"); - case cel_ValueKind_kTimestamp: - return cel_StringView_From("google.protobuf.Timestamp"); - case cel_ValueKind_kList: - return cel_StringView_From("list"); - case cel_ValueKind_kMap: - return cel_StringView_From("map"); - case cel_ValueKind_kStruct: - return cel_StructValue_TypeName(cel_Value_GetStruct(value)); - case cel_ValueKind_kOpaque: - return cel_OpaqueValue_TypeName(cel_Value_GetOpaque(value)); - case cel_ValueKind_kType: - return cel_StringView_From("type"); - default: - return cel_StringView_From(""); - } -} - -bool cel_Value_Equals(const cel_Value* cel_nonnull value, - const cel_ValueContext* cel_nonnull context, - const cel_Value* cel_nonnull other, - cel_Value* cel_nonnull result, - cel_Status* cel_nonnull status) { - CEL_ASSERT_NOT_NULL(value); - CEL_ASSERT_NOT_NULL(context); - CEL_ASSERT_NOT_NULL(other); - CEL_ASSERT_NOT_NULL(result); - CEL_ASSERT_NOT_NULL(status); - - if (CEL_UNLIKELY(!cel_Status_Ok(status))) { - return false; - } - - const cel_ValueKind value_kind = cel_Value_Kind(value); - const cel_ValueKind other_kind = cel_Value_Kind(other); - - if (value_kind == cel_ValueKind_kError) { - *result = *value; - return true; - } - - if (other_kind == cel_ValueKind_kError) { - *result = *other; - return true; - } - - if (value == other) { - cel_Value_SetTrue(result); - return true; - } - - if (value_kind != other_kind) { - { - const bool null_value = value_kind == cel_ValueKind_kNull; - const bool other_null_value = other_kind == cel_ValueKind_kNull; - if (null_value || other_null_value) { - cel_Value_SetBool(result, null_value == other_null_value); - return true; - } - } - // Heterogeneous - switch (value_kind) { - case cel_ValueKind_kInt: - switch (other_kind) { - case cel_ValueKind_kUint: { - const int64_t int_value = cel_Value_GetInt(value); - cel_Value_SetBool( - result, int_value >= 0 && - int_value == (int64_t)cel_Value_GetUint(other)); - } break; - case cel_ValueKind_kDouble: { - const double double_value = cel_Value_GetDouble(other); - cel_Value_SetBool( - result, double_value >= _cel_kDoubleToIntMin && - double_value <= _cel_kDoubleToIntMax && - double_value == (double)cel_Value_GetInt(value)); - } break; - default: - cel_Value_SetFalse(result); - break; - } - break; - case cel_ValueKind_kUint: - switch (other_kind) { - case cel_ValueKind_kInt: { - const int64_t int_value = cel_Value_GetInt(other); - cel_Value_SetBool( - result, int_value >= 0 && - int_value == (int64_t)cel_Value_GetUint(value)); - } break; - case cel_ValueKind_kDouble: { - const double double_value = cel_Value_GetDouble(other); - cel_Value_SetBool( - result, double_value >= _cel_kDoubleToUintMin && - double_value <= _cel_kDoubleToUintMax && - double_value == (double)cel_Value_GetUint(value)); - } break; - default: - cel_Value_SetFalse(result); - break; - } - break; - case cel_ValueKind_kDouble: - switch (other_kind) { - case cel_ValueKind_kInt: { - const double double_value = cel_Value_GetDouble(value); - cel_Value_SetBool( - result, double_value >= _cel_kDoubleToIntMin && - double_value <= _cel_kDoubleToIntMax && - double_value == (double)cel_Value_GetInt(other)); - } break; - case cel_ValueKind_kUint: { - const double double_value = cel_Value_GetDouble(value); - cel_Value_SetBool( - result, double_value >= _cel_kDoubleToUintMin && - double_value <= _cel_kDoubleToUintMax && - double_value == (double)cel_Value_GetUint(other)); - } break; - default: - cel_Value_SetFalse(result); - break; - } - break; - default: - cel_Value_SetFalse(result); - break; - } - return true; - } - - // Homogeneous - switch (value_kind) { - case cel_ValueKind_kNull: - cel_Value_SetTrue(result); - break; - case cel_ValueKind_kBool: - cel_Value_SetBool(result, - cel_Value_GetBool(value) == cel_Value_GetBool(other)); - break; - case cel_ValueKind_kInt: - cel_Value_SetBool(result, - cel_Value_GetInt(value) == cel_Value_GetInt(other)); - break; - case cel_ValueKind_kUint: - cel_Value_SetBool(result, - cel_Value_GetUint(value) == cel_Value_GetUint(other)); - break; - case cel_ValueKind_kDouble: - cel_Value_SetBool( - result, cel_Value_GetDouble(value) == cel_Value_GetDouble(other)); - break; - case cel_ValueKind_kString: - cel_Value_SetBool(result, - cel_StringView_Equals(cel_Value_GetString(value), - cel_Value_GetString(other))); - break; - case cel_ValueKind_kBytes: - cel_Value_SetBool(result, - cel_StringView_Equals(cel_Value_GetBytes(value), - cel_Value_GetBytes(other))); - break; - case cel_ValueKind_kDuration: - cel_Value_SetBool(result, - cel_Duration_Equals(cel_Value_GetDuration(value), - cel_Value_GetDuration(other))); - break; - case cel_ValueKind_kTimestamp: - cel_Value_SetBool(result, - cel_Timestamp_Equals(cel_Value_GetTimestamp(value), - cel_Value_GetTimestamp(other))); - break; - case cel_ValueKind_kList: - return cel_ListValue_Equals(cel_Value_GetList(value), context, - cel_Value_GetList(other), result, status); - case cel_ValueKind_kMap: - return cel_MapValue_Equals(cel_Value_GetMap(value), context, - cel_Value_GetMap(other), result, status); - case cel_ValueKind_kStruct: - return cel_StructValue_Equals(cel_Value_GetStruct(value), context, - cel_Value_GetStruct(other), result, status); - case cel_ValueKind_kOpaque: - return cel_OpaqueValue_Equals(cel_Value_GetOpaque(value), context, - cel_Value_GetOpaque(other), result, status); - case cel_ValueKind_kType: - cel_Value_SetBool(result, - cel_StringView_Equals(cel_Value_GetType(value), - cel_Value_GetType(other))); - break; - case cel_ValueKind_kUnknown: - CEL_ATTRIBUTE_FALLTHROUGH; - default: - cel_Value_SetFalse(result); - break; - } - return true; -} - -bool cel_Value_FromMessage(cel_Value* cel_nonnull value, - const cel_ValueContext* cel_nonnull context, - const upb_Message* message_val, - const upb_MessageDef* cel_nonnull message_def, - cel_Status* cel_nonnull status) { - CEL_ASSERT_NOT_NULL(value); - CEL_ASSERT_NOT_NULL(context); - CEL_ASSERT_NOT_NULL(message_val); - CEL_ASSERT_NOT_NULL(message_def); - CEL_ASSERT_NOT_NULL(status); - - if (CEL_UNLIKELY(!cel_Status_Ok(status))) { - return false; - } - - upb_WellKnown well_known_type = upb_MessageDef_WellKnownType(message_def); - if (well_known_type == kUpb_WellKnown_Any) { - CEL_ASSERT_EQ(message_def, context->well_known_types->any.def); - upb_Message* out_message_val; - const upb_MessageDef* out_message_def; - _cel_AnyUnpackResult result = _cel_AnyUnpack( - message_val, context->def_pool, &context->well_known_types->any, - context->arena, &out_message_val, &out_message_def); - if (result != _cel_AnyUnpackResult_kOk) { - if (result == _cel_AnyUnpackResult_kOutOfMemory) { - cel_OutOfMemoryStatus(status); - return false; - } - cel_Error* error = cel_Error_New(context->arena); - if (CEL_UNLIKELY(error == cel_nullptr)) { - cel_OutOfMemoryStatus(status); - return false; - } - cel_Error_SetCanonicalCode( - error, (cel_ErrorCode)_cel_AnyUnpackResult_ToStatusCode(result)); - cel_Error_SetMessage(error, cel_StringView_FromString( - _cel_AnyUnpackResult_ToMessage(result))); - cel_Value_SetError(value, error); - return true; - } - message_val = out_message_val; - message_def = out_message_def; - well_known_type = upb_MessageDef_WellKnownType(out_message_def); - } - - switch (well_known_type) { - case kUpb_WellKnown_Duration: { - CEL_ASSERT_EQ(message_def, context->well_known_types->duration.def); - int64_t seconds = - upb_Message_GetFieldByDef( - message_val, context->well_known_types->duration.seconds_def) - .int64_val; - int32_t nanos = - upb_Message_GetFieldByDef( - message_val, context->well_known_types->duration.nanos_def) - .int32_val; - if (cel_Duration_Normalize(&seconds, &nanos)) { - cel_Value_SetDuration(value, cel_Duration_FromUnix(seconds, nanos)); - } else { - cel_Error* error = cel_Error_New(context->arena); - if (CEL_UNLIKELY(error == cel_nullptr)) { - cel_OutOfMemoryStatus(status); - return false; - } - cel_Error_SetCanonicalCode(error, cel_ErrorCode_kOutOfRange); - cel_Error_SetMessage(error, - cel_StringView_From("duration out of range")); - cel_Value_SetError(value, error); - } - return true; - } - case kUpb_WellKnown_Timestamp: { - CEL_ASSERT_EQ(message_def, context->well_known_types->timestamp.def); - int64_t seconds = - upb_Message_GetFieldByDef( - message_val, context->well_known_types->timestamp.seconds_def) - .int64_val; - int32_t nanos = - upb_Message_GetFieldByDef( - message_val, context->well_known_types->timestamp.nanos_def) - .int32_val; - if (cel_Timestamp_Normalize(&seconds, &nanos)) { - cel_Value_SetTimestamp(value, cel_Timestamp_FromUnix(seconds, nanos)); - } else { - cel_Error* error = cel_Error_New(context->arena); - if (CEL_UNLIKELY(error == cel_nullptr)) { - cel_OutOfMemoryStatus(status); - return false; - } - cel_Error_SetCanonicalCode(error, cel_ErrorCode_kOutOfRange); - cel_Error_SetMessage(error, - cel_StringView_From("timestamp out of range")); - cel_Value_SetError(value, error); - } - return true; - } - case kUpb_WellKnown_DoubleValue: - CEL_ASSERT_EQ(message_def, context->well_known_types->double_value.def); - cel_Value_SetDouble( - value, - upb_Message_GetFieldByDef( - message_val, context->well_known_types->double_value.value_def) - .double_val); - return true; - case kUpb_WellKnown_FloatValue: - CEL_ASSERT_EQ(message_def, context->well_known_types->float_value.def); - cel_Value_SetDouble( - value, - upb_Message_GetFieldByDef( - message_val, context->well_known_types->float_value.value_def) - .float_val); - return true; - case kUpb_WellKnown_Int64Value: - CEL_ASSERT_EQ(message_def, context->well_known_types->int64_value.def); - cel_Value_SetInt( - value, - upb_Message_GetFieldByDef( - message_val, context->well_known_types->int64_value.value_def) - .int64_val); - return true; - case kUpb_WellKnown_UInt64Value: - CEL_ASSERT_EQ(message_def, context->well_known_types->uint64_value.def); - cel_Value_SetUint( - value, - upb_Message_GetFieldByDef( - message_val, context->well_known_types->uint64_value.value_def) - .uint64_val); - return true; - case kUpb_WellKnown_Int32Value: - CEL_ASSERT_EQ(message_def, context->well_known_types->int32_value.def); - cel_Value_SetInt( - value, - upb_Message_GetFieldByDef( - message_val, context->well_known_types->int32_value.value_def) - .int32_val); - return true; - case kUpb_WellKnown_UInt32Value: - CEL_ASSERT_EQ(message_def, context->well_known_types->uint32_value.def); - cel_Value_SetUint( - value, - upb_Message_GetFieldByDef( - message_val, context->well_known_types->uint32_value.value_def) - .uint32_val); - return true; - case kUpb_WellKnown_StringValue: - CEL_ASSERT_EQ(message_def, context->well_known_types->string_value.def); - cel_Value_SetString( - value, - upb_Message_GetFieldByDef( - message_val, context->well_known_types->string_value.value_def) - .str_val); - return true; - case kUpb_WellKnown_BytesValue: - CEL_ASSERT_EQ(message_def, context->well_known_types->bytes_value.def); - cel_Value_SetBytes( - value, - upb_Message_GetFieldByDef( - message_val, context->well_known_types->bytes_value.value_def) - .str_val); - return true; - case kUpb_WellKnown_BoolValue: - CEL_ASSERT_EQ(message_def, context->well_known_types->bool_value.def); - cel_Value_SetBool( - value, - upb_Message_GetFieldByDef( - message_val, context->well_known_types->bool_value.value_def) - .bool_val); - return true; - case kUpb_WellKnown_Value: { - CEL_ASSERT_EQ(message_def, context->well_known_types->value.def); - const upb_FieldDef* field_def = upb_Message_WhichOneofByDef( - message_val, context->well_known_types->value.kind_def); - if (field_def == cel_nullptr) { - cel_Value_SetNull(value); - return true; - } - switch (upb_FieldDef_Number(field_def)) { - case 1: // null_value - CEL_ASSERT_EQ(field_def, - context->well_known_types->value.null_value_def); - cel_Value_SetNull(value); - return true; - case 2: // number_value - CEL_ASSERT_EQ(field_def, - context->well_known_types->value.number_value_def); - cel_Value_SetDouble( - value, - upb_Message_GetFieldByDef(message_val, field_def).double_val); - return true; - case 3: // string_value - CEL_ASSERT_EQ(field_def, - context->well_known_types->value.string_value_def); - cel_Value_SetString( - value, upb_Message_GetFieldByDef(message_val, field_def).str_val); - return true; - case 4: // bool_value - CEL_ASSERT_EQ(field_def, - context->well_known_types->value.bool_value_def); - cel_Value_SetBool( - value, - upb_Message_GetFieldByDef(message_val, field_def).bool_val); - return true; - case 5: // struct_value - CEL_ASSERT_EQ(field_def, - context->well_known_types->value.struct_value_def); - _cel_ParsedMapFieldValue_Set( - cel_Value_SetMap(value), - upb_Message_GetFieldByDef( - upb_Message_GetFieldByDef(message_val, field_def).msg_val, - context->well_known_types->struct_value.fields_def) - .map_val, - context->well_known_types->struct_value.fields_def); - return true; - case 6: // list_value - CEL_ASSERT_EQ(field_def, - context->well_known_types->value.list_value_def); - _cel_ParsedRepeatedFieldValue_Set( - cel_Value_SetList(value), - upb_Message_GetFieldByDef( - upb_Message_GetFieldByDef(message_val, field_def).msg_val, - context->well_known_types->list_value.values_def) - .array_val, - context->well_known_types->list_value.values_def); - return true; - default: - CEL_UNREACHABLE(); - } - } - case kUpb_WellKnown_ListValue: - CEL_ASSERT_EQ(message_def, context->well_known_types->list_value.def); - _cel_ParsedRepeatedFieldValue_Set( - cel_Value_SetList(value), - upb_Message_GetFieldByDef( - message_val, context->well_known_types->list_value.values_def) - .array_val, - context->well_known_types->list_value.values_def); - return true; - case kUpb_WellKnown_Struct: - CEL_ASSERT_EQ(message_def, context->well_known_types->struct_value.def); - _cel_ParsedMapFieldValue_Set( - cel_Value_SetMap(value), - upb_Message_GetFieldByDef( - message_val, context->well_known_types->struct_value.fields_def) - .map_val, - context->well_known_types->struct_value.fields_def); - return true; - default: - _cel_ParsedMessageValue_Set(cel_Value_SetStruct(value), message_val, - message_def); - return true; - } -} - -bool cel_Value_FromEnum(cel_Value* cel_nonnull value, - const cel_ValueContext* cel_nonnull context, - int32_t enum_val, - const upb_EnumDef* cel_nonnull enum_def, - cel_Status* cel_nonnull status) { - CEL_ASSERT_NOT_NULL(value); - CEL_ASSERT_NOT_NULL(enum_def); - CEL_ASSERT_NOT_NULL(status); - - if (CEL_UNLIKELY(!cel_Status_Ok(status))) { - return false; - } - - if (context->well_known_types->null_value.def == enum_def) { - cel_Value_SetNull(value); - return true; - } - CEL_ASSERT_NOT(cel_IsWellKnownEnumType(enum_def)); - - if (upb_EnumDef_IsClosed(enum_def)) { - const upb_EnumValueDef* enum_val_def = - upb_EnumDef_FindValueByNumber(enum_def, enum_val); - if (CEL_UNLIKELY(enum_val_def == cel_nullptr)) { - cel_Error* error = cel_Error_New(context->arena); - if (CEL_UNLIKELY(error == cel_nullptr)) { - cel_OutOfMemoryStatus(status); - return false; - } - cel_Error_SetCanonicalCode(error, cel_ErrorCode_kInvalidArgument); - cel_Error_SetMessage( - error, cel_StringView_From("cel: number not present in closed enum")); - cel_Value_SetError(value, error); - return true; - } - } - cel_Value_SetInt(value, enum_val); - return true; -} - -bool cel_Value_FromEnumValue(cel_Value* cel_nonnull value, - const cel_ValueContext* cel_nonnull context, - const upb_EnumValueDef* enum_val, - cel_Status* cel_nonnull status) { - CEL_ASSERT_NOT_NULL(value); - CEL_ASSERT_NOT_NULL(enum_val); - CEL_ASSERT_NOT_NULL(status); - - if (CEL_UNLIKELY(!cel_Status_Ok(status))) { - return false; - } - - if (context->well_known_types->null_value.value_def == enum_val) { - cel_Value_SetNull(value); - } else { - CEL_ASSERT_NOT(cel_IsWellKnownEnumType(upb_EnumValueDef_Enum(enum_val))); - cel_Value_SetInt(value, upb_EnumValueDef_Number(enum_val)); - } - return true; -} - -CEL_ATTRIBUTE_NODISCARD -static bool _cel_Value_FromSingularField( - cel_Value* cel_nonnull value, const cel_ValueContext* cel_nonnull context, - upb_MessageValue field_val, const upb_FieldDef* cel_nonnull field_def, - cel_Status* cel_nonnull status) { - CEL_ASSERT_NOT(upb_FieldDef_IsMap(field_def)); - - switch (upb_FieldDef_CType(field_def)) { - case kUpb_CType_Bool: - cel_Value_SetBool(value, field_val.bool_val); - return true; - case kUpb_CType_Float: - cel_Value_SetDouble(value, field_val.float_val); - return true; - case kUpb_CType_Int32: - cel_Value_SetInt(value, field_val.int32_val); - return true; - case kUpb_CType_UInt32: - cel_Value_SetUint(value, field_val.uint32_val); - return true; - case kUpb_CType_Enum: - return cel_Value_FromEnum(value, context, field_val.int32_val, - upb_FieldDef_EnumSubDef(field_def), status); - case kUpb_CType_Message: - return cel_Value_FromMessage(value, context, field_val.msg_val, - upb_FieldDef_MessageSubDef(field_def), - status); - case kUpb_CType_Double: - cel_Value_SetDouble(value, field_val.double_val); - return true; - case kUpb_CType_Int64: - cel_Value_SetInt(value, field_val.int64_val); - return true; - case kUpb_CType_UInt64: - cel_Value_SetUint(value, field_val.uint64_val); - return true; - case kUpb_CType_String: - cel_Value_SetString(value, field_val.str_val); - return true; - case kUpb_CType_Bytes: - cel_Value_SetBytes(value, field_val.str_val); - return true; - } -} - -bool cel_Value_FromField(cel_Value* cel_nonnull value, - const cel_ValueContext* cel_nonnull context, - upb_MessageValue field_val, - const upb_FieldDef* cel_nonnull field_def, - cel_Status* cel_nonnull status) { - CEL_ASSERT_NOT_NULL(value); - CEL_ASSERT_NOT_NULL(context); - CEL_ASSERT_NOT_NULL(field_def); - CEL_ASSERT_NOT_NULL(status); - - if (CEL_UNLIKELY(!cel_Status_Ok(status))) { - return false; - } - - if (upb_FieldDef_IsMap(field_def)) { - _cel_ParsedMapFieldValue_Set(cel_Value_SetMap(value), field_val.map_val, - field_def); - return true; - } - - if (upb_FieldDef_IsRepeated(field_def)) { - _cel_ParsedRepeatedFieldValue_Set(cel_Value_SetList(value), - field_val.array_val, field_def); - return true; - } - - return _cel_Value_FromSingularField(value, context, field_val, field_def, - status); -} - -bool cel_Value_FromRepeatedFieldElement( - cel_Value* cel_nonnull value, const cel_ValueContext* cel_nonnull context, - upb_MessageValue field_val, const upb_FieldDef* cel_nonnull field_def, - cel_Status* cel_nonnull status) { - CEL_ASSERT_NOT_NULL(value); - CEL_ASSERT_NOT_NULL(context); - CEL_ASSERT_NOT_NULL(field_def); - CEL_ASSERT(upb_FieldDef_IsRepeated(field_def)); - CEL_ASSERT_NOT_NULL(status); - - if (CEL_UNLIKELY(!cel_Status_Ok(status))) { - return false; - } - - return _cel_Value_FromSingularField(value, context, field_val, field_def, - status); -} - -bool cel_Value_FromMapFieldKey(cel_Value* cel_nonnull value, - const cel_ValueContext* cel_nonnull context, - upb_MessageValue field_val, - const upb_FieldDef* cel_nonnull field_def, - cel_Status* cel_nonnull status) { - CEL_ASSERT_NOT_NULL(value); - CEL_ASSERT_NOT_NULL(context); - CEL_ASSERT_NOT_NULL(field_def); - CEL_ASSERT_NOT(upb_FieldDef_IsRepeated(field_def)); - CEL_ASSERT_NOT_NULL(status); - - if (CEL_UNLIKELY(!cel_Status_Ok(status))) { - return false; - } - - return _cel_Value_FromSingularField(value, context, field_val, field_def, - status); -} - -bool cel_Value_FromMapFieldValue(cel_Value* cel_nonnull value, - const cel_ValueContext* cel_nonnull context, - upb_MessageValue field_val, - const upb_FieldDef* cel_nonnull field_def, - cel_Status* cel_nonnull status) { - CEL_ASSERT_NOT_NULL(value); - CEL_ASSERT_NOT_NULL(context); - CEL_ASSERT_NOT_NULL(field_def); - CEL_ASSERT_NOT(upb_FieldDef_IsRepeated(field_def)); - CEL_ASSERT_NOT_NULL(status); - - if (CEL_UNLIKELY(!cel_Status_Ok(status))) { - return false; - } - - return _cel_Value_FromSingularField(value, context, field_val, field_def, - status); -} diff --git a/cel-c/status.c b/cel-c/status.c deleted file mode 100644 index dd0b297..0000000 --- a/cel-c/status.c +++ /dev/null @@ -1,406 +0,0 @@ -// Copyright 2025 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "cel-c/status.h" - -#include -#include -#include -#include -#include -#include - -#include "cel-c/alloc.h" -#include "cel-c/assert.h" -#include "cel-c/config.h" -#include "cel-c/error_space.h" -#include "cel-c/status_code.h" -#include "cel-c/string_view.h" -#include "cel-c/src/array.h" -#include "cel-c/src/string.h" - -#undef cel_OutOfMemoryStatus -#undef cel_Status_SetMessage -#undef cel_Status_VFormatMessage -#undef cel_Status_FormatMessage -#undef cel_Status_Set -#undef cel_Status_SetPayload - -typedef struct { - _cel_String type_url; - _cel_String value; -} _cel_StatusRepPayload; - -typedef union { - CEL_ATTRIBUTE_MAYBE_UNUSED cel_Status pub; - struct { - // code **must** be first. - unsigned int code; - - int raw_code; - CEL_NONNULL(const cel_ErrorSpace*) space; - _cel_String message; - _cel_Array(_cel_StatusRepPayload) payloads; - CEL_NULLABLE(const char*) file; - int line; - }; -} _cel_StatusRep; - -CEL_STATIC_ASSERT(sizeof(_cel_StatusRep) == sizeof(cel_Status)); -CEL_STATIC_ASSERT(alignof(_cel_StatusRep) == alignof(cel_Status)); -CEL_STATIC_ASSERT(offsetof(_cel_StatusRep, code) == offsetof(cel_Status, code)); - -CEL_ATTRIBUTE_NODISCARD -static CEL_NONNULL(const _cel_StatusRep*) - _cel_Status_ConstRep(CEL_NONNULL(const cel_Status*) status) { - return (const _cel_StatusRep*)status; -} - -CEL_ATTRIBUTE_NODISCARD -static CEL_NONNULL(_cel_StatusRep*) - _cel_Status_MutableRep(CEL_NONNULL(cel_Status*) status) { - return (_cel_StatusRep*)status; -} - -#define _cel_Status_Rep(status) \ - (_Generic((status), \ - const cel_Status*: _cel_Status_ConstRep, \ - cel_Status*: _cel_Status_MutableRep)((status))) - -static void _cel_StatusRepPayload_Construct(CEL_NONNULL(_cel_StatusRepPayload*) - payload) { - _cel_String_Construct(&payload->type_url); - _cel_String_Construct(&payload->value); -} - -static void _cel_StatusRepPayload_Destruct(CEL_NONNULL(_cel_StatusRepPayload*) - payload) { - _cel_String_Destruct(&payload->value, cel_DefaultAllocator); - _cel_String_Destruct(&payload->type_url, cel_DefaultAllocator); -} - -static void _cel_StatusRep_ResetMessage(CEL_NONNULL(_cel_StatusRep*) - status_rep) { - _cel_String_Reset(&status_rep->message, cel_DefaultAllocator); -} - -static void _cel_StatusRep_ResetPayloads(CEL_NONNULL(_cel_StatusRep*) - status_rep) { - const size_t payloads_size = _cel_Array_Size(&status_rep->payloads); - for (size_t i = 0; i < payloads_size; ++i) { - _cel_StatusRepPayload_Destruct( - _cel_Array_MutableAt(&status_rep->payloads, i)); - } - _cel_Array_Reset(&status_rep->payloads, cel_DefaultAllocator); -} - -CEL_ATTRIBUTE_NODISCARD -static unsigned int _cel_StatusRep_EncodeCanonical(cel_StatusCode code, - bool oom) { - return (((unsigned int)code) << 1) | (oom ? 1u : 0u); -} - -void cel_Status_Construct(CEL_NONNULL(cel_Status*) status) { - CEL_ASSERT_NOT_NULL(status); - - CEL_NONNULL(_cel_StatusRep*) status_rep = _cel_Status_Rep(status); - memset(status_rep, '\0', sizeof(*status_rep)); - status_rep->space = cel_CanonicalErrorSpace; - _cel_String_Construct(&status_rep->message); - _cel_Array_Construct(&status_rep->payloads); -} - -void cel_Status_Destruct(CEL_NONNULL(cel_Status*) status) { - CEL_ASSERT_NOT_NULL(status); - - CEL_NONNULL(_cel_StatusRep*) status_rep = _cel_Status_Rep(status); - const size_t payloads_size = _cel_Array_Size(&status_rep->payloads); - for (size_t i = 0; i < payloads_size; ++i) { - _cel_StatusRepPayload_Destruct( - _cel_Array_MutableAt(&status_rep->payloads, i)); - } - _cel_Array_Destruct(&status_rep->payloads, cel_DefaultAllocator); - _cel_String_Destruct(&status_rep->message, cel_DefaultAllocator); -} - -void cel_Status_Clear(CEL_NONNULL(cel_Status*) status) { - CEL_ASSERT_NOT_NULL(status); - - CEL_NONNULL(_cel_StatusRep*) status_rep = _cel_Status_Rep(status); - const size_t payloads_size = _cel_Array_Size(&status_rep->payloads); - for (size_t i = 0; i < payloads_size; ++i) { - _cel_StatusRepPayload_Destruct( - _cel_Array_MutableAt(&status_rep->payloads, i)); - } - _cel_Array_Clear(&status_rep->payloads); - _cel_String_Clear(&status_rep->message); - status_rep->code = - _cel_StatusRep_EncodeCanonical(cel_StatusCode_kOk, /*oom=*/false); - status_rep->space = cel_CanonicalErrorSpace; - status_rep->raw_code = cel_StatusCode_kOk; - status_rep->file = cel_nullptr; - status_rep->line = 0; -} - -void cel_Status_Reset(CEL_NONNULL(cel_Status*) status) { - CEL_ASSERT_NOT_NULL(status); - - CEL_NONNULL(_cel_StatusRep*) status_rep = _cel_Status_Rep(status); - _cel_StatusRep_ResetMessage(status_rep); - _cel_StatusRep_ResetPayloads(status_rep); - status_rep->code = - _cel_StatusRep_EncodeCanonical(cel_StatusCode_kOk, /*oom=*/false); - status_rep->space = cel_CanonicalErrorSpace; - status_rep->raw_code = cel_StatusCode_kOk; - status_rep->file = cel_nullptr; - status_rep->line = 0; -} - -CEL_NONNULL(const cel_ErrorSpace*) -cel_Status_Space(CEL_NONNULL(const cel_Status*) status) { - CEL_ASSERT_NOT_NULL(status); - - return _cel_Status_Rep(status)->space; -} - -int cel_Status_Code(CEL_NONNULL(const cel_Status*) status) { - CEL_ASSERT_NOT_NULL(status); - - return _cel_Status_Rep(status)->raw_code; -} - -cel_StringView cel_Status_Message(CEL_NONNULL(const cel_Status*) status) { - CEL_ASSERT_NOT_NULL(status); - - return _cel_String_ToStringView(&_cel_Status_Rep(status)->message); -} - -void cel_Status_SetCode(CEL_NONNULL(cel_Status*) status, - CEL_NONNULL(const cel_ErrorSpace*) space, int code) { - CEL_ASSERT_NOT_NULL(status); - CEL_ASSERT_NOT_NULL(space); - - cel_StatusCode canonical_code = cel_ErrorSpace_Canonical(space, code); - bool oom; - if (canonical_code == cel_StatusCode_kOk) { - cel_Status_Reset(status); - oom = false; - } else { - oom = cel_ErrorSpace_OutOfMemory(space, code); - } - CEL_NONNULL(_cel_StatusRep*) status_rep = _cel_Status_Rep(status); - status_rep->code = _cel_StatusRep_EncodeCanonical(canonical_code, oom); - status_rep->space = space; - status_rep->raw_code = code; -} - -bool cel_Status_SetMessage(CEL_NONNULL(cel_Status*) status, - CEL_NONNULL(const char*) file, int line, - cel_StringView message) { - CEL_ASSERT_NOT_NULL(status); - CEL_ASSERT_NOT_NULL(file); - CEL_ASSERT_GT(line, 0); - - if (cel_StringView_Empty(message) || status->code == cel_StatusCode_kOk) { - return true; - } - - if (!_cel_String_Assign(&_cel_Status_Rep(status)->message, - cel_DefaultAllocator, message)) { - cel_OutOfMemoryStatus(status, file, line); - return false; - } - - return true; -} - -void cel_OutOfMemoryStatus(CEL_NONNULL(cel_Status*) status, - CEL_NONNULL(const char*) file, int line) { - CEL_ASSERT_NOT_NULL(status); - CEL_ASSERT_NOT_NULL(file); - CEL_ASSERT_GT(line, 0); - - CEL_NONNULL(_cel_StatusRep*) status_rep = _cel_Status_Rep(status); - _cel_StatusRep_ResetMessage(status_rep); - _cel_StatusRep_ResetPayloads(status_rep); - status_rep->code = _cel_StatusRep_EncodeCanonical( - cel_StatusCode_kResourceExhausted, /*oom=*/true); - status_rep->space = cel_CanonicalErrorSpace; - status_rep->file = file; - status_rep->line = line; - status_rep->raw_code = cel_StatusCode_kResourceExhausted; -} - -bool cel_Status_VFormatMessage(CEL_NONNULL(cel_Status*) status, - CEL_NONNULL(const char*) file, int line, - const char* cel_nonnull fmt, va_list args) { - CEL_ASSERT_NOT_NULL(status); - CEL_ASSERT_NOT_NULL(file); - CEL_ASSERT_GT(line, 0); - CEL_ASSERT_NOT_NULL(fmt); - - CEL_NONNULL(_cel_StatusRep*) status_rep = _cel_Status_Rep(status); - _cel_String_Clear(&status_rep->message); - if (!_cel_String_VAppendF(&status_rep->message, cel_DefaultAllocator, fmt, - args)) { - cel_OutOfMemoryStatus(status, file, line); - return false; - } - status_rep->file = file; - status_rep->line = line; - return true; -} - -bool cel_Status_GetPayload(CEL_NONNULL(const cel_Status*) status, - cel_StringView type_url, - CEL_NULLABLE(cel_StringView*) value) { - CEL_ASSERT_NOT_NULL(status); - - if (cel_Status_Ok(status) || cel_StringView_Empty(type_url)) { - return false; - } - - CEL_NONNULL(const _cel_StatusRep*) status_rep = _cel_Status_Rep(status); - const size_t payloads_len = _cel_Array_Size(&status_rep->payloads); - for (size_t i = 0; i < payloads_len; ++i) { - CEL_NONNULL(const _cel_StatusRepPayload*) - payload_at = _cel_Array_At(&status_rep->payloads, i); - if (cel_StringView_Equals(_cel_String_ToStringView(&payload_at->type_url), - type_url)) { - if (value) { - *value = _cel_String_ToStringView(&payload_at->value); - } - return true; - } - } - - return false; -} - -bool cel_Status_SetPayload(CEL_NONNULL(cel_Status*) status, - cel_StringView type_url, cel_StringView value, - CEL_NONNULL(const char*) file, int line) { - CEL_ASSERT_NOT_NULL(status); - CEL_ASSERT_NOT_NULL(file); - CEL_ASSERT_GT(line, 0); - - if (cel_Status_Ok(status) || cel_StringView_Empty(type_url)) { - return true; - } - - CEL_NONNULL(_cel_StatusRep*) status_rep = _cel_Status_Rep(status); - const size_t payloads_len = _cel_Array_Size(&status_rep->payloads); - for (size_t i = 0; i < payloads_len; ++i) { - CEL_NONNULL(_cel_StatusRepPayload*) - payload_at = _cel_Array_MutableAt(&status_rep->payloads, i); - if (cel_StringView_Equals(_cel_String_ToStringView(&payload_at->type_url), - type_url)) { - if (!_cel_String_Assign(&payload_at->value, cel_DefaultAllocator, - value)) { - cel_OutOfMemoryStatus(status, file, line); - return false; - } - return true; - } - } - - CEL_NULLABLE(_cel_StatusRepPayload*) - payload = _cel_Array_Push(&status_rep->payloads, cel_DefaultAllocator); - if (payload == cel_nullptr) { - cel_OutOfMemoryStatus(status, file, line); - return false; - } - - _cel_StatusRepPayload_Construct(payload); - - if (!_cel_String_Assign(&payload->type_url, cel_DefaultAllocator, type_url)) { - cel_OutOfMemoryStatus(status, file, line); - return false; - } - - if (!_cel_String_Assign(&payload->value, cel_DefaultAllocator, value)) { - cel_OutOfMemoryStatus(status, file, line); - return false; - } - - return true; -} - -bool cel_Status_DeletePayload(CEL_NONNULL(cel_Status*) status, - cel_StringView type_url) { - CEL_ASSERT_NOT_NULL(status); - - if (cel_Status_Ok(status) || cel_StringView_Empty(type_url)) { - return false; - } - - CEL_NONNULL(_cel_StatusRep*) status_rep = _cel_Status_Rep(status); - const size_t payloads_len = _cel_Array_Size(&status_rep->payloads); - for (size_t i = 0; i < payloads_len; ++i) { - CEL_NONNULL(_cel_StatusRepPayload*) - payload_at = _cel_Array_MutableAt(&status_rep->payloads, i); - if (cel_StringView_Equals(_cel_String_ToStringView(&payload_at->type_url), - type_url)) { - _cel_StatusRepPayload_Destruct(payload_at); - _cel_Array_Erase(&status_rep->payloads, i); - return true; - } - } - - return false; -} - -bool cel_Status_NextPayload(CEL_NONNULL(const cel_Status*) status, - CEL_NULLABLE(cel_StringView*) type_url, - CEL_NULLABLE(cel_StringView*) value, - CEL_NONNULL(cel_StatusPayloadIterator*) iter) { - CEL_ASSERT_NOT_NULL(status); - CEL_ASSERT_NE(type_url, value); - CEL_ASSERT_NOT_NULL(iter); - CEL_ASSERT(iter->rep < cel_Status_Payloads(status) || iter->rep == SIZE_MAX); - - if (cel_Status_Ok(status)) { - return false; - } - - CEL_NONNULL(const _cel_StatusRep*) status_rep = _cel_Status_Rep(status); - size_t idx = ++iter->rep; - if (idx >= _cel_Array_Size(&status_rep->payloads)) { - return false; - } - CEL_NONNULL(const _cel_StatusRepPayload*) - payload = _cel_Array_At(&status_rep->payloads, idx); - if (type_url != cel_nullptr) { - *type_url = _cel_String_ToStringView(&payload->type_url); - } - if (value != cel_nullptr) { - *value = _cel_String_ToStringView(&payload->value); - } - iter->rep = idx; - return true; -} - -size_t cel_Status_Payloads(CEL_NONNULL(const cel_Status*) status) { - CEL_ASSERT_NOT_NULL(status); - - return cel_Status_Ok(status) - ? 0 - : _cel_Array_Size(&_cel_Status_Rep(status)->payloads); -} - -void cel_Status_ClearPayloads(CEL_NONNULL(cel_Status*) status) { - CEL_ASSERT_NOT_NULL(status); - - _cel_Array_Clear(&_cel_Status_Rep(status)->payloads); -} diff --git a/cel-c/status_code.c b/cel-c/status_code.c deleted file mode 100644 index 2268638..0000000 --- a/cel-c/status_code.c +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright 2025 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "cel-c/status_code.h" - -#include "cel-c/config.h" -#include "cel-c/error_code.h" - -CEL_NONNULL(const char*) cel_StatusCode_Name(cel_StatusCode code) { - switch (code) { - case cel_StatusCode_kOk: - return "OK"; - default: - return cel_ErrorCode_Name((cel_ErrorCode)code); - } -} - -CEL_NONNULL(const char*) cel_StatusCode_Message(cel_StatusCode code) { - switch (code) { - case cel_StatusCode_kOk: - return ""; - default: - return cel_ErrorCode_Message((cel_ErrorCode)code); - } -} diff --git a/cel-c/status_proto.c b/cel-c/status_proto.c deleted file mode 100644 index b78ca95..0000000 --- a/cel-c/status_proto.c +++ /dev/null @@ -1,145 +0,0 @@ -// Copyright 2025 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "cel-c/status_proto.h" - -#include -#include - -#include "google/protobuf/any.upb.h" -#include "google/rpc/code.upb.h" -#include "google/rpc/status.upb.h" -#include "cel-c/assert.h" -#include "cel-c/config.h" -#include "cel-c/status.h" -#include "cel-c/status_code_proto.h" -#include "cel-c/string_view.h" -#include "upb/base/string_view.h" -#include "upb/mem/arena.h" - -static bool _cel_Status_StrDup(cel_StringView in, CEL_NONNULL(upb_Arena*) arena, - CEL_NONNULL(upb_StringView*) out) { - if (cel_StringView_Empty(in)) { - *out = upb_StringView_FromString(""); - return true; - } - char* copied = upb_Arena_Malloc(arena, cel_StringView_Size(in)); - if (copied == cel_nullptr) { - return false; - } - memcpy(copied, cel_StringView_Data(in), cel_StringView_Size(in)); - *out = upb_StringView_FromDataAndSize(copied, cel_StringView_Size(in)); - return true; -} - -bool cel_Status_ToProto(CEL_NONNULL(const cel_Status*) in, - CEL_NONNULL(upb_Arena*) arena, - CEL_NONNULL(google_rpc_Status*) out) { - CEL_ASSERT_NOT_NULL(in); - CEL_ASSERT_NOT_NULL(arena); - CEL_ASSERT_NOT_NULL(out); - - if (cel_Status_Ok(in)) { - google_rpc_Status_clear_code(out); - google_rpc_Status_clear_message(out); - google_rpc_Status_clear_details(out); - return true; - } - - google_rpc_Status_set_code(out, cel_StatusCode_ToProto(cel_Status_CanonicalCode(in))); - cel_StringView in_message = cel_Status_Message(in); - upb_StringView out_message; - if (!_cel_Status_StrDup(in_message, arena, &out_message)) { - return false; - } - google_rpc_Status_set_message(out, out_message); - - size_t in_payloads_len = cel_Status_Payloads(in); - if (in_payloads_len == 0) { - google_rpc_Status_clear_details(out); - } else { - google_protobuf_Any** out_payloads = - google_rpc_Status_resize_details(out, in_payloads_len, arena); - if (out_payloads == cel_nullptr) { - return false; - } - size_t i = 0; - cel_StringView in_type_url; - cel_StringView in_value; - cel_StatusPayloadIterator iter = cel_Status_BeginPayloads(in); - bool oom = false; - while (cel_Status_NextPayload(in, &in_type_url, &in_value, &iter)) { - google_protobuf_Any* out_payload = google_protobuf_Any_new(arena); - if (out_payload == cel_nullptr) { - oom = true; - break; - } - out_payloads[i++] = out_payload; - upb_StringView out_type_url; - if (!_cel_Status_StrDup(in_type_url, arena, &out_type_url)) { - oom = true; - break; - } - google_protobuf_Any_set_type_url(out_payload, out_type_url); - upb_StringView out_value; - if (!_cel_Status_StrDup(in_value, arena, &out_value)) { - oom = true; - break; - } - google_protobuf_Any_set_value(out_payload, out_value); - } - if (i < in_payloads_len) { - google_rpc_Status_resize_details(out, i, arena); - } - if (oom) { - return false; - } - } - - return true; -} - -bool cel_Status_FromProto(CEL_NONNULL(cel_Status*) out, - CEL_NONNULL(const google_rpc_Status*) in) { - CEL_ASSERT_NOT_NULL(in); - CEL_ASSERT_NOT_NULL(out); - - google_rpc_Code in_code = google_rpc_Status_code(in); - if (in_code == google_rpc_OK) { - cel_Status_Clear(out); - return true; - } - cel_Status_SetCanonicalCode(out, cel_StatusCode_FromProto(in_code)); - if (!cel_Status_SetMessage(out, google_rpc_Status_message(in))) { - return false; - } - - cel_Status_ClearPayloads(out); - - size_t in_payloads_len; - const google_protobuf_Any* const* in_payloads = - google_rpc_Status_details(in, &in_payloads_len); - for (size_t i = 0; i < in_payloads_len; ++i) { - const google_protobuf_Any* in_payload = in_payloads[i]; - CEL_ASSERT_NOT_NULL(in_payload); - if (in_payload == cel_nullptr) { - continue; - } - if (!cel_Status_SetPayload(out, google_protobuf_Any_type_url(in_payload), - google_protobuf_Any_value(in_payload))) { - return false; - } - } - return true; -} diff --git a/cel-c/string_view.c b/cel-c/string_view.c deleted file mode 100644 index 410153b..0000000 --- a/cel-c/string_view.c +++ /dev/null @@ -1,98 +0,0 @@ -// Copyright 2025 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "cel-c/string_view.h" - -#include -#include - -#include "cel-c/assert.h" -#include "cel-c/config.h" -#include "cel-c/src/memory.h" - -const char* cel_nullable cel_StringView_FindFirst(cel_StringView haystack, - cel_StringView needle) { - return _cel_Memory_FindFirst( - cel_StringView_Data(haystack), cel_StringView_Size(haystack), - cel_StringView_Data(needle), cel_StringView_Size(needle)); -} - -const char* cel_nullable cel_StringView_FindLast(cel_StringView haystack, - cel_StringView needle) { - return _cel_Memory_FindLast( - cel_StringView_Data(haystack), cel_StringView_Size(haystack), - cel_StringView_Data(needle), cel_StringView_Size(needle)); -} - -size_t cel_StringView_Count(cel_StringView haystack, cel_StringView needle) { - CEL_ASSERT_NOT(cel_StringView_Empty(needle)); - - size_t count = 0; - const char* pos; - while ((pos = cel_StringView_FindFirst(haystack, needle)) != cel_nullptr) { - cel_StringView_RemovePrefix( - &haystack, - (pos - cel_StringView_Data(haystack)) + cel_StringView_Size(needle)); - ++count; - } - return count; -} - -bool cel_StringViewTokenizer_Next(cel_StringViewTokenizer* cel_nonnull - tokenizer, - cel_StringView* cel_nonnull token) { - CEL_ASSERT_NOT_NULL(tokenizer); - CEL_ASSERT_NOT_NULL(token); - - if (tokenizer->done) { - return false; - } - const char* next = - cel_StringView_FindFirst(tokenizer->subject, tokenizer->delim); - if (next == cel_nullptr) { - *token = tokenizer->subject; - tokenizer->done = true; - return true; - } - const char* data = cel_StringView_Data(tokenizer->subject); - *token = cel_StringView_FromArray(data, next - data); - cel_StringView_RemovePrefix( - &tokenizer->subject, - (next - data) + cel_StringView_Size(tokenizer->delim)); - return true; -} - -bool cel_StringView_EqualsIgnoreCase(cel_StringView lhs, cel_StringView rhs) { - const char* const lhs_data = cel_StringView_Data(lhs); - const size_t lhs_size = cel_StringView_Size(lhs); - const char* const rhs_data = cel_StringView_Data(rhs); - if (lhs_size != cel_StringView_Size(rhs)) { - return false; - } - if (lhs_data == rhs_data) { - return true; - } - for (size_t i = 0; i < lhs_size; ++i) { - uint8_t lhs_c = (uint8_t)lhs_data[i]; - uint8_t rhs_c = (uint8_t)rhs_data[i]; - if (lhs_c != rhs_c) { - lhs_c = lhs_c >= 'A' && lhs_c <= 'Z' ? lhs_c - 'A' + 'a' : lhs_c; - rhs_c = rhs_c >= 'A' && rhs_c <= 'Z' ? rhs_c - 'A' + 'a' : rhs_c; - if (lhs_c != rhs_c) { - return false; - } - } - } - return true; -} diff --git a/cel-c/timestamp.c b/cel-c/timestamp.c deleted file mode 100644 index 5123781..0000000 --- a/cel-c/timestamp.c +++ /dev/null @@ -1,134 +0,0 @@ -// Copyright 2025 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "cel-c/timestamp.h" - -#include -#include - -#include "cel-c/assert.h" -#include "cel-c/config.h" -#include "cel-c/duration.h" -#include "cel-c/src/ckdint.h" - -bool cel_Timestamp_Normalize(int64_t* cel_nonnull sec, - int32_t* cel_nonnull nsec) { - int32_t rem; - - // Normalize nsec. - rem = *nsec / INT32_C(1000000000); - if (rem != 0) { - if (CEL_UNLIKELY(_cel_ckd_add(sec, *sec, (int64_t)rem))) { - return false; - } - *nsec %= INT32_C(1000000000); - } - - // Normalize sign. - if (*nsec < 0) { - if (CEL_UNLIKELY(_cel_ckd_sub(sec, *sec, INT64_C(1)))) { - return false; - } - *nsec += INT32_C(1000000000); - } - - return cel_Timestamp_Valid(*sec, *nsec); -} - -bool cel_Timestamp_Add(cel_Timestamp* cel_nonnull out, cel_Timestamp lhs, - cel_Duration rhs) { - CEL_ASSERT_NOT_NULL(out); - CEL_ASSERT(cel_Timestamp_Valid(lhs.sec, lhs.nsec)); - CEL_ASSERT(cel_Duration_Valid(rhs.sec, rhs.nsec)); - - int64_t lhs_sec = lhs.sec; - int64_t rhs_sec = rhs.sec; - int64_t sec; - int32_t nsec; - int32_t lhs_nsec = lhs.nsec; - int32_t rhs_nsec = rhs.nsec; - - if (CEL_UNLIKELY(_cel_ckd_add(&sec, lhs_sec, rhs_sec))) { - return false; - } - - if (CEL_UNLIKELY(_cel_ckd_add(&nsec, lhs_nsec, rhs_nsec))) { - return false; - } - - if (CEL_UNLIKELY(!cel_Timestamp_Normalize(&sec, &nsec))) { - return false; - } - - *out = cel_Timestamp_FromUnix(sec, nsec); - return true; -} - -bool cel_Timestamp_Sub(cel_Timestamp* cel_nonnull out, cel_Timestamp lhs, - cel_Duration rhs) { - CEL_ASSERT_NOT_NULL(out); - CEL_ASSERT(cel_Timestamp_Valid(lhs.sec, lhs.nsec)); - CEL_ASSERT(cel_Duration_Valid(rhs.sec, rhs.nsec)); - - int64_t lhs_sec = lhs.sec; - int64_t rhs_sec = rhs.sec; - int64_t sec; - int32_t nsec; - int32_t lhs_nsec = lhs.nsec; - int32_t rhs_nsec = rhs.nsec; - - if (CEL_UNLIKELY(_cel_ckd_sub(&sec, lhs_sec, rhs_sec))) { - return false; - } - - if (CEL_UNLIKELY(_cel_ckd_sub(&nsec, lhs_nsec, rhs_nsec))) { - return false; - } - - if (CEL_UNLIKELY(!cel_Timestamp_Normalize(&sec, &nsec))) { - return false; - } - - *out = cel_Timestamp_FromUnix(sec, nsec); - return true; -} - -bool cel_Timestamp_Diff(cel_Duration* cel_nonnull out, cel_Timestamp lhs, - cel_Timestamp rhs) { - CEL_ASSERT_NOT_NULL(out); - CEL_ASSERT(cel_Timestamp_Valid(lhs.sec, lhs.nsec)); - CEL_ASSERT(cel_Timestamp_Valid(rhs.sec, rhs.nsec)); - - int64_t lhs_sec = lhs.sec; - int64_t rhs_sec = rhs.sec; - int64_t sec; - int32_t nsec; - int32_t lhs_nsec = lhs.nsec; - int32_t rhs_nsec = rhs.nsec; - - if (CEL_UNLIKELY(_cel_ckd_sub(&sec, lhs_sec, rhs_sec))) { - return false; - } - - if (CEL_UNLIKELY(_cel_ckd_sub(&nsec, lhs_nsec, rhs_nsec))) { - return false; - } - - if (CEL_UNLIKELY(!cel_Duration_Normalize(&sec, &nsec))) { - return false; - } - - *out = cel_Duration_FromUnix(sec, nsec); - return true; -} diff --git a/cel-c/timestamp_proto.c b/cel-c/timestamp_proto.c deleted file mode 100644 index ae30791..0000000 --- a/cel-c/timestamp_proto.c +++ /dev/null @@ -1,50 +0,0 @@ -// Copyright 2025 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "cel-c/timestamp_proto.h" - -#include -#include - -#include "google/protobuf/timestamp.upb.h" -#include "cel-c/assert.h" -#include "cel-c/config.h" -#include "cel-c/timestamp.h" - -void cel_Timestamp_ToProto(cel_Timestamp in, - CEL_NONNULL(google_protobuf_Timestamp*) out) { - CEL_ASSERT_NOT_NULL(out); - - int64_t sec; - int32_t nsec; - cel_Timestamp_ToUnix(in, &sec, &nsec); - google_protobuf_Timestamp_set_seconds(out, sec); - google_protobuf_Timestamp_set_nanos(out, nsec); -} - -bool cel_Timestamp_FromProto(CEL_NONNULL(cel_Timestamp*) out, - CEL_NONNULL(const google_protobuf_Timestamp*) in) { - CEL_ASSERT_NOT_NULL(out); - CEL_ASSERT_NOT_NULL(in); - - int64_t sec; - int32_t nsec; - sec = google_protobuf_Timestamp_seconds(in); - nsec = google_protobuf_Timestamp_nanos(in); - if (!cel_Timestamp_Normalize(&sec, &nsec)) { - return false; - } - *out = cel_Timestamp_FromUnix(sec, nsec); - return true; -} diff --git a/cel-c/type.c b/cel-c/type.c deleted file mode 100644 index dc561ca..0000000 --- a/cel-c/type.c +++ /dev/null @@ -1,829 +0,0 @@ -// Copyright 2025 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "cel-c/type.h" - -#include -#include -#include -#include -#include -#include -#include - -#include "cel-c/arena.h" -#include "cel-c/assert.h" -#include "cel-c/config.h" -#include "cel-c/string_view.h" -#include "cel-c/type_kind.h" -#include "upb/reflection/def.h" - -struct cel_ListType { - cel_TypeKind kind; - - const cel_Type* cel_nonnull elem; -}; - -struct cel_MapType { - cel_TypeKind kind; - - const cel_Type* cel_nonnull key_val[2]; -}; - -struct cel_StructType { - cel_TypeKind kind; - - cel_StringView name; -}; - -struct cel_EnumType { - cel_TypeKind kind; - - cel_StringView name; -}; - -struct cel_OpaqueType { - cel_TypeKind kind; - - cel_StringView name; - size_t params_len; - const cel_Type* cel_nonnull params[]; -}; - -struct cel_OptionalType { - cel_OpaqueType super; -}; - -struct cel_TypeType { - cel_TypeKind kind; - - const cel_Type* cel_nonnull type; -}; - -struct cel_TypeParamType { - cel_TypeKind kind; - - cel_StringView name; -}; - -struct cel_FunctionType { - cel_TypeKind kind; - - const cel_Type* cel_nonnull result; - size_t args_len; - const cel_Type* cel_nonnull args[]; -}; - -struct cel_Type { - union { - struct { - cel_TypeKind kind; - }; - cel_ListType list_type; - cel_MapType map_type; - cel_StructType struct_type; - cel_EnumType enum_type; - cel_OpaqueType opaque_type; - cel_OptionalType optional_type; - cel_TypeType type_type; - cel_TypeParamType type_param_type; - cel_FunctionType function_type; - }; -}; - -bool cel_IsWellKnownMessageType(const upb_MessageDef* cel_nonnull def) { - switch (upb_MessageDef_WellKnownType(def)) { - case kUpb_WellKnown_Any: - return true; - case kUpb_WellKnown_Duration: - return true; - case kUpb_WellKnown_Timestamp: - return true; - case kUpb_WellKnown_DoubleValue: - return true; - case kUpb_WellKnown_FloatValue: - return true; - case kUpb_WellKnown_Int64Value: - return true; - case kUpb_WellKnown_UInt64Value: - return true; - case kUpb_WellKnown_Int32Value: - return true; - case kUpb_WellKnown_UInt32Value: - return true; - case kUpb_WellKnown_StringValue: - return true; - case kUpb_WellKnown_BytesValue: - return true; - case kUpb_WellKnown_BoolValue: - return true; - case kUpb_WellKnown_Value: - return true; - case kUpb_WellKnown_ListValue: - return true; - case kUpb_WellKnown_Struct: - return true; - default: - return false; - } -} - -static const cel_StringView _cel_kWellKnownMessageTypeNames[] = { - CEL_STRINGVIEW_C("Any"), CEL_STRINGVIEW_C("BoolValue"), - CEL_STRINGVIEW_C("BytesValue"), CEL_STRINGVIEW_C("DoubleValue"), - CEL_STRINGVIEW_C("Duration"), CEL_STRINGVIEW_C("FloatValue"), - CEL_STRINGVIEW_C("Int32Value"), CEL_STRINGVIEW_C("Int64Value"), - CEL_STRINGVIEW_C("ListValue"), CEL_STRINGVIEW_C("StringValue"), - CEL_STRINGVIEW_C("Struct"), CEL_STRINGVIEW_C("Timestamp"), - CEL_STRINGVIEW_C("UInt32Value"), CEL_STRINGVIEW_C("UInt64Value"), - CEL_STRINGVIEW_C("Value"), -}; - -static int _cel_kWellKnownMessageTypeNames_Compare( - const void* cel_nullability_unknown lhs, - const void* cel_nullability_unknown rhs) { - return cel_StringView_Compare(*(const cel_StringView*)lhs, - *(const cel_StringView*)rhs); -} - -bool cel_IsWellKnownMessageTypeName(cel_StringView name) { - return cel_StringView_ConsumePrefix( - &name, cel_StringView_From("google.protobuf.")) && - bsearch(&name, &_cel_kWellKnownMessageTypeNames[0], - cel_arraysize(_cel_kWellKnownMessageTypeNames), - sizeof(*_cel_kWellKnownMessageTypeNames), - &_cel_kWellKnownMessageTypeNames_Compare) != cel_nullptr; -} - -bool cel_IsWellKnownEnumType(const upb_EnumDef* cel_nonnull def) { - const char* name = upb_EnumDef_FullName(def); - return name != cel_nullptr && strcmp(name, "google.protobuf.NullValue") == 0; -} - -bool cel_IsWellKnownEnumTypeName(cel_StringView name) { - return cel_StringView_Equals( - name, cel_StringView_From("google.protobuf.NullValue")); -} - -static const cel_Type _cel_DynType = { - .kind = cel_TypeKind_kDyn, -}; - -const cel_Type* const cel_nonnull cel_DynType = &_cel_DynType; - -static const cel_Type _cel_NullType = { - .kind = cel_TypeKind_kNull, -}; - -const cel_Type* const cel_nonnull cel_NullType = &_cel_NullType; - -static const cel_Type _cel_BoolType = { - .kind = cel_TypeKind_kBool, -}; - -const cel_Type* const cel_nonnull cel_BoolType = &_cel_BoolType; - -static const cel_Type _cel_IntType = { - .kind = cel_TypeKind_kInt, -}; - -const cel_Type* const cel_nonnull cel_IntType = &_cel_IntType; - -static const cel_Type _cel_UintType = { - .kind = cel_TypeKind_kUint, -}; - -const cel_Type* const cel_nonnull cel_UintType = &_cel_UintType; - -static const cel_Type _cel_DoubleType = { - .kind = cel_TypeKind_kDouble, -}; - -const cel_Type* const cel_nonnull cel_DoubleType = &_cel_DoubleType; - -static const cel_Type _cel_StringType = { - .kind = cel_TypeKind_kString, -}; - -const cel_Type* const cel_nonnull cel_StringType = &_cel_StringType; - -static const cel_Type _cel_BytesType = { - .kind = cel_TypeKind_kBytes, -}; - -const cel_Type* const cel_nonnull cel_BytesType = &_cel_BytesType; - -static const cel_Type _cel_AnyType = { - .kind = cel_TypeKind_kAny, -}; - -const cel_Type* const cel_nonnull cel_AnyType = &_cel_AnyType; - -static const cel_Type _cel_DurationType = { - .kind = cel_TypeKind_kDuration, -}; - -const cel_Type* const cel_nonnull cel_DurationType = &_cel_DurationType; - -static const cel_Type _cel_TimestampType = { - .kind = cel_TypeKind_kTimestamp, -}; - -const cel_Type* const cel_nonnull cel_TimestampType = &_cel_TimestampType; - -static const cel_Type _cel_UnknownType = { - .kind = cel_TypeKind_kUnknown, -}; - -const cel_Type* const cel_nonnull cel_UnknownType = &_cel_UnknownType; - -static const cel_Type _cel_ErrorType = { - .kind = cel_TypeKind_kError, -}; - -const cel_Type* const cel_nonnull cel_ErrorType = &_cel_ErrorType; - -static const cel_Type _cel_BoolWrapperType = { - .kind = cel_TypeKind_kBoolWrapper, -}; - -const cel_Type* const cel_nonnull cel_BoolWrapperType = &_cel_BoolWrapperType; - -static const cel_Type _cel_IntWrapperType = { - .kind = cel_TypeKind_kIntWrapper, -}; - -const cel_Type* const cel_nonnull cel_IntWrapperType = &_cel_IntWrapperType; - -static const cel_Type _cel_UintWrapperType = { - .kind = cel_TypeKind_kUintWrapper, -}; - -const cel_Type* const cel_nonnull cel_UintWrapperType = &_cel_UintWrapperType; - -static const cel_Type _cel_DoubleWrapperType = { - .kind = cel_TypeKind_kDoubleWrapper, -}; - -const cel_Type* const cel_nonnull cel_DoubleWrapperType = - &_cel_DoubleWrapperType; - -static const cel_Type _cel_StringWrapperType = { - .kind = cel_TypeKind_kStringWrapper, -}; - -const cel_Type* const cel_nonnull cel_StringWrapperType = - &_cel_StringWrapperType; - -static const cel_Type _cel_BytesWrapperType = { - .kind = cel_TypeKind_kBytesWrapper, -}; - -const cel_Type* const cel_nonnull cel_BytesWrapperType = &_cel_BytesWrapperType; - -cel_TypeKind cel_Type_Kind(const cel_Type* cel_nonnull type) { - CEL_ASSERT_NOT_NULL(type); - - return type->kind; -} - -cel_StringView cel_Type_Name(const cel_Type* cel_nonnull type) { - CEL_ASSERT_NOT_NULL(type); - - switch (cel_Type_Kind(type)) { - case cel_TypeKind_kDyn: - return cel_StringView_From("dyn"); - case cel_TypeKind_kNull: - return cel_StringView_From("null_type"); - case cel_TypeKind_kBool: - return cel_StringView_From("bool"); - case cel_TypeKind_kInt: - return cel_StringView_From("int"); - case cel_TypeKind_kUint: - return cel_StringView_From("uint"); - case cel_TypeKind_kDouble: - return cel_StringView_From("double"); - case cel_TypeKind_kString: - return cel_StringView_From("string"); - case cel_TypeKind_kBytes: - return cel_StringView_From("bytes"); - case cel_TypeKind_kStruct: - return cel_StructType_Name(cel_StructType_DownCast(type)); - case cel_TypeKind_kDuration: - return cel_StringView_From("google.protobuf.Duration"); - case cel_TypeKind_kTimestamp: - return cel_StringView_From("google.protobuf.Timestamp"); - case cel_TypeKind_kList: - return cel_StringView_From("list"); - case cel_TypeKind_kMap: - return cel_StringView_From("map"); - case cel_TypeKind_kUnknown: - return cel_StringView_From("**unknown**"); - case cel_TypeKind_kType: - return cel_StringView_From("type"); - case cel_TypeKind_kError: - return cel_StringView_From("**error**"); - case cel_TypeKind_kAny: - return cel_StringView_From("google.protobuf.Any"); - case cel_TypeKind_kOpaque: - return cel_OpaqueType_Name(cel_OpaqueType_DownCast(type)); - case cel_TypeKind_kBoolWrapper: - return cel_StringView_From("google.protobuf.BoolValue"); - case cel_TypeKind_kIntWrapper: - return cel_StringView_From("google.protobuf.Int64Value"); - case cel_TypeKind_kUintWrapper: - return cel_StringView_From("google.protobuf.UInt64Value"); - case cel_TypeKind_kDoubleWrapper: - return cel_StringView_From("google.protobuf.DoubleValue"); - case cel_TypeKind_kStringWrapper: - return cel_StringView_From("google.protobuf.StringValue"); - case cel_TypeKind_kBytesWrapper: - return cel_StringView_From("google.protobuf.BytesValue"); - case cel_TypeKind_kTypeParam: - return cel_TypeParamType_Name(cel_TypeParamType_DownCast(type)); - case cel_TypeKind_kFunction: - return cel_StringView_From("**function**"); - case cel_TypeKind_kEnum: - return cel_EnumType_Name(cel_EnumType_DownCast(type)); - default: - return cel_StringView_From(""); - } -} - -const cel_Type* cel_nonnull const* cel_nullability_unknown -cel_Type_Params(const cel_Type* cel_nonnull type, size_t* cel_nullable size) { - CEL_ASSERT_NOT_NULL(type); - - switch (cel_Type_Kind(type)) { - case cel_TypeKind_kList: - if (size != cel_nullptr) { - *size = 1; - } - return &cel_ListType_DownCast(type)->elem; - case cel_TypeKind_kMap: - if (size != cel_nullptr) { - *size = 2; - } - return cel_MapType_DownCast(type)->key_val; - case cel_TypeKind_kOpaque: - return cel_OpaqueType_Params(cel_OpaqueType_DownCast(type), size); - default: - if (size != cel_nullptr) { - *size = 0; - } - return cel_nullptr; - } -} - -bool cel_Type_Equals(const cel_Type* cel_nonnull lhs, - const cel_Type* cel_nonnull rhs) { - CEL_ASSERT_NOT_NULL(lhs); - CEL_ASSERT_NOT_NULL(rhs); - - if (lhs == rhs) { - return true; - } - - const cel_TypeKind kind = cel_Type_Kind(lhs); - if (kind != cel_Type_Kind(rhs)) { - return false; - } - - switch (kind) { - case cel_TypeKind_kDyn: - return true; - case cel_TypeKind_kNull: - return true; - case cel_TypeKind_kBool: - return true; - case cel_TypeKind_kInt: - return true; - case cel_TypeKind_kUint: - return true; - case cel_TypeKind_kDouble: - return true; - case cel_TypeKind_kString: - return true; - case cel_TypeKind_kBytes: - return true; - case cel_TypeKind_kStruct: - return cel_StructType_Equals(cel_StructType_DownCast(lhs), - cel_StructType_DownCast(rhs)); - case cel_TypeKind_kDuration: - return true; - case cel_TypeKind_kTimestamp: - return true; - case cel_TypeKind_kList: - return cel_ListType_Equals(cel_ListType_DownCast(lhs), - cel_ListType_DownCast(rhs)); - case cel_TypeKind_kMap: - return cel_MapType_Equals(cel_MapType_DownCast(lhs), - cel_MapType_DownCast(rhs)); - case cel_TypeKind_kUnknown: - return true; - case cel_TypeKind_kType: - return cel_TypeType_Equals(cel_TypeType_DownCast(lhs), - cel_TypeType_DownCast(rhs)); - case cel_TypeKind_kError: - return true; - case cel_TypeKind_kAny: - return true; - case cel_TypeKind_kOpaque: - return cel_OpaqueType_Equals(cel_OpaqueType_DownCast(lhs), - cel_OpaqueType_DownCast(rhs)); - case cel_TypeKind_kBoolWrapper: - return true; - case cel_TypeKind_kIntWrapper: - return true; - case cel_TypeKind_kUintWrapper: - return true; - case cel_TypeKind_kDoubleWrapper: - return true; - case cel_TypeKind_kStringWrapper: - return true; - case cel_TypeKind_kBytesWrapper: - return true; - case cel_TypeKind_kTypeParam: - return cel_TypeParamType_Equals(cel_TypeParamType_DownCast(lhs), - cel_TypeParamType_DownCast(rhs)); - case cel_TypeKind_kFunction: - return cel_FunctionType_Equals(cel_FunctionType_DownCast(lhs), - cel_FunctionType_DownCast(rhs)); - case cel_TypeKind_kEnum: - return cel_EnumType_Equals(cel_EnumType_DownCast(lhs), - cel_EnumType_DownCast(rhs)); - default: - return false; - } -} - -const cel_ListType* cel_nullable cel_ListType_New( - const cel_Type* cel_nonnull element, cel_Arena* cel_nonnull arena) { - CEL_ASSERT_NOT_NULL(element); - CEL_ASSERT_NOT_NULL(arena); - - cel_ListType* type = - (cel_ListType*)cel_Arena_Malloc(arena, sizeof(cel_ListType), cel_nullptr); - if (CEL_LIKELY(type != cel_nullptr)) { - memset(type, '\0', sizeof(*type)); - type->kind = cel_TypeKind_kList; - type->elem = element; - } - return type; -} - -const cel_Type* cel_nonnull -cel_ListType_Element(const cel_ListType* cel_nonnull type) { - CEL_ASSERT_NOT_NULL(type); - - return type->elem; -} - -bool cel_ListType_Equals(const cel_ListType* cel_nonnull lhs, - const cel_ListType* cel_nonnull rhs) { - CEL_ASSERT_NOT_NULL(lhs); - CEL_ASSERT_NOT_NULL(rhs); - - if (lhs == rhs) { - return true; - } - return cel_Type_Equals(cel_ListType_Element(lhs), cel_ListType_Element(rhs)); -} - -const cel_MapType* cel_nullable cel_MapType_New( - const cel_Type* cel_nonnull key, const cel_Type* cel_nonnull value, - cel_Arena* cel_nonnull arena) { - CEL_ASSERT_NOT_NULL(key); - CEL_ASSERT_NOT_NULL(value); - CEL_ASSERT_NOT_NULL(arena); - - cel_MapType* type = - (cel_MapType*)cel_Arena_Malloc(arena, sizeof(cel_MapType), cel_nullptr); - if (CEL_LIKELY(type != cel_nullptr)) { - memset(type, '\0', sizeof(*type)); - type->kind = cel_TypeKind_kMap; - type->key_val[0] = key; - type->key_val[1] = value; - } - return type; -} - -const cel_Type* cel_nonnull -cel_MapType_Key(const cel_MapType* cel_nonnull type) { - CEL_ASSERT_NOT_NULL(type); - - return type->key_val[0]; -} - -const cel_Type* cel_nonnull -cel_MapType_Value(const cel_MapType* cel_nonnull type) { - CEL_ASSERT_NOT_NULL(type); - - return type->key_val[1]; -} - -bool cel_MapType_Equals(const cel_MapType* cel_nonnull lhs, - const cel_MapType* cel_nonnull rhs) { - CEL_ASSERT_NOT_NULL(lhs); - CEL_ASSERT_NOT_NULL(rhs); - - if (lhs == rhs) { - return true; - } - return cel_Type_Equals(cel_MapType_Key(lhs), cel_MapType_Key(rhs)) && - cel_Type_Equals(cel_MapType_Value(lhs), cel_MapType_Value(rhs)); -} - -const cel_StructType* cel_nullable -cel_StructType_New(cel_StringView name, cel_Arena* cel_nonnull arena) { - CEL_ASSERT_NOT_NULL(arena); - - cel_StructType* type = (cel_StructType*)cel_Arena_Malloc( - arena, sizeof(cel_StructType), cel_nullptr); - if (CEL_LIKELY(type != cel_nullptr)) { - memset(type, '\0', sizeof(*type)); - type->kind = cel_TypeKind_kStruct; - type->name = name; - } - return type; -} - -cel_StringView cel_StructType_Name(const cel_StructType* cel_nonnull type) { - CEL_ASSERT_NOT_NULL(type); - - return type->name; -} - -bool cel_StructType_Equals(const cel_StructType* cel_nonnull lhs, - const cel_StructType* cel_nonnull rhs) { - CEL_ASSERT_NOT_NULL(lhs); - CEL_ASSERT_NOT_NULL(rhs); - - if (lhs == rhs) { - return true; - } - return cel_StringView_Equals(cel_StructType_Name(lhs), - cel_StructType_Name(rhs)); -} - -const cel_EnumType* cel_nullable -cel_EnumType_New(cel_StringView name, cel_Arena* cel_nonnull arena) { - CEL_ASSERT_NOT_NULL(arena); - - cel_EnumType* type = - (cel_EnumType*)cel_Arena_Malloc(arena, sizeof(cel_EnumType), cel_nullptr); - if (CEL_LIKELY(type != cel_nullptr)) { - memset(type, '\0', sizeof(*type)); - type->kind = cel_TypeKind_kEnum; - type->name = name; - } - return type; -} - -cel_StringView cel_EnumType_Name(const cel_EnumType* cel_nonnull type) { - CEL_ASSERT_NOT_NULL(type); - - return type->name; -} - -bool cel_EnumType_Equals(const cel_EnumType* cel_nonnull lhs, - const cel_EnumType* cel_nonnull rhs) { - CEL_ASSERT_NOT_NULL(lhs); - CEL_ASSERT_NOT_NULL(rhs); - - if (lhs == rhs) { - return true; - } - return cel_StringView_Equals(cel_EnumType_Name(lhs), cel_EnumType_Name(rhs)); -} - -cel_OpaqueType* cel_nullable -cel_OpaqueType_New(cel_StringView name, size_t params_len, - const cel_Type * cel_nullability_unknown * - cel_nullability_unknown * cel_nullability_unknown params, - cel_Arena* cel_nonnull arena) { - CEL_ASSERT(params != cel_nullptr || params_len == 0); - CEL_ASSERT_NOT_NULL(arena); - - const size_t size = - offsetof(cel_OpaqueType, params) + (sizeof(const cel_Type*) * params_len); - cel_OpaqueType* type = - (cel_OpaqueType*)cel_Arena_Malloc(arena, size, cel_nullptr); - if (CEL_LIKELY(type != cel_nullptr)) { - memset(type, '\0', size); - type->kind = cel_TypeKind_kOpaque; - type->name = name; - type->params_len = params_len; - if (params_len > 0) { - *params = type->params; - } - } - return type; -} - -cel_StringView cel_OpaqueType_Name(const cel_OpaqueType* cel_nonnull type) { - CEL_ASSERT_NOT_NULL(type); - - return type->name; -} - -const cel_Type* const cel_nonnull* cel_nullability_unknown -cel_OpaqueType_Params(const cel_OpaqueType* cel_nonnull type, - size_t* cel_nullable size) { - CEL_ASSERT_NOT_NULL(type); - - if (size != cel_nullptr) { - *size = type->params_len; - } - return type->params; -} - -bool cel_OpaqueType_Equals(const cel_OpaqueType* cel_nonnull lhs, - const cel_OpaqueType* cel_nonnull rhs) { - CEL_ASSERT_NOT_NULL(lhs); - CEL_ASSERT_NOT_NULL(rhs); - - if (lhs == rhs) { - return true; - } - size_t lhs_params_size; - size_t rhs_params_size; - const cel_Type* const* lhs_params = - cel_OpaqueType_Params(lhs, &lhs_params_size); - const cel_Type* const* rhs_params = - cel_OpaqueType_Params(rhs, &rhs_params_size); - if (lhs_params_size != rhs_params_size) { - return false; - } - if (!cel_StringView_Equals(cel_OpaqueType_Name(lhs), - cel_OpaqueType_Name(rhs))) { - return false; - } - for (size_t i = 0; i < lhs_params_size; ++i) { - if (!cel_Type_Equals(lhs_params[i], rhs_params[i])) { - return false; - } - } - return true; -} - -const cel_OptionalType* cel_nullable cel_OptionalType_New( - const cel_Type* cel_nonnull param, cel_Arena* cel_nonnull arena) { - CEL_ASSERT_NOT_NULL(param); - CEL_ASSERT_NOT_NULL(arena); - - const cel_Type** params; - cel_OpaqueType* type = cel_OpaqueType_New( - cel_StringView_FromString("optional_type"), 1, ¶ms, arena); - if (CEL_LIKELY(type != cel_nullptr)) { - *params = param; - } - return cel_OptionalType_MutableDownCast(type); -} - -const cel_TypeType* cel_nullable cel_TypeType_New( - const cel_Type* cel_nonnull type, cel_Arena* cel_nonnull arena) { - CEL_ASSERT_NOT_NULL(type); - CEL_ASSERT_NOT_NULL(arena); - - cel_TypeType* type_type = - (cel_TypeType*)cel_Arena_Malloc(arena, sizeof(cel_TypeType), cel_nullptr); - if (CEL_LIKELY(type_type != cel_nullptr)) { - memset(type_type, '\0', sizeof(*type_type)); - type_type->kind = cel_TypeKind_kType; - type_type->type = type; - } - return type_type; -} - -const cel_Type* cel_nonnull -cel_TypeType_Type(const cel_TypeType* cel_nonnull type) { - CEL_ASSERT_NOT_NULL(type); - - return type->type; -} - -bool cel_TypeType_Equals(const cel_TypeType* cel_nonnull lhs, - const cel_TypeType* cel_nonnull rhs) { - CEL_ASSERT_NOT_NULL(lhs); - CEL_ASSERT_NOT_NULL(rhs); - - if (lhs == rhs) { - return true; - } - return cel_Type_Equals(cel_TypeType_Type(lhs), cel_TypeType_Type(rhs)); -} - -const cel_TypeParamType* cel_nullable -cel_TypeParamType_New(cel_StringView name, cel_Arena* cel_nonnull arena) { - CEL_ASSERT_NOT_NULL(arena); - - cel_TypeParamType* type = (cel_TypeParamType*)cel_Arena_Malloc( - arena, sizeof(cel_TypeParamType), cel_nullptr); - if (CEL_LIKELY(type != cel_nullptr)) { - memset(type, '\0', sizeof(*type)); - type->kind = cel_TypeKind_kTypeParam; - type->name = name; - } - return type; -} - -cel_StringView cel_TypeParamType_Name( - const cel_TypeParamType* cel_nonnull type) { - CEL_ASSERT_NOT_NULL(type); - - return type->name; -} - -bool cel_TypeParamType_Equals(const cel_TypeParamType* cel_nonnull lhs, - const cel_TypeParamType* cel_nonnull rhs) { - CEL_ASSERT_NOT_NULL(lhs); - CEL_ASSERT_NOT_NULL(rhs); - - if (lhs == rhs) { - return true; - } - return cel_StringView_Equals(cel_TypeParamType_Name(lhs), - cel_TypeParamType_Name(rhs)); -} - -cel_FunctionType* cel_nullable -cel_FunctionType_New(const cel_Type* cel_nonnull result, size_t args_len, - const cel_Type * cel_nullability_unknown * - cel_nullability_unknown * cel_nullability_unknown args, - cel_Arena* cel_nonnull arena) { - CEL_ASSERT_NOT_NULL(result); - CEL_ASSERT(args != cel_nullptr || args_len == 0); - CEL_ASSERT_NOT_NULL(arena); - - const size_t size = - offsetof(cel_FunctionType, args) + (sizeof(const cel_Type*) * args_len); - cel_FunctionType* type = - (cel_FunctionType*)cel_Arena_Malloc(arena, size, cel_nullptr); - if (CEL_LIKELY(type != cel_nullptr)) { - memset(type, '\0', size); - type->kind = cel_TypeKind_kFunction; - type->result = result; - type->args_len = args_len; - if (args_len > 0) { - *args = type->args; - } - } - return type; -} - -const cel_Type* cel_nonnull -cel_FunctionType_Result(const cel_FunctionType* cel_nonnull type) { - CEL_ASSERT_NOT_NULL(type); - - return type->result; -} - -const cel_Type* const cel_nonnull* cel_nullability_unknown -cel_FunctionType_Args(const cel_FunctionType* cel_nonnull type, - size_t* cel_nullable size) { - CEL_ASSERT_NOT_NULL(type); - - if (size != cel_nullptr) { - *size = type->args_len; - } - return type->args; -} - -bool cel_FunctionType_Equals(const cel_FunctionType* cel_nonnull lhs, - const cel_FunctionType* cel_nonnull rhs) { - CEL_ASSERT_NOT_NULL(lhs); - CEL_ASSERT_NOT_NULL(rhs); - - if (lhs == rhs) { - return true; - } - size_t lhs_args_size; - size_t rhs_args_size; - const cel_Type* const* lhs_args = cel_FunctionType_Args(lhs, &lhs_args_size); - const cel_Type* const* rhs_args = cel_FunctionType_Args(rhs, &rhs_args_size); - if (lhs_args_size != rhs_args_size) { - return false; - } - if (!cel_Type_Equals(cel_FunctionType_Result(lhs), - cel_FunctionType_Result(rhs))) { - return false; - } - for (size_t i = 0; i < lhs_args_size; ++i) { - if (!cel_Type_Equals(lhs_args[i], rhs_args[i])) { - return false; - } - } - return true; -} diff --git a/cel-c/type_proto.c b/cel-c/type_proto.c deleted file mode 100644 index 83756e7..0000000 --- a/cel-c/type_proto.c +++ /dev/null @@ -1,299 +0,0 @@ -// Copyright 2025 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "cel-c/type_proto.h" - -#include - -#include "cel/expr/checked.upb.h" -#include "cel-c/arena.h" -#include "cel-c/assert.h" -#include "cel-c/config.h" -#include "cel-c/status.h" -#include "cel-c/string_view.h" -#include "cel-c/type.h" - -const cel_Type* cel_nullable cel_Type_FromProto( - const cel_expr_Type* cel_nonnull in, cel_Arena* cel_nonnull arena, - cel_Status* cel_nonnull status) { - CEL_ASSERT_NOT_NULL(in); - CEL_ASSERT_NOT_NULL(arena); - CEL_ASSERT(cel_Status_Ok(status)); - - const cel_expr_Type_type_kind_oneofcases type_kind = - cel_expr_Type_type_kind_case(in); - switch (type_kind) { - case cel_expr_Type_type_kind_dyn: - return cel_DynType; - case cel_expr_Type_type_kind_null: - return cel_NullType; - case cel_expr_Type_type_kind_primitive: { - const cel_expr_Type_PrimitiveType primitive = - cel_expr_Type_primitive(in); - switch (primitive) { - case cel_expr_Type_BOOL: - return cel_BoolType; - case cel_expr_Type_INT64: - return cel_IntType; - case cel_expr_Type_UINT64: - return cel_UintType; - case cel_expr_Type_DOUBLE: - return cel_DoubleType; - case cel_expr_Type_STRING: - return cel_StringType; - case cel_expr_Type_BYTES: - return cel_BytesType; - default: - cel_InvalidArgumentStatusF( - status, "cel: unexpected google.api.expr.Type.PrimitiveType: %d", - primitive); - return cel_nullptr; - } - } - case cel_expr_Type_type_kind_wrapper: { - const cel_expr_Type_PrimitiveType primitive = - cel_expr_Type_wrapper(in); - switch (primitive) { - case cel_expr_Type_BOOL: - return cel_BoolWrapperType; - case cel_expr_Type_INT64: - return cel_IntWrapperType; - case cel_expr_Type_UINT64: - return cel_UintWrapperType; - case cel_expr_Type_DOUBLE: - return cel_DoubleWrapperType; - case cel_expr_Type_STRING: - return cel_StringWrapperType; - case cel_expr_Type_BYTES: - return cel_BytesWrapperType; - default: - cel_InvalidArgumentStatusF( - status, "cel: unexpected google.api.expr.Type.PrimitiveType: %d", - primitive); - return cel_nullptr; - } - } - case cel_expr_Type_type_kind_well_known: { - const cel_expr_Type_WellKnownType well_known = - cel_expr_Type_well_known(in); - switch (well_known) { - case cel_expr_Type_ANY: - return cel_AnyType; - case cel_expr_Type_TIMESTAMP: - return cel_TimestampType; - case cel_expr_Type_DURATION: - return cel_DurationType; - default: - cel_InvalidArgumentStatusF( - status, "cel: unexpected google.api.expr.Type.WellKnownType: %d", - well_known); - return cel_nullptr; - } - } - case cel_expr_Type_type_kind_list_type: { - const cel_expr_Type_ListType* in_list = - cel_expr_Type_list_type(in); - const cel_ListType* out_list; - if (CEL_UNLIKELY(in_list == cel_nullptr)) { - out_list = cel_ListType_New(cel_DynType, arena); - } else { - const cel_expr_Type* in_list_element = - cel_expr_Type_ListType_elem_type(in_list); - if (CEL_UNLIKELY(in_list_element == cel_nullptr)) { - out_list = cel_ListType_New(cel_DynType, arena); - } else { - const cel_Type* out_list_element = - cel_Type_FromProto(in_list_element, arena, status); - if (CEL_UNLIKELY(out_list_element == cel_nullptr)) { - return cel_nullptr; - } - out_list = cel_ListType_New(out_list_element, arena); - } - } - if (CEL_UNLIKELY(out_list == cel_nullptr)) { - cel_OutOfMemoryStatus(status); - } - return cel_Type_UpCast(out_list); - } - case cel_expr_Type_type_kind_map_type: { - const cel_expr_Type_MapType* in_map = - cel_expr_Type_map_type(in); - const cel_MapType* out_map; - if (CEL_UNLIKELY(in_map == cel_nullptr)) { - out_map = cel_MapType_New(cel_DynType, cel_DynType, arena); - } else { - const cel_Type* out_map_key; - const cel_Type* out_map_value; - const cel_expr_Type* in_map_key = - cel_expr_Type_MapType_key_type(in_map); - if (CEL_UNLIKELY(in_map_key == cel_nullptr)) { - out_map_key = cel_DynType; - } else { - out_map_key = cel_Type_FromProto(in_map_key, arena, status); - if (CEL_UNLIKELY(out_map_key == cel_nullptr)) { - return cel_nullptr; - } - } - const cel_expr_Type* in_map_value = - cel_expr_Type_MapType_value_type(in_map); - if (CEL_UNLIKELY(in_map_value == cel_nullptr)) { - out_map_value = cel_DynType; - } else { - out_map_value = cel_Type_FromProto(in_map_value, arena, status); - if (CEL_UNLIKELY(out_map_value == cel_nullptr)) { - return cel_nullptr; - } - } - out_map = cel_MapType_New(out_map_key, out_map_value, arena); - } - if (CEL_UNLIKELY(out_map == cel_nullptr)) { - cel_OutOfMemoryStatus(status); - } - return cel_Type_UpCast(out_map); - } - case cel_expr_Type_type_kind_function: { - const cel_expr_Type_FunctionType* in_function = - cel_expr_Type_function(in); - const cel_expr_Type* in_function_result = - cel_expr_Type_FunctionType_result_type(in_function); - const cel_Type* out_function_result; - if (CEL_UNLIKELY(in_function_result == cel_nullptr)) { - out_function_result = cel_DynType; - } else { - out_function_result = - cel_Type_FromProto(in_function_result, arena, status); - if (CEL_UNLIKELY(out_function_result == cel_nullptr)) { - return cel_nullptr; - } - } - size_t function_args_len; - const cel_expr_Type* const* in_function_args = - cel_expr_Type_FunctionType_arg_types(in_function, - &function_args_len); - const cel_Type** out_function_args; - cel_FunctionType* out_function = cel_FunctionType_New( - out_function_result, function_args_len, &out_function_args, arena); - if (CEL_UNLIKELY(out_function == cel_nullptr)) { - cel_OutOfMemoryStatus(status); - return cel_nullptr; - } - for (size_t i = 0; i < function_args_len; ++i) { - const cel_expr_Type* in_function_arg = in_function_args[i]; - const cel_Type* out_function_arg; - if (CEL_UNLIKELY(in_function_arg == cel_nullptr)) { - out_function_arg = cel_DynType; - } else { - out_function_arg = cel_Type_FromProto(in_function_arg, arena, status); - if (CEL_UNLIKELY(out_function_arg == cel_nullptr)) { - return cel_nullptr; - } - } - out_function_args[i] = out_function_arg; - } - return cel_Type_UpCast(out_function); - } - case cel_expr_Type_type_kind_message_type: { - cel_StringView in_struct_name = cel_expr_Type_message_type(in); - cel_StringView out_struct_name; - if (CEL_UNLIKELY( - !cel_Arena_StrDup(arena, &out_struct_name, in_struct_name))) { - cel_OutOfMemoryStatus(status); - return cel_nullptr; - } - const cel_StructType* out_struct = - cel_StructType_New(out_struct_name, arena); - if (CEL_UNLIKELY(out_struct == cel_nullptr)) { - cel_OutOfMemoryStatus(status); - } - return cel_Type_UpCast(out_struct); - } - case cel_expr_Type_type_kind_type_param: { - cel_StringView in_type_param_name = cel_expr_Type_type_param(in); - cel_StringView out_type_param_name; - if (CEL_UNLIKELY(!cel_Arena_StrDup(arena, &out_type_param_name, - in_type_param_name))) { - cel_OutOfMemoryStatus(status); - return cel_nullptr; - } - const cel_TypeParamType* out_type_param = - cel_TypeParamType_New(out_type_param_name, arena); - if (CEL_UNLIKELY(out_type_param == cel_nullptr)) { - cel_OutOfMemoryStatus(status); - } - return cel_Type_UpCast(out_type_param); - } - case cel_expr_Type_type_kind_type: { - const cel_expr_Type* in_type = cel_expr_Type_type(in); - const cel_Type* out_type; - if (CEL_UNLIKELY(in_type == cel_nullptr)) { - out_type = cel_DynType; - } else { - out_type = cel_Type_FromProto(in_type, arena, status); - if (CEL_UNLIKELY(out_type == cel_nullptr)) { - return cel_nullptr; - } - } - const cel_TypeType* out_type_type = cel_TypeType_New(out_type, arena); - if (CEL_UNLIKELY(out_type == cel_nullptr)) { - cel_OutOfMemoryStatus(status); - return cel_nullptr; - } - return cel_Type_UpCast(out_type_type); - } - case cel_expr_Type_type_kind_error: - return cel_ErrorType; - case cel_expr_Type_type_kind_abstract_type: { - const cel_expr_Type_AbstractType* in_opaque = - cel_expr_Type_abstract_type(in); - cel_StringView in_opaque_name = - cel_expr_Type_AbstractType_name(in_opaque); - cel_StringView out_opaque_name; - if (CEL_UNLIKELY( - !cel_Arena_StrDup(arena, &out_opaque_name, in_opaque_name))) { - cel_OutOfMemoryStatus(status); - return cel_nullptr; - } - size_t opaque_params_len; - const cel_expr_Type* const* in_opaque_params = - cel_expr_Type_AbstractType_parameter_types(in_opaque, - &opaque_params_len); - const cel_Type** out_opaque_params; - cel_OpaqueType* out_opaque = cel_OpaqueType_New( - out_opaque_name, opaque_params_len, &out_opaque_params, arena); - if (CEL_UNLIKELY(out_opaque == cel_nullptr)) { - cel_OutOfMemoryStatus(status); - return cel_nullptr; - } - for (size_t i = 0; i < opaque_params_len; ++i) { - const cel_expr_Type* in_opaque_arg = in_opaque_params[i]; - const cel_Type* out_opaque_arg; - if (CEL_UNLIKELY(in_opaque_arg == cel_nullptr)) { - out_opaque_arg = cel_DynType; - } else { - out_opaque_arg = cel_Type_FromProto(in_opaque_arg, arena, status); - if (CEL_UNLIKELY(out_opaque_arg == cel_nullptr)) { - return cel_nullptr; - } - } - out_opaque_params[i] = out_opaque_arg; - } - return cel_Type_UpCast(out_opaque); - } - default: - cel_InvalidArgumentStatusF( - status, "cel: unexpected google.api.expr.Type.type_kind: %d", - type_kind); - return cel_nullptr; - } -} diff --git a/cel-c/type_proto_v1alpha1.c b/cel-c/type_proto_v1alpha1.c deleted file mode 100644 index 9d4a430..0000000 --- a/cel-c/type_proto_v1alpha1.c +++ /dev/null @@ -1,310 +0,0 @@ -// Copyright 2025 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "cel-c/type_proto_v1alpha1.h" - -#include - -#include "google/api/expr/v1alpha1/checked.upb.h" -#include "cel-c/arena.h" -#include "cel-c/assert.h" -#include "cel-c/config.h" -#include "cel-c/status.h" -#include "cel-c/string_view.h" -#include "cel-c/type.h" - -const cel_Type* cel_nullable cel_Type_FromProtoV1Alpha1( - const google_api_expr_v1alpha1_Type* cel_nonnull in, - cel_Arena* cel_nonnull arena, cel_Status* cel_nonnull status) { - CEL_ASSERT_NOT_NULL(in); - CEL_ASSERT_NOT_NULL(arena); - CEL_ASSERT(cel_Status_Ok(status)); - - const google_api_expr_v1alpha1_Type_type_kind_oneofcases type_kind = - google_api_expr_v1alpha1_Type_type_kind_case(in); - switch (type_kind) { - case google_api_expr_v1alpha1_Type_type_kind_dyn: - return cel_DynType; - case google_api_expr_v1alpha1_Type_type_kind_null: - return cel_NullType; - case google_api_expr_v1alpha1_Type_type_kind_primitive: { - const google_api_expr_v1alpha1_Type_PrimitiveType primitive = - google_api_expr_v1alpha1_Type_primitive(in); - switch (primitive) { - case google_api_expr_v1alpha1_Type_BOOL: - return cel_BoolType; - case google_api_expr_v1alpha1_Type_INT64: - return cel_IntType; - case google_api_expr_v1alpha1_Type_UINT64: - return cel_UintType; - case google_api_expr_v1alpha1_Type_DOUBLE: - return cel_DoubleType; - case google_api_expr_v1alpha1_Type_STRING: - return cel_StringType; - case google_api_expr_v1alpha1_Type_BYTES: - return cel_BytesType; - default: - cel_InvalidArgumentStatusF( - status, - "cel: unexpected google.api.expr.v1alpha1.Type.PrimitiveType: %d", - primitive); - return cel_nullptr; - } - } - case google_api_expr_v1alpha1_Type_type_kind_wrapper: { - const google_api_expr_v1alpha1_Type_PrimitiveType primitive = - google_api_expr_v1alpha1_Type_wrapper(in); - switch (primitive) { - case google_api_expr_v1alpha1_Type_BOOL: - return cel_BoolWrapperType; - case google_api_expr_v1alpha1_Type_INT64: - return cel_IntWrapperType; - case google_api_expr_v1alpha1_Type_UINT64: - return cel_UintWrapperType; - case google_api_expr_v1alpha1_Type_DOUBLE: - return cel_DoubleWrapperType; - case google_api_expr_v1alpha1_Type_STRING: - return cel_StringWrapperType; - case google_api_expr_v1alpha1_Type_BYTES: - return cel_BytesWrapperType; - default: - cel_InvalidArgumentStatusF( - status, - "cel: unexpected google.api.expr.v1alpha1.Type.PrimitiveType: %d", - primitive); - return cel_nullptr; - } - } - case google_api_expr_v1alpha1_Type_type_kind_well_known: { - const google_api_expr_v1alpha1_Type_WellKnownType well_known = - google_api_expr_v1alpha1_Type_well_known(in); - switch (well_known) { - case google_api_expr_v1alpha1_Type_ANY: - return cel_AnyType; - case google_api_expr_v1alpha1_Type_TIMESTAMP: - return cel_TimestampType; - case google_api_expr_v1alpha1_Type_DURATION: - return cel_DurationType; - default: - cel_InvalidArgumentStatusF( - status, - "cel: unexpected google.api.expr.v1alpha1.Type.WellKnownType: %d", - well_known); - return cel_nullptr; - } - } - case google_api_expr_v1alpha1_Type_type_kind_list_type: { - const google_api_expr_v1alpha1_Type_ListType* in_list = - google_api_expr_v1alpha1_Type_list_type(in); - const cel_ListType* out_list; - if (CEL_UNLIKELY(in_list == cel_nullptr)) { - out_list = cel_ListType_New(cel_DynType, arena); - } else { - const google_api_expr_v1alpha1_Type* in_list_element = - google_api_expr_v1alpha1_Type_ListType_elem_type(in_list); - if (CEL_UNLIKELY(in_list_element == cel_nullptr)) { - out_list = cel_ListType_New(cel_DynType, arena); - } else { - const cel_Type* out_list_element = - cel_Type_FromProtoV1Alpha1(in_list_element, arena, status); - if (CEL_UNLIKELY(out_list_element == cel_nullptr)) { - return cel_nullptr; - } - out_list = cel_ListType_New(out_list_element, arena); - } - } - if (CEL_UNLIKELY(out_list == cel_nullptr)) { - cel_OutOfMemoryStatus(status); - } - return cel_Type_UpCast(out_list); - } - case google_api_expr_v1alpha1_Type_type_kind_map_type: { - const google_api_expr_v1alpha1_Type_MapType* in_map = - google_api_expr_v1alpha1_Type_map_type(in); - const cel_MapType* out_map; - if (CEL_UNLIKELY(in_map == cel_nullptr)) { - out_map = cel_MapType_New(cel_DynType, cel_DynType, arena); - } else { - const cel_Type* out_map_key; - const cel_Type* out_map_value; - const google_api_expr_v1alpha1_Type* in_map_key = - google_api_expr_v1alpha1_Type_MapType_key_type(in_map); - if (CEL_UNLIKELY(in_map_key == cel_nullptr)) { - out_map_key = cel_DynType; - } else { - out_map_key = cel_Type_FromProtoV1Alpha1(in_map_key, arena, status); - if (CEL_UNLIKELY(out_map_key == cel_nullptr)) { - return cel_nullptr; - } - } - const google_api_expr_v1alpha1_Type* in_map_value = - google_api_expr_v1alpha1_Type_MapType_value_type(in_map); - if (CEL_UNLIKELY(in_map_value == cel_nullptr)) { - out_map_value = cel_DynType; - } else { - out_map_value = - cel_Type_FromProtoV1Alpha1(in_map_value, arena, status); - if (CEL_UNLIKELY(out_map_value == cel_nullptr)) { - return cel_nullptr; - } - } - out_map = cel_MapType_New(out_map_key, out_map_value, arena); - } - if (CEL_UNLIKELY(out_map == cel_nullptr)) { - cel_OutOfMemoryStatus(status); - } - return cel_Type_UpCast(out_map); - } - case google_api_expr_v1alpha1_Type_type_kind_function: { - const google_api_expr_v1alpha1_Type_FunctionType* in_function = - google_api_expr_v1alpha1_Type_function(in); - const google_api_expr_v1alpha1_Type* in_function_result = - google_api_expr_v1alpha1_Type_FunctionType_result_type(in_function); - const cel_Type* out_function_result; - if (CEL_UNLIKELY(in_function_result == cel_nullptr)) { - out_function_result = cel_DynType; - } else { - out_function_result = - cel_Type_FromProtoV1Alpha1(in_function_result, arena, status); - if (CEL_UNLIKELY(out_function_result == cel_nullptr)) { - return cel_nullptr; - } - } - size_t function_args_len; - const google_api_expr_v1alpha1_Type* const* in_function_args = - google_api_expr_v1alpha1_Type_FunctionType_arg_types( - in_function, &function_args_len); - const cel_Type** out_function_args; - cel_FunctionType* out_function = cel_FunctionType_New( - out_function_result, function_args_len, &out_function_args, arena); - if (CEL_UNLIKELY(out_function == cel_nullptr)) { - cel_OutOfMemoryStatus(status); - return cel_nullptr; - } - for (size_t i = 0; i < function_args_len; ++i) { - const google_api_expr_v1alpha1_Type* in_function_arg = - in_function_args[i]; - const cel_Type* out_function_arg; - if (CEL_UNLIKELY(in_function_arg == cel_nullptr)) { - out_function_arg = cel_DynType; - } else { - out_function_arg = - cel_Type_FromProtoV1Alpha1(in_function_arg, arena, status); - if (CEL_UNLIKELY(out_function_arg == cel_nullptr)) { - return cel_nullptr; - } - } - out_function_args[i] = out_function_arg; - } - return cel_Type_UpCast(out_function); - } - case google_api_expr_v1alpha1_Type_type_kind_message_type: { - cel_StringView in_struct_name = - google_api_expr_v1alpha1_Type_message_type(in); - cel_StringView out_struct_name; - if (CEL_UNLIKELY( - !cel_Arena_StrDup(arena, &out_struct_name, in_struct_name))) { - cel_OutOfMemoryStatus(status); - return cel_nullptr; - } - const cel_StructType* out_struct = - cel_StructType_New(out_struct_name, arena); - if (CEL_UNLIKELY(out_struct == cel_nullptr)) { - cel_OutOfMemoryStatus(status); - } - return cel_Type_UpCast(out_struct); - } - case google_api_expr_v1alpha1_Type_type_kind_type_param: { - cel_StringView in_type_param_name = - google_api_expr_v1alpha1_Type_type_param(in); - cel_StringView out_type_param_name; - if (CEL_UNLIKELY(!cel_Arena_StrDup(arena, &out_type_param_name, - in_type_param_name))) { - cel_OutOfMemoryStatus(status); - return cel_nullptr; - } - const cel_TypeParamType* out_type_param = - cel_TypeParamType_New(out_type_param_name, arena); - if (CEL_UNLIKELY(out_type_param == cel_nullptr)) { - cel_OutOfMemoryStatus(status); - } - return cel_Type_UpCast(out_type_param); - } - case google_api_expr_v1alpha1_Type_type_kind_type: { - const google_api_expr_v1alpha1_Type* in_type = - google_api_expr_v1alpha1_Type_type(in); - const cel_Type* out_type; - if (CEL_UNLIKELY(in_type == cel_nullptr)) { - out_type = cel_DynType; - } else { - out_type = cel_Type_FromProtoV1Alpha1(in_type, arena, status); - if (CEL_UNLIKELY(out_type == cel_nullptr)) { - return cel_nullptr; - } - } - const cel_TypeType* out_type_type = cel_TypeType_New(out_type, arena); - if (CEL_UNLIKELY(out_type == cel_nullptr)) { - cel_OutOfMemoryStatus(status); - return cel_nullptr; - } - return cel_Type_UpCast(out_type_type); - } - case google_api_expr_v1alpha1_Type_type_kind_error: - return cel_ErrorType; - case google_api_expr_v1alpha1_Type_type_kind_abstract_type: { - const google_api_expr_v1alpha1_Type_AbstractType* in_opaque = - google_api_expr_v1alpha1_Type_abstract_type(in); - cel_StringView in_opaque_name = - google_api_expr_v1alpha1_Type_AbstractType_name(in_opaque); - cel_StringView out_opaque_name; - if (CEL_UNLIKELY( - !cel_Arena_StrDup(arena, &out_opaque_name, in_opaque_name))) { - cel_OutOfMemoryStatus(status); - return cel_nullptr; - } - size_t opaque_params_len; - const google_api_expr_v1alpha1_Type* const* in_opaque_params = - google_api_expr_v1alpha1_Type_AbstractType_parameter_types( - in_opaque, &opaque_params_len); - const cel_Type** out_opaque_params; - cel_OpaqueType* out_opaque = cel_OpaqueType_New( - out_opaque_name, opaque_params_len, &out_opaque_params, arena); - if (CEL_UNLIKELY(out_opaque == cel_nullptr)) { - cel_OutOfMemoryStatus(status); - return cel_nullptr; - } - for (size_t i = 0; i < opaque_params_len; ++i) { - const google_api_expr_v1alpha1_Type* in_opaque_arg = - in_opaque_params[i]; - const cel_Type* out_opaque_arg; - if (CEL_UNLIKELY(in_opaque_arg == cel_nullptr)) { - out_opaque_arg = cel_DynType; - } else { - out_opaque_arg = - cel_Type_FromProtoV1Alpha1(in_opaque_arg, arena, status); - if (CEL_UNLIKELY(out_opaque_arg == cel_nullptr)) { - return cel_nullptr; - } - } - out_opaque_params[i] = out_opaque_arg; - } - return cel_Type_UpCast(out_opaque); - } - default: - cel_InvalidArgumentStatusF( - status, "cel: unexpected google.api.expr.v1alpha1.Type.type_kind: %d", - type_kind); - return cel_nullptr; - } -} diff --git a/cel-c/well_known_types.c b/cel-c/well_known_types.c deleted file mode 100644 index ab6ad24..0000000 --- a/cel-c/well_known_types.c +++ /dev/null @@ -1,738 +0,0 @@ -// Copyright 2025 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "cel-c/well_known_types.h" - -#include -#include -#include -#include - -#include "cel-c/assert.h" -#include "cel-c/config.h" -#include "cel-c/status.h" -#include "cel-c/string_view.h" -#include "upb/base/descriptor_constants.h" -#include "upb/reflection/def.h" - -CEL_ATTRIBUTE_NODISCARD -static const upb_MessageDef* cel_nullable _cel_WellKnownType_FindMessage( - const upb_DefPool* cel_nonnull def_pool, cel_StringView name, - bool error_if_not_found, cel_Status* cel_nonnull status) { - CEL_ASSERT(cel_Status_Ok(status)); - - const upb_MessageDef* def = upb_DefPool_FindMessageByNameWithSize( - def_pool, cel_StringView_Data(name), cel_StringView_Size(name)); - if (CEL_UNLIKELY(def == cel_nullptr)) { - if (error_if_not_found) { - cel_NotFoundStatusF( - status, "cel: well known message type not found: " CEL_STRINGVIEW_FMT, - CEL_STRINGVIEW_ARGS(name)); - } - return cel_nullptr; - } - return def; -} - -typedef enum { - _cel_WellKnownTypeFieldLabel_kOptional = 1, - _cel_WellKnownTypeFieldLabel_kRepeated, - _cel_WellKnownTypeFieldLabel_kMap, -} _cel_WellKnownTypeFieldLabel; - -static const char* cel_nonnull _cel_WellKnownType_LabelName(upb_Label label) { - switch (label) { - case kUpb_Label_Optional: - return "optional"; - case kUpb_Label_Required: - return "required"; - case kUpb_Label_Repeated: - return "repeated"; - default: - return "unknown"; - } -} - -CEL_ATTRIBUTE_NODISCARD -static const upb_FieldDef* cel_nullable _cel_WellKnownType_CheckField( - const upb_FieldDef* cel_nonnull field_def, uint32_t number, upb_CType type, - _cel_WellKnownTypeFieldLabel label, cel_StringView type_name, - const upb_OneofDef* cel_nullable oneof, cel_Status* cel_nonnull status) { - CEL_ASSERT(cel_Status_Ok(status)); - - if (CEL_UNLIKELY(upb_FieldDef_Number(field_def) != number)) { - cel_FailedPreconditionStatusF( - status, - "cel: well known message type field number unexpected: " - "%s: got %" PRIu32 ", want %" PRIu32, - upb_FieldDef_FullName(field_def), upb_FieldDef_Number(field_def), - number); - return cel_nullptr; - } - if (CEL_UNLIKELY(upb_FieldDef_CType(field_def) != type)) { - cel_FailedPreconditionStatusF( - status, - "cel: well known message type field type unexpected: " - "%s: got %d, want %d", - upb_FieldDef_FullName(field_def), upb_FieldDef_CType(field_def), type); - return cel_nullptr; - } - switch (label) { - case _cel_WellKnownTypeFieldLabel_kOptional: - if (CEL_UNLIKELY(upb_FieldDef_Label(field_def) != kUpb_Label_Optional)) { - cel_FailedPreconditionStatusF( - status, - "cel: well known message type field label unexpected: " - "%s: got %s, want optional", - upb_FieldDef_FullName(field_def), - _cel_WellKnownType_LabelName(upb_FieldDef_Label(field_def))); - return cel_nullptr; - } - break; - case _cel_WellKnownTypeFieldLabel_kRepeated: - if (CEL_UNLIKELY(upb_FieldDef_IsMap(field_def))) { - cel_FailedPreconditionStatusF( - status, - "cel: well known message type field label unexpected: " - "%s: got map, want repeated", - upb_FieldDef_FullName(field_def)); - return cel_nullptr; - } - if (CEL_UNLIKELY(!upb_FieldDef_IsRepeated(field_def))) { - cel_FailedPreconditionStatusF( - status, - "cel: well known message type field label unexpected: " - "%s: got %s, want repeated", - upb_FieldDef_FullName(field_def), - _cel_WellKnownType_LabelName(upb_FieldDef_Label(field_def))); - return cel_nullptr; - } - break; - case _cel_WellKnownTypeFieldLabel_kMap: - if (CEL_UNLIKELY(!upb_FieldDef_IsMap(field_def))) { - cel_FailedPreconditionStatusF( - status, - "cel: well known message type field label unexpected: " - "%s: got %s, want map", - upb_FieldDef_FullName(field_def), - _cel_WellKnownType_LabelName(upb_FieldDef_Label(field_def))); - return cel_nullptr; - } - break; - default: - CEL_UNREACHABLE(); - } - if (type == kUpb_CType_Message) { - if (CEL_UNLIKELY(!cel_StringView_Equals( - cel_StringView_From( - upb_MessageDef_FullName(upb_FieldDef_MessageSubDef(field_def))), - type_name))) { - cel_FailedPreconditionStatusF( - status, - "cel: well known message type field type name unexpected: " - "%s: got %s, want " CEL_STRINGVIEW_FMT, - upb_FieldDef_FullName(field_def), - upb_MessageDef_FullName(upb_FieldDef_MessageSubDef(field_def)), - CEL_STRINGVIEW_ARGS(type_name)); - return cel_nullptr; - } - } else if (type == kUpb_CType_Enum) { - if (CEL_UNLIKELY(!cel_StringView_Equals( - cel_StringView_From( - upb_EnumDef_FullName(upb_FieldDef_EnumSubDef(field_def))), - type_name))) { - cel_FailedPreconditionStatusF( - status, - "cel: well known message type field type name unexpected: " - "%s: got %s, want " CEL_STRINGVIEW_FMT, - upb_FieldDef_FullName(field_def), - upb_EnumDef_FullName(upb_FieldDef_EnumSubDef(field_def)), - CEL_STRINGVIEW_ARGS(type_name)); - return cel_nullptr; - } - } - const upb_OneofDef* got_oneof = upb_FieldDef_ContainingOneof(field_def); - if (CEL_UNLIKELY(got_oneof != oneof)) { - cel_FailedPreconditionStatusF( - status, - "cel: well known message type field oneof unexpected: " - "%s: got %s, want %s", - upb_FieldDef_FullName(field_def), - got_oneof != cel_nullptr ? upb_OneofDef_Name(got_oneof) : "null", - oneof != cel_nullptr ? upb_OneofDef_Name(oneof) : "null"); - return cel_nullptr; - } - return field_def; -} - -CEL_ATTRIBUTE_NODISCARD -static const upb_FieldDef* cel_nullable _cel_WellKnownType_FindField( - const upb_MessageDef* cel_nonnull def, cel_StringView name, uint32_t number, - upb_CType type, _cel_WellKnownTypeFieldLabel label, - cel_StringView type_name, const upb_OneofDef* cel_nullable oneof, - cel_Status* cel_nonnull status) { - CEL_ASSERT(cel_Status_Ok(status)); - - const upb_FieldDef* field_def = upb_MessageDef_FindFieldByNameWithSize( - def, cel_StringView_Data(name), cel_StringView_Size(name)); - if (CEL_UNLIKELY(field_def == cel_nullptr)) { - cel_NotFoundStatusF( - status, - "cel: well known message type field not found: %s." CEL_STRINGVIEW_FMT, - upb_MessageDef_FullName(def), CEL_STRINGVIEW_ARGS(name)); - return cel_nullptr; - } - return _cel_WellKnownType_CheckField(field_def, number, type, label, - type_name, oneof, status); -} - -bool cel_NullValueWellKnownType_Initialize( - cel_NullValueWellKnownType* cel_nonnull wkt, - const upb_DefPool* cel_nonnull def_pool, cel_Status* cel_nonnull status) { - CEL_ASSERT_NOT_NULL(wkt); - CEL_ASSERT_NOT_NULL(def_pool); - CEL_ASSERT_NOT_NULL(status); - - memset(wkt, 0, sizeof(*wkt)); - - if (CEL_UNLIKELY(!cel_Status_Ok(status))) { - return false; - } - - const upb_EnumDef* def = - upb_DefPool_FindEnumByName(def_pool, "google.protobuf.NullValue"); - if (CEL_UNLIKELY(def == cel_nullptr)) { - cel_NotFoundStatus( - status, - cel_StringView_From( - "cel: well known enum type not found: google.protobuf.NullValue")); - return false; - } - if (CEL_UNLIKELY(upb_EnumDef_ValueCount(def) != 1)) { - cel_FailedPreconditionStatus( - status, - cel_StringView_From("cel: well known enum type does not have exactly " - "one value: google.protobuf.NullValue")); - return false; - } - const upb_EnumValueDef* value_def = upb_EnumDef_FindValueByNumber(def, 0); - if (CEL_UNLIKELY(value_def == cel_nullptr)) { - cel_NotFoundStatus( - status, cel_StringView_From("cel: well known enum type value not found: " - "google.protobuf.NullValue.0")); - return false; - } - const char* name = upb_EnumValueDef_Name(value_def); - if (CEL_UNLIKELY(name == cel_nullptr || strcmp(name, "NULL_VALUE") != 0)) { - cel_NotFoundStatus( - status, cel_StringView_From("cel: well known enum type value not found: " - "google.protobuf.NullValue.NULL_VALUE")); - return false; - } - - wkt->def = def; - wkt->value_def = value_def; - return true; -} - -static bool _cel_WrapperWellKnownType_Initialize( - cel_BoolValueWellKnownType* cel_nonnull wkt, - const upb_DefPool* cel_nonnull def_pool, cel_StringView name, - upb_CType type, cel_Status* cel_nonnull status) { - CEL_ASSERT_NOT_NULL(wkt); - CEL_ASSERT_NOT_NULL(def_pool); - CEL_ASSERT_NOT_NULL(status); - - memset(wkt, 0, sizeof(*wkt)); - - if (CEL_UNLIKELY(!cel_Status_Ok(status))) { - return false; - } - - const upb_MessageDef* def = _cel_WellKnownType_FindMessage( - def_pool, name, /*error_if_not_found=*/true, status); - if (CEL_UNLIKELY(def == cel_nullptr)) { - return false; - } - const upb_FieldDef* value_def = _cel_WellKnownType_FindField( - def, cel_StringView_From("value"), UINT32_C(1), type, - _cel_WellKnownTypeFieldLabel_kOptional, cel_StringView_From(""), - /*oneof=*/cel_nullptr, status); - if (CEL_UNLIKELY(value_def == cel_nullptr)) { - return false; - } - - wkt->def = def; - wkt->value_def = value_def; - return true; -} - -bool cel_BoolValueWellKnownType_Initialize( - cel_BoolValueWellKnownType* cel_nonnull wkt, - const upb_DefPool* cel_nonnull def_pool, cel_Status* cel_nonnull status) { - return _cel_WrapperWellKnownType_Initialize( - wkt, def_pool, cel_StringView_From("google.protobuf.BoolValue"), - kUpb_CType_Bool, status); -} - -bool cel_Int32ValueWellKnownType_Initialize( - cel_Int32ValueWellKnownType* cel_nonnull wkt, - const upb_DefPool* cel_nonnull def_pool, cel_Status* cel_nonnull status) { - return _cel_WrapperWellKnownType_Initialize( - wkt, def_pool, cel_StringView_From("google.protobuf.Int32Value"), - kUpb_CType_Int32, status); -} - -bool cel_UInt32ValueWellKnownType_Initialize( - cel_UInt32ValueWellKnownType* cel_nonnull wkt, - const upb_DefPool* cel_nonnull def_pool, cel_Status* cel_nonnull status) { - return _cel_WrapperWellKnownType_Initialize( - wkt, def_pool, cel_StringView_From("google.protobuf.UInt32Value"), - kUpb_CType_UInt32, status); -} - -bool cel_Int64ValueWellKnownType_Initialize( - cel_Int64ValueWellKnownType* cel_nonnull wkt, - const upb_DefPool* cel_nonnull def_pool, cel_Status* cel_nonnull status) { - return _cel_WrapperWellKnownType_Initialize( - wkt, def_pool, cel_StringView_From("google.protobuf.Int64Value"), - kUpb_CType_Int64, status); -} - -bool cel_UInt64ValueWellKnownType_Initialize( - cel_UInt64ValueWellKnownType* cel_nonnull wkt, - const upb_DefPool* cel_nonnull def_pool, cel_Status* cel_nonnull status) { - return _cel_WrapperWellKnownType_Initialize( - wkt, def_pool, cel_StringView_From("google.protobuf.UInt64Value"), - kUpb_CType_UInt64, status); -} - -bool cel_FloatValueWellKnownType_Initialize( - cel_FloatValueWellKnownType* cel_nonnull wkt, - const upb_DefPool* cel_nonnull def_pool, cel_Status* cel_nonnull status) { - return _cel_WrapperWellKnownType_Initialize( - wkt, def_pool, cel_StringView_From("google.protobuf.FloatValue"), - kUpb_CType_Float, status); -} - -bool cel_DoubleValueWellKnownType_Initialize( - cel_DoubleValueWellKnownType* cel_nonnull wkt, - const upb_DefPool* cel_nonnull def_pool, cel_Status* cel_nonnull status) { - return _cel_WrapperWellKnownType_Initialize( - wkt, def_pool, cel_StringView_From("google.protobuf.DoubleValue"), - kUpb_CType_Double, status); -} - -bool cel_BytesValueWellKnownType_Initialize( - cel_BytesValueWellKnownType* cel_nonnull wkt, - const upb_DefPool* cel_nonnull def_pool, cel_Status* cel_nonnull status) { - return _cel_WrapperWellKnownType_Initialize( - wkt, def_pool, cel_StringView_From("google.protobuf.BytesValue"), - kUpb_CType_Bytes, status); -} - -bool cel_StringValueWellKnownType_Initialize( - cel_StringValueWellKnownType* cel_nonnull wkt, - const upb_DefPool* cel_nonnull def_pool, cel_Status* cel_nonnull status) { - return _cel_WrapperWellKnownType_Initialize( - wkt, def_pool, cel_StringView_From("google.protobuf.StringValue"), - kUpb_CType_String, status); -} - -CEL_ATTRIBUTE_NODISCARD -static bool _cel_TemporalWellKnownType_Initialize( - cel_TemporalWellKnownType* cel_nonnull wkt, - const upb_DefPool* cel_nonnull def_pool, cel_StringView name, - cel_Status* cel_nonnull status) { - CEL_ASSERT_NOT_NULL(wkt); - CEL_ASSERT_NOT_NULL(def_pool); - CEL_ASSERT_NOT_NULL(status); - - memset(wkt, 0, sizeof(*wkt)); - - if (CEL_UNLIKELY(!cel_Status_Ok(status))) { - return false; - } - - const upb_MessageDef* def = _cel_WellKnownType_FindMessage( - def_pool, name, /*error_if_not_found=*/true, status); - if (CEL_UNLIKELY(def == cel_nullptr)) { - return false; - } - const upb_FieldDef* seconds_def = _cel_WellKnownType_FindField( - def, cel_StringView_From("seconds"), UINT32_C(1), kUpb_CType_Int64, - _cel_WellKnownTypeFieldLabel_kOptional, cel_StringView_From(""), - /*oneof=*/cel_nullptr, status); - if (CEL_UNLIKELY(seconds_def == cel_nullptr)) { - return false; - } - const upb_FieldDef* nanos_def = _cel_WellKnownType_FindField( - def, cel_StringView_From("nanos"), UINT32_C(2), kUpb_CType_Int32, - _cel_WellKnownTypeFieldLabel_kOptional, cel_StringView_From(""), - /*oneof=*/cel_nullptr, status); - if (CEL_UNLIKELY(nanos_def == cel_nullptr)) { - return false; - } - - wkt->def = def; - wkt->seconds_def = seconds_def; - wkt->nanos_def = nanos_def; - return true; -} - -bool cel_DurationWellKnownType_Initialize( - cel_DurationWellKnownType* cel_nonnull wkt, - const upb_DefPool* cel_nonnull def_pool, cel_Status* cel_nonnull status) { - return _cel_TemporalWellKnownType_Initialize( - wkt, def_pool, cel_StringView_From("google.protobuf.Duration"), status); -} - -bool cel_TimestampWellKnownType_Initialize( - cel_TimestampWellKnownType* cel_nonnull wkt, - const upb_DefPool* cel_nonnull def_pool, cel_Status* cel_nonnull status) { - return _cel_TemporalWellKnownType_Initialize( - wkt, def_pool, cel_StringView_From("google.protobuf.Timestamp"), status); -} - -bool cel_AnyWellKnownType_Initialize(cel_AnyWellKnownType* cel_nonnull wkt, - const upb_DefPool* cel_nonnull def_pool, - cel_Status* cel_nonnull status) { - CEL_ASSERT_NOT_NULL(wkt); - CEL_ASSERT_NOT_NULL(def_pool); - CEL_ASSERT_NOT_NULL(status); - - memset(wkt, 0, sizeof(*wkt)); - - if (CEL_UNLIKELY(!cel_Status_Ok(status))) { - return false; - } - - const upb_MessageDef* def = _cel_WellKnownType_FindMessage( - def_pool, cel_StringView_From("google.protobuf.Any"), - /*error_if_not_found=*/true, status); - if (CEL_UNLIKELY(def == cel_nullptr)) { - return false; - } - const upb_FieldDef* type_url_def = _cel_WellKnownType_FindField( - def, cel_StringView_From("type_url"), UINT32_C(1), kUpb_CType_String, - _cel_WellKnownTypeFieldLabel_kOptional, cel_StringView_From(""), - /*oneof=*/cel_nullptr, status); - if (CEL_UNLIKELY(type_url_def == cel_nullptr)) { - return false; - } - const upb_FieldDef* value_def = _cel_WellKnownType_FindField( - def, cel_StringView_From("value"), UINT32_C(2), kUpb_CType_Bytes, - _cel_WellKnownTypeFieldLabel_kOptional, cel_StringView_From(""), - /*oneof=*/cel_nullptr, status); - if (CEL_UNLIKELY(value_def == cel_nullptr)) { - return false; - } - - wkt->def = def; - wkt->type_url_def = type_url_def; - wkt->value_def = value_def; - return true; -} - -bool cel_ValueWellKnownType_Initialize(cel_ValueWellKnownType* cel_nonnull wkt, - const upb_DefPool* cel_nonnull def_pool, - cel_Status* cel_nonnull status) { - CEL_ASSERT_NOT_NULL(wkt); - CEL_ASSERT_NOT_NULL(def_pool); - CEL_ASSERT_NOT_NULL(status); - - memset(wkt, 0, sizeof(*wkt)); - - if (CEL_UNLIKELY(!cel_Status_Ok(status))) { - return false; - } - - const upb_MessageDef* def = _cel_WellKnownType_FindMessage( - def_pool, cel_StringView_From("google.protobuf.Value"), - /*error_if_not_found=*/true, status); - if (CEL_UNLIKELY(def == cel_nullptr)) { - return false; - } - const upb_OneofDef* kind_def = upb_MessageDef_FindOneofByName(def, "kind"); - if (CEL_UNLIKELY(kind_def == cel_nullptr)) { - cel_NotFoundStatusF(status, - "cel: well known message type oneof not found: %s.kind", - upb_MessageDef_FullName(def)); - return false; - } - if (CEL_UNLIKELY(upb_OneofDef_FieldCount(kind_def) != 6)) { - cel_FailedPreconditionStatusF( - status, - "cel: well known message type oneof does not have " - "exactly 6 fields: %s %d", - upb_OneofDef_FullName(kind_def), upb_OneofDef_FieldCount(kind_def)); - return false; - } - const upb_FieldDef* null_value_def = _cel_WellKnownType_FindField( - def, cel_StringView_From("null_value"), UINT32_C(1), kUpb_CType_Enum, - _cel_WellKnownTypeFieldLabel_kOptional, - cel_StringView_From("google.protobuf.NullValue"), kind_def, status); - if (CEL_UNLIKELY(null_value_def == cel_nullptr)) { - return false; - } - const upb_FieldDef* number_value_def = _cel_WellKnownType_FindField( - def, cel_StringView_From("number_value"), UINT32_C(2), kUpb_CType_Double, - _cel_WellKnownTypeFieldLabel_kOptional, cel_StringView_From(""), kind_def, - status); - if (CEL_UNLIKELY(number_value_def == cel_nullptr)) { - return false; - } - const upb_FieldDef* string_value_def = _cel_WellKnownType_FindField( - def, cel_StringView_From("string_value"), UINT32_C(3), kUpb_CType_String, - _cel_WellKnownTypeFieldLabel_kOptional, cel_StringView_From(""), kind_def, - status); - if (CEL_UNLIKELY(string_value_def == cel_nullptr)) { - return false; - } - const upb_FieldDef* bool_value_def = _cel_WellKnownType_FindField( - def, cel_StringView_From("bool_value"), UINT32_C(4), kUpb_CType_Bool, - _cel_WellKnownTypeFieldLabel_kOptional, cel_StringView_From(""), kind_def, - status); - if (CEL_UNLIKELY(bool_value_def == cel_nullptr)) { - return false; - } - const upb_FieldDef* struct_value_def = _cel_WellKnownType_FindField( - def, cel_StringView_From("struct_value"), UINT32_C(5), kUpb_CType_Message, - _cel_WellKnownTypeFieldLabel_kOptional, - cel_StringView_From("google.protobuf.Struct"), kind_def, status); - if (CEL_UNLIKELY(struct_value_def == cel_nullptr)) { - return false; - } - const upb_FieldDef* list_value_def = _cel_WellKnownType_FindField( - def, cel_StringView_From("list_value"), UINT32_C(6), kUpb_CType_Message, - _cel_WellKnownTypeFieldLabel_kOptional, - cel_StringView_From("google.protobuf.ListValue"), kind_def, status); - if (CEL_UNLIKELY(list_value_def == cel_nullptr)) { - return false; - } - - wkt->def = def; - wkt->kind_def = kind_def; - wkt->null_value_def = null_value_def; - wkt->number_value_def = number_value_def; - wkt->string_value_def = string_value_def; - wkt->bool_value_def = bool_value_def; - wkt->struct_value_def = struct_value_def; - wkt->list_value_def = list_value_def; - return true; -} - -bool cel_StructWellKnownType_Initialize( - cel_StructWellKnownType* cel_nonnull wkt, - const upb_DefPool* cel_nonnull def_pool, cel_Status* cel_nonnull status) { - CEL_ASSERT_NOT_NULL(wkt); - CEL_ASSERT_NOT_NULL(def_pool); - CEL_ASSERT_NOT_NULL(status); - - memset(wkt, 0, sizeof(*wkt)); - - if (CEL_UNLIKELY(!cel_Status_Ok(status))) { - return false; - } - - const upb_MessageDef* def = _cel_WellKnownType_FindMessage( - def_pool, cel_StringView_From("google.protobuf.Struct"), - /*error_if_not_found=*/true, status); - if (CEL_UNLIKELY(def == cel_nullptr)) { - return false; - } - const upb_FieldDef* fields_def = _cel_WellKnownType_FindField( - def, cel_StringView_From("fields"), UINT32_C(1), kUpb_CType_Message, - _cel_WellKnownTypeFieldLabel_kMap, - cel_StringView_From("google.protobuf.Struct.FieldsEntry"), - /*oneof=*/cel_nullptr, status); - if (CEL_UNLIKELY(fields_def == cel_nullptr)) { - return false; - } - const upb_MessageDef* fields_entry_def = - upb_FieldDef_MessageSubDef(fields_def); - const upb_FieldDef* fields_key_def = _cel_WellKnownType_CheckField( - upb_MessageDef_FindFieldByNumber(fields_entry_def, - kUpb_MapEntry_KeyFieldNumber), - kUpb_MapEntry_KeyFieldNumber, kUpb_CType_String, - _cel_WellKnownTypeFieldLabel_kOptional, cel_StringView_From(""), - /*oneof=*/cel_nullptr, status); - if (fields_key_def == cel_nullptr) { - return false; - } - const upb_FieldDef* fields_value_def = _cel_WellKnownType_CheckField( - upb_MessageDef_FindFieldByNumber(fields_entry_def, - kUpb_MapEntry_ValueFieldNumber), - kUpb_MapEntry_ValueFieldNumber, kUpb_CType_Message, - _cel_WellKnownTypeFieldLabel_kOptional, - cel_StringView_From("google.protobuf.Value"), - /*oneof=*/cel_nullptr, status); - if (fields_value_def == cel_nullptr) { - return false; - } - - wkt->def = def; - wkt->fields_def = fields_def; - wkt->fields_key_def = fields_key_def; - wkt->fields_value_def = fields_value_def; - return true; -} - -bool cel_ListValueWellKnownType_Initialize( - cel_ListValueWellKnownType* cel_nonnull wkt, - const upb_DefPool* cel_nonnull def_pool, cel_Status* cel_nonnull status) { - CEL_ASSERT_NOT_NULL(wkt); - CEL_ASSERT_NOT_NULL(def_pool); - CEL_ASSERT_NOT_NULL(status); - - memset(wkt, 0, sizeof(*wkt)); - - if (CEL_UNLIKELY(!cel_Status_Ok(status))) { - return false; - } - - const upb_MessageDef* def = _cel_WellKnownType_FindMessage( - def_pool, cel_StringView_From("google.protobuf.ListValue"), - /*error_if_not_found=*/true, status); - if (CEL_UNLIKELY(def == cel_nullptr)) { - return false; - } - const upb_FieldDef* values_def = _cel_WellKnownType_FindField( - def, cel_StringView_From("values"), UINT32_C(1), kUpb_CType_Message, - _cel_WellKnownTypeFieldLabel_kRepeated, - cel_StringView_From("google.protobuf.Value"), - /*oneof=*/cel_nullptr, status); - if (CEL_UNLIKELY(values_def == cel_nullptr)) { - return false; - } - - wkt->def = def; - wkt->values_def = values_def; - return true; -} - -bool cel_FieldMaskWellKnownType_Initialize( - cel_FieldMaskWellKnownType* cel_nonnull wkt, - const upb_DefPool* cel_nonnull def_pool, cel_Status* cel_nonnull status) { - CEL_ASSERT_NOT_NULL(wkt); - CEL_ASSERT_NOT_NULL(def_pool); - CEL_ASSERT_NOT_NULL(status); - - memset(wkt, 0, sizeof(*wkt)); - - if (CEL_UNLIKELY(!cel_Status_Ok(status))) { - return false; - } - - const upb_MessageDef* def = _cel_WellKnownType_FindMessage( - def_pool, cel_StringView_From("google.protobuf.FieldMask"), - /*error_if_not_found=*/false, status); - if (CEL_UNLIKELY(def == cel_nullptr)) { - return false; - } - const upb_FieldDef* paths_def = _cel_WellKnownType_FindField( - def, cel_StringView_From("paths"), UINT32_C(1), kUpb_CType_String, - _cel_WellKnownTypeFieldLabel_kRepeated, cel_StringView_From(""), - /*oneof=*/cel_nullptr, status); - if (CEL_UNLIKELY(paths_def == cel_nullptr)) { - return false; - } - - wkt->def = def; - wkt->paths_def = paths_def; - return true; -} - -bool cel_WellKnownTypes_Initialize(cel_WellKnownTypes* cel_nonnull wkts, - const upb_DefPool* cel_nonnull def_pool, - cel_Status* cel_nonnull status) { - CEL_ASSERT_NOT_NULL(wkts); - CEL_ASSERT_NOT_NULL(def_pool); - CEL_ASSERT_NOT_NULL(status); - - memset(wkts, 0, sizeof(*wkts)); - - if (CEL_UNLIKELY(!cel_Status_Ok(status))) { - return false; - } - - if (!cel_NullValueWellKnownType_Initialize(&wkts->null_value, def_pool, - status)) { - return false; - } - if (!cel_BoolValueWellKnownType_Initialize(&wkts->bool_value, def_pool, - status)) { - return false; - } - if (!cel_Int32ValueWellKnownType_Initialize(&wkts->int32_value, def_pool, - status)) { - return false; - } - if (!cel_UInt32ValueWellKnownType_Initialize(&wkts->uint32_value, def_pool, - status)) { - return false; - } - if (!cel_Int64ValueWellKnownType_Initialize(&wkts->int64_value, def_pool, - status)) { - return false; - } - if (!cel_UInt64ValueWellKnownType_Initialize(&wkts->uint64_value, def_pool, - status)) { - return false; - } - if (!cel_FloatValueWellKnownType_Initialize(&wkts->float_value, def_pool, - status)) { - return false; - } - if (!cel_DoubleValueWellKnownType_Initialize(&wkts->double_value, def_pool, - status)) { - return false; - } - if (!cel_BytesValueWellKnownType_Initialize(&wkts->bytes_value, def_pool, - status)) { - return false; - } - if (!cel_StringValueWellKnownType_Initialize(&wkts->string_value, def_pool, - status)) { - return false; - } - if (!cel_DurationWellKnownType_Initialize(&wkts->duration, def_pool, - status)) { - return false; - } - if (!cel_TimestampWellKnownType_Initialize(&wkts->timestamp, def_pool, - status)) { - return false; - } - if (!cel_AnyWellKnownType_Initialize(&wkts->any, def_pool, status)) { - return false; - } - if (!cel_ValueWellKnownType_Initialize(&wkts->value, def_pool, status)) { - return false; - } - if (!cel_StructWellKnownType_Initialize(&wkts->struct_value, def_pool, - status)) { - return false; - } - if (!cel_ListValueWellKnownType_Initialize(&wkts->list_value, def_pool, - status)) { - return false; - } - if (!cel_FieldMaskWellKnownType_Initialize(&wkts->field_mask, def_pool, - status) && - !cel_Status_Ok(status)) { - return false; - } - return true; -}