Skip to content

Commit

Permalink
Refactor value deserialization to be handle agnostic
Browse files Browse the repository at this point in the history
PiperOrigin-RevId: 589881956
  • Loading branch information
jcking authored and copybara-github committed Dec 11, 2023
1 parent d3f0ad3 commit 4921986
Show file tree
Hide file tree
Showing 9 changed files with 443 additions and 228 deletions.
1 change: 1 addition & 0 deletions base/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,7 @@ cc_library(
"//common:memory",
"//common:native_type",
"//internal:casts",
"//internal:deserialize",
"//internal:no_destructor",
"//internal:number",
"//internal:overloaded",
Expand Down
26 changes: 4 additions & 22 deletions base/types/duration_type.cc
Original file line number Diff line number Diff line change
Expand Up @@ -18,16 +18,14 @@
#include "absl/time/time.h"
#include "base/value_factory.h"
#include "base/values/duration_value.h"
#include "internal/proto_wire.h"
#include "internal/deserialize.h"
#include "internal/status_macros.h"

namespace cel {

namespace {

using internal::MakeProtoWireTag;
using internal::ProtoWireDecoder;
using internal::ProtoWireType;
using internal::DeserializeDuration;

} // namespace

Expand All @@ -36,24 +34,8 @@ CEL_INTERNAL_TYPE_IMPL(DurationType);
absl::StatusOr<Handle<DurationValue>> DurationType::NewValueFromAny(
ValueFactory& value_factory, const absl::Cord& value) const {
// google.protobuf.Duration.
int64_t seconds = 0;
int32_t nanos = 0;
ProtoWireDecoder decoder("google.protobuf.Duration", value);
while (decoder.HasNext()) {
CEL_ASSIGN_OR_RETURN(auto tag, decoder.ReadTag());
if (tag == MakeProtoWireTag(1, ProtoWireType::kVarint)) {
CEL_ASSIGN_OR_RETURN(seconds, decoder.ReadVarint<int64_t>());
continue;
}
if (tag == MakeProtoWireTag(2, ProtoWireType::kVarint)) {
CEL_ASSIGN_OR_RETURN(nanos, decoder.ReadVarint<int32_t>());
continue;
}
CEL_RETURN_IF_ERROR(decoder.SkipLengthValue());
}
decoder.EnsureFullyDecoded();
return value_factory.CreateDurationValue(absl::Seconds(seconds) +
absl::Nanoseconds(nanos));
CEL_ASSIGN_OR_RETURN(auto deserialized_value, DeserializeDuration(value));
return value_factory.CreateDurationValue(deserialized_value);
}

} // namespace cel
56 changes: 6 additions & 50 deletions base/types/dyn_type.cc
Original file line number Diff line number Diff line change
Expand Up @@ -14,20 +14,20 @@

#include "base/types/dyn_type.h"

#include <utility>

#include "absl/strings/cord.h"
#include "absl/strings/string_view.h"
#include "absl/types/span.h"
#include "base/value_factory.h"
#include "internal/proto_wire.h"
#include "internal/deserialize.h"
#include "internal/status_macros.h"

namespace cel {

namespace {

using internal::MakeProtoWireTag;
using internal::ProtoWireDecoder;
using internal::ProtoWireType;
using internal::DeserializeValue;

} // namespace

Expand All @@ -36,52 +36,8 @@ CEL_INTERNAL_TYPE_IMPL(DynType);
absl::StatusOr<Handle<Value>> DynType::NewValueFromAny(
ValueFactory& value_factory, const absl::Cord& value) const {
// google.protobuf.Value.
Handle<Value> primitive = value_factory.GetNullValue();
ProtoWireDecoder decoder("google.protobuf.Value", value);
while (decoder.HasNext()) {
CEL_ASSIGN_OR_RETURN(auto tag, decoder.ReadTag());
if (tag == MakeProtoWireTag(1, ProtoWireType::kVarint)) {
CEL_ASSIGN_OR_RETURN(auto unused, decoder.ReadVarint<bool>());
static_cast<void>(unused);
primitive = value_factory.GetNullValue();
continue;
}
if (tag == MakeProtoWireTag(2, ProtoWireType::kFixed64)) {
CEL_ASSIGN_OR_RETURN(auto number_value, decoder.ReadFixed64<double>());
primitive = value_factory.CreateDoubleValue(number_value);
continue;
}
if (tag == MakeProtoWireTag(3, ProtoWireType::kLengthDelimited)) {
CEL_ASSIGN_OR_RETURN(auto string_value, decoder.ReadLengthDelimited());
CEL_ASSIGN_OR_RETURN(primitive,
value_factory.CreateStringValue(string_value));
continue;
}
if (tag == MakeProtoWireTag(4, ProtoWireType::kVarint)) {
CEL_ASSIGN_OR_RETURN(auto bool_value, decoder.ReadVarint<bool>());
primitive = value_factory.CreateBoolValue(bool_value);
continue;
}
if (tag == MakeProtoWireTag(5, ProtoWireType::kLengthDelimited)) {
CEL_ASSIGN_OR_RETURN(auto struct_value, decoder.ReadLengthDelimited());
CEL_ASSIGN_OR_RETURN(
primitive,
value_factory.type_factory().GetJsonMapType()->NewValueFromAny(
value_factory, struct_value));
continue;
}
if (tag == MakeProtoWireTag(6, ProtoWireType::kLengthDelimited)) {
CEL_ASSIGN_OR_RETURN(auto list_value, decoder.ReadLengthDelimited());
CEL_ASSIGN_OR_RETURN(
primitive,
value_factory.type_factory().GetJsonListType()->NewValueFromAny(
value_factory, list_value));
continue;
}
CEL_RETURN_IF_ERROR(decoder.SkipLengthValue());
}
decoder.EnsureFullyDecoded();
return primitive;
CEL_ASSIGN_OR_RETURN(auto deserialized_value, DeserializeValue(value));
return value_factory.CreateValueFromJson(std::move(deserialized_value));
}

absl::Span<const absl::string_view> DynType::aliases() const {
Expand Down
52 changes: 4 additions & 48 deletions base/types/map_type.cc
Original file line number Diff line number Diff line change
Expand Up @@ -37,16 +37,14 @@
#include "base/values/map_value.h"
#include "base/values/map_value_builder.h"
#include "base/values/string_value.h"
#include "internal/proto_wire.h"
#include "internal/deserialize.h"
#include "internal/status_macros.h"

namespace cel {

namespace {

using internal::MakeProtoWireTag;
using internal::ProtoWireDecoder;
using internal::ProtoWireType;
using internal::DeserializeStruct;

} // namespace

Expand Down Expand Up @@ -77,50 +75,8 @@ absl::StatusOr<Handle<MapValue>> MapType::NewValueFromAny(
absl::StrCat("google.protobuf.Any cannot be deserialized as ", name()));
}
// google.protobuf.Struct.
CEL_ASSIGN_OR_RETURN(auto builder, NewValueBuilder(value_factory));
ProtoWireDecoder decoder("google.protobuf.Struct", value);
while (decoder.HasNext()) {
CEL_ASSIGN_OR_RETURN(auto tag, decoder.ReadTag());
if (tag == MakeProtoWireTag(1, ProtoWireType::kLengthDelimited)) {
// fields
CEL_ASSIGN_OR_RETURN(auto fields_value, decoder.ReadLengthDelimited());
Handle<StringValue> field_name = value_factory.GetStringValue();
Handle<Value> field_value = value_factory.GetNullValue();
ProtoWireDecoder fields_decoder("google.protobuf.Struct.FieldsEntry",
fields_value);
while (fields_decoder.HasNext()) {
CEL_ASSIGN_OR_RETURN(auto fields_tag, fields_decoder.ReadTag());
if (fields_tag ==
MakeProtoWireTag(1, ProtoWireType::kLengthDelimited)) {
// key
CEL_ASSIGN_OR_RETURN(auto field_name_value,
fields_decoder.ReadLengthDelimited());
CEL_ASSIGN_OR_RETURN(field_name, value_factory.CreateStringValue(
std::move(field_name_value)));
continue;
}
if (fields_tag ==
MakeProtoWireTag(2, ProtoWireType::kLengthDelimited)) {
// value
CEL_ASSIGN_OR_RETURN(auto field_value_value,
fields_decoder.ReadLengthDelimited());
CEL_ASSIGN_OR_RETURN(
field_value,
value_factory.type_factory().GetJsonValueType()->NewValueFromAny(
value_factory, field_value_value));
continue;
}
CEL_RETURN_IF_ERROR(fields_decoder.SkipLengthValue());
}
fields_decoder.EnsureFullyDecoded();
CEL_RETURN_IF_ERROR(
builder->Put(std::move(field_name), std::move(field_value)));
continue;
}
CEL_RETURN_IF_ERROR(decoder.SkipLengthValue());
}
decoder.EnsureFullyDecoded();
return std::move(*builder).Build();
CEL_ASSIGN_OR_RETURN(auto deserialized_value, DeserializeStruct(value));
return value_factory.CreateMapValueFromJson(std::move(deserialized_value));
}

absl::Span<const absl::string_view> MapType::aliases() const {
Expand Down
26 changes: 4 additions & 22 deletions base/types/timestamp_type.cc
Original file line number Diff line number Diff line change
Expand Up @@ -18,16 +18,14 @@
#include "absl/time/time.h"
#include "base/value_factory.h"
#include "base/values/timestamp_value.h"
#include "internal/proto_wire.h"
#include "internal/deserialize.h"
#include "internal/status_macros.h"

namespace cel {

namespace {

using internal::MakeProtoWireTag;
using internal::ProtoWireDecoder;
using internal::ProtoWireType;
using internal::DeserializeTimestamp;

} // namespace

Expand All @@ -36,24 +34,8 @@ CEL_INTERNAL_TYPE_IMPL(TimestampType);
absl::StatusOr<Handle<TimestampValue>> TimestampType::NewValueFromAny(
ValueFactory& value_factory, const absl::Cord& value) const {
// google.protobuf.Timestamp.
int64_t seconds = 0;
int32_t nanos = 0;
ProtoWireDecoder decoder("google.protobuf.Timestamp", value);
while (decoder.HasNext()) {
CEL_ASSIGN_OR_RETURN(auto tag, decoder.ReadTag());
if (tag == MakeProtoWireTag(1, ProtoWireType::kVarint)) {
CEL_ASSIGN_OR_RETURN(seconds, decoder.ReadVarint<int64_t>());
continue;
}
if (tag == MakeProtoWireTag(2, ProtoWireType::kVarint)) {
CEL_ASSIGN_OR_RETURN(nanos, decoder.ReadVarint<int32_t>());
continue;
}
CEL_RETURN_IF_ERROR(decoder.SkipLengthValue());
}
decoder.EnsureFullyDecoded();
return value_factory.CreateTimestampValue(
absl::UnixEpoch() + absl::Seconds(seconds) + absl::Nanoseconds(nanos));
CEL_ASSIGN_OR_RETURN(auto deserialized_value, DeserializeTimestamp(value));
return value_factory.CreateTimestampValue(deserialized_value);
}

} // namespace cel
Loading

0 comments on commit 4921986

Please sign in to comment.