Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 9 additions & 6 deletions cel-c/internal/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -659,6 +659,12 @@ cc_test(
deps = [
":config",
":value",
"@googletest//:gtest_main",
"@abseil-cpp//absl/cleanup",
"@abseil-cpp//absl/container:flat_hash_map",
"@abseil-cpp//absl/log:absl_check",
"@abseil-cpp//absl/log:die_if_null",
"@abseil-cpp//absl/strings:string_view",
"//cel-c:alloc",
"//cel-c:arena",
"//cel-c:ast",
Expand All @@ -677,15 +683,12 @@ cc_test(
"//cel-c/internal/testing:compiler",
"//cel-c/internal/testing:def_pool",
"//cel-c/internal/testing:parser",
"@abseil-cpp//absl/cleanup",
"@abseil-cpp//absl/container:flat_hash_map",
"@abseil-cpp//absl/log:absl_check",
"@abseil-cpp//absl/log:die_if_null",
"@abseil-cpp//absl/strings:string_view",
"@cel-cpp//internal:testing_descriptor_pool",
"@cel-cpp//internal:testing_message_factory",
"@googletest//:gtest_main",
"@protobuf",
# Embeds the full IANA time zone database so that `absl::LoadTimeZone`
# works on platforms without a system zoneinfo database (e.g. Windows).
"//third_party/tz:zoneinfo_embedded",
"@protobuf//upb/message",
"@protobuf//upb/reflection",
"@protobuf//upb/wire",
Expand Down
68 changes: 58 additions & 10 deletions cel-c/internal/runtime/interpretable.cc
Original file line number Diff line number Diff line change
Expand Up @@ -326,6 +326,19 @@ _cel_Interpretable_NewTimestampOverflowError(
return error;
}

CEL_ATTRIBUTE_NODISCARD
static CEL_INLINE cel_Error* cel_nonnull
_cel_Interpretable_NewInvalidTimeZoneError(
_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: invalid time zone"));
cel_Error_SetCanonicalCode(error, cel_ErrorCode_kInvalidArgument);
return error;
}

CEL_ATTRIBUTE_NODISCARD
static CEL_INLINE cel_Error* cel_nonnull
_cel_Interpretable_NewDuplicateKeyError(
Expand Down Expand Up @@ -2817,39 +2830,74 @@ static inline int64_t _cel_Interpretable_CivilTimeComponent(
//
// (google.protobuf.Duration) -> int
// (google.protobuf.Timestamp) -> int
// (google.protobuf.Timestamp, string) -> int
//
// Timestamps are broken down in UTC.
// For timestamps, the optional string is the time zone, otherwise UTC is used.
static inline void _cel_Interpretable_CallTimeAccessor(
_cel_Interpretable* cel_nonnull interp,
const _cel_InstrData* cel_nonnull instr, _cel_TimeAccessor accessor) {
CEL_ASSERT_NOT_NULL(interp);
CEL_ASSERT_NOT_NULL(instr);
CEL_ASSERT(instr->call.args == 1);
CEL_ASSERT(instr->call.args == 1 || instr->call.args == 2);

cel_Value* const top =
_cel_Interpretable_TopN(interp, instr, instr->call.args);
cel_Value* const tz = instr->call.args == 2 ? top + 1 : cel_nullptr;

cel_Value* const top = _cel_Interpretable_Top(interp, instr);
switch (cel_Value_Kind(top)) {
case cel_ValueKind_kError:
break;
case cel_ValueKind_kDuration:
if (tz != cel_nullptr) {
// There is no time zone overload for durations.
if (cel_Value_IsError(tz)) {
*top = *tz;
} else {
cel_Value_SetError(top,
_cel_Interpretable_NewNoSuchOverloadError(interp));
}
break;
}
cel_Value_SetInt(top, _cel_Interpretable_DurationComponent(
cel_Value_GetDuration(top), accessor));
break;
case cel_ValueKind_kTimestamp: {
cel_StringView tz_name = cel_StringView_From("");
if (tz != cel_nullptr) {
if (cel_Value_IsError(tz)) {
*top = *tz;
break;
}
if (cel_Value_Kind(tz) != cel_ValueKind_kString) {
cel_Value_SetError(top,
_cel_Interpretable_NewNoSuchOverloadError(interp));
break;
}
tz_name = cel_Value_GetString(tz);
}
_cel_CivilTime civil_time;
if (CEL_UNLIKELY(!_cel_Timestamp_ToCivilTime(cel_Value_GetTimestamp(top),
cel_StringView_From(""),
&civil_time))) {
// An empty time zone means UTC, which is always valid.
CEL_UNREACHABLE();
if (!_cel_Timestamp_ToCivilTime(cel_Value_GetTimestamp(top), tz_name,
&civil_time)) {
cel_Value_SetError(top,
_cel_Interpretable_NewInvalidTimeZoneError(interp));
break;
}
cel_Value_SetInt(
top, _cel_Interpretable_CivilTimeComponent(&civil_time, accessor));
} break;
default:
cel_Value_SetError(top,
_cel_Interpretable_NewNoSuchOverloadError(interp));
if (tz != cel_nullptr && cel_Value_IsError(tz)) {
*top = *tz;
} else {
cel_Value_SetError(top,
_cel_Interpretable_NewNoSuchOverloadError(interp));
}
break;
}

if (tz != cel_nullptr) {
_cel_Interpretable_Pop(interp, instr);
}
}

static inline void _cel_Interpretable_Index(
Expand Down
5 changes: 3 additions & 2 deletions cel-c/internal/runtime/interpreter.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1565,7 +1565,8 @@ static void _cel_Interpreter_PreVisitCallArgExpr(

// Returns the instruction kind for the duration/timestamp accessor `fn_name`,
// or `_cel_InstrKind_kUnreachable` if `fn_name` is not an accessor. Accessors
// accept (google.protobuf.Duration) or (google.protobuf.Timestamp).
// accept (google.protobuf.Duration), (google.protobuf.Timestamp) or
// (google.protobuf.Timestamp, string).
CEL_ATTRIBUTE_NODISCARD
static _cel_InstrKind _cel_Interpreter_TimeAccessorKind(
cel_StringView fn_name) {
Expand Down Expand Up @@ -1645,7 +1646,7 @@ static void _cel_Interpreter_PostVisitCallExpr(
}
}

if (!found && instr->data.call.args == 1) {
if (!found && (instr->data.call.args == 1 || instr->data.call.args == 2)) {
_cel_InstrKind kind = _cel_Interpreter_TimeAccessorKind(fn_name);
if (kind != _cel_InstrKind_kUnreachable) {
instr->kind = kind;
Expand Down
Loading
Loading