Roll inspector_protocol to 5221cbfa7f940d56ae8b79bf34c446a56781dd56
Change-Id: I4da78ec0f309c72007ee30336d77a77205f3e3fd Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3406597 Auto-Submit: Andrey Kosyakov <caseq@chromium.org> Reviewed-by: Yang Guo <yangguo@chromium.org> Commit-Queue: Yang Guo <yangguo@chromium.org> Cr-Commit-Position: refs/heads/main@{#78729}
This commit is contained in:
parent
49fd384551
commit
21e5104388
@ -238,13 +238,3 @@ std::string String16::utf8() const {
|
||||
}
|
||||
|
||||
} // namespace v8_inspector
|
||||
|
||||
namespace v8_crdtp {
|
||||
void SerializerTraits<v8_inspector::String16>::Serialize(
|
||||
const v8_inspector::String16& str, std::vector<uint8_t>* out) {
|
||||
cbor::EncodeFromUTF16(
|
||||
span<uint16_t>(reinterpret_cast<const uint16_t*>(str.characters16()),
|
||||
str.length()),
|
||||
out);
|
||||
}
|
||||
} // namespace v8_crdtp
|
||||
|
@ -6,13 +6,13 @@
|
||||
#define V8_INSPECTOR_STRING_16_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <cctype>
|
||||
#include <climits>
|
||||
#include <cstring>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "../../third_party/inspector_protocol/crdtp/serializer_traits.h"
|
||||
#include "src/base/compiler-specific.h"
|
||||
|
||||
namespace v8_inspector {
|
||||
@ -168,13 +168,4 @@ struct hash<v8_inspector::String16> {
|
||||
|
||||
#endif // !defined(__APPLE__) || defined(_LIBCPP_VERSION)
|
||||
|
||||
// See third_party/inspector_protocol/crdtp/serializer_traits.h.
|
||||
namespace v8_crdtp {
|
||||
template <>
|
||||
struct SerializerTraits<v8_inspector::String16> {
|
||||
static void Serialize(const v8_inspector::String16& str,
|
||||
std::vector<uint8_t>* out);
|
||||
};
|
||||
} // namespace v8_crdtp
|
||||
|
||||
#endif // V8_INSPECTOR_STRING_16_H_
|
||||
|
@ -305,8 +305,4 @@ void ProtocolTypeTraits<Binary>::Serialize(const Binary& value,
|
||||
cbor::EncodeBinary(span<uint8_t>(value.data(), value.size()), bytes);
|
||||
}
|
||||
|
||||
void SerializerTraits<Binary>::Serialize(
|
||||
const v8_inspector::protocol::Binary& binary, std::vector<uint8_t>* out) {
|
||||
cbor::EncodeBinary(span<uint8_t>(binary.data(), binary.size()), out);
|
||||
}
|
||||
} // namespace v8_crdtp
|
||||
|
@ -108,12 +108,6 @@ struct ProtocolTypeTraits<v8_inspector::protocol::Binary> {
|
||||
std::vector<uint8_t>* bytes);
|
||||
};
|
||||
|
||||
template <>
|
||||
struct SerializerTraits<v8_inspector::protocol::Binary> {
|
||||
static void Serialize(const v8_inspector::protocol::Binary& binary,
|
||||
std::vector<uint8_t>* out);
|
||||
};
|
||||
|
||||
namespace detail {
|
||||
template <>
|
||||
struct MaybeTypedef<v8_inspector::String16> {
|
||||
|
2
third_party/inspector_protocol/BUILD.gn
vendored
2
third_party/inspector_protocol/BUILD.gn
vendored
@ -31,7 +31,6 @@ v8_source_set("crdtp") {
|
||||
"crdtp/protocol_core.h",
|
||||
"crdtp/serializable.cc",
|
||||
"crdtp/serializable.h",
|
||||
"crdtp/serializer_traits.h",
|
||||
"crdtp/span.cc",
|
||||
"crdtp/span.h",
|
||||
"crdtp/status.cc",
|
||||
@ -63,7 +62,6 @@ v8_source_set("crdtp_test") {
|
||||
"crdtp/glue_test.cc",
|
||||
"crdtp/json_test.cc",
|
||||
"crdtp/serializable_test.cc",
|
||||
"crdtp/serializer_traits_test.cc",
|
||||
"crdtp/span_test.cc",
|
||||
"crdtp/status_test.cc",
|
||||
"crdtp/status_test_support.cc",
|
||||
|
2
third_party/inspector_protocol/README.v8
vendored
2
third_party/inspector_protocol/README.v8
vendored
@ -2,7 +2,7 @@ Name: inspector protocol
|
||||
Short Name: inspector_protocol
|
||||
URL: https://chromium.googlesource.com/deps/inspector_protocol/
|
||||
Version: 0
|
||||
Revision: 32cf5f2bf4dc20c73ead291e68d2e2f6b638cd57
|
||||
Revision: 5221cbfa7f940d56ae8b79bf34c446a56781dd56
|
||||
License: BSD
|
||||
License File: LICENSE
|
||||
Security Critical: no
|
||||
|
@ -3,6 +3,7 @@
|
||||
# Use of this source code is governed by a BSD-style license that can be
|
||||
# found in the LICENSE file.
|
||||
|
||||
import os
|
||||
import os.path
|
||||
import sys
|
||||
import argparse
|
||||
@ -144,6 +145,7 @@ def dash_to_camelcase(word):
|
||||
|
||||
|
||||
def to_snake_case(name):
|
||||
name = re.sub(r"([A-Z]{2,})([A-Z][a-z])", r"\1_\2", name)
|
||||
return re.sub(r"([a-z0-9])([A-Z])", r"\1_\2", name, sys.maxsize).lower()
|
||||
|
||||
|
||||
@ -693,6 +695,11 @@ def main():
|
||||
sys.exit()
|
||||
|
||||
for file_name, content in outputs.items():
|
||||
# Remove output file first to account for potential case changes.
|
||||
try:
|
||||
os.remove(file_name)
|
||||
except OSError:
|
||||
pass
|
||||
out_file = open(file_name, "w")
|
||||
out_file.write(content)
|
||||
out_file.close()
|
||||
|
@ -10,6 +10,13 @@ import sys
|
||||
|
||||
import pdl
|
||||
|
||||
def open_to_write(path):
|
||||
if sys.version_info >= (3,0):
|
||||
return open(path, 'w', encoding='utf-8')
|
||||
else:
|
||||
return open(path, 'wb')
|
||||
|
||||
|
||||
def main(argv):
|
||||
parser = argparse.ArgumentParser(description=(
|
||||
"Converts from .pdl to .json by invoking the pdl Python module."))
|
||||
@ -25,8 +32,7 @@ def main(argv):
|
||||
pdl_string = input_file.read()
|
||||
protocol = pdl.loads(pdl_string, file_name, args.map_binary_to_string)
|
||||
input_file.close()
|
||||
|
||||
output_file = open(os.path.normpath(args.json_file), 'wb')
|
||||
output_file = open_to_write(os.path.normpath(args.json_file))
|
||||
json.dump(protocol, output_file, indent=4, separators=(',', ': '))
|
||||
output_file.close()
|
||||
|
||||
|
10
third_party/inspector_protocol/crdtp/cbor.cc
vendored
10
third_party/inspector_protocol/crdtp/cbor.cc
vendored
@ -695,8 +695,9 @@ void CBORTokenizer::ReadNextToken(bool enter_envelope) {
|
||||
// inspector protocol, it's not a CBOR limitation), so we check
|
||||
// against the signed max, so that the allowable values are
|
||||
// 0, 1, 2, ... 2^31 - 1.
|
||||
if (!bytes_read || std::numeric_limits<int32_t>::max() <
|
||||
token_start_internal_value_) {
|
||||
if (!bytes_read ||
|
||||
static_cast<uint64_t>(std::numeric_limits<int32_t>::max()) <
|
||||
static_cast<uint64_t>(token_start_internal_value_)) {
|
||||
SetError(Error::CBOR_INVALID_INT32);
|
||||
return;
|
||||
}
|
||||
@ -713,8 +714,9 @@ void CBORTokenizer::ReadNextToken(bool enter_envelope) {
|
||||
// We check the payload in token_start_internal_value_ against
|
||||
// that range (2^31-1 is also known as
|
||||
// std::numeric_limits<int32_t>::max()).
|
||||
if (!bytes_read || token_start_internal_value_ >
|
||||
std::numeric_limits<int32_t>::max()) {
|
||||
if (!bytes_read ||
|
||||
static_cast<uint64_t>(token_start_internal_value_) >
|
||||
static_cast<uint64_t>(std::numeric_limits<int32_t>::max())) {
|
||||
SetError(Error::CBOR_INVALID_INT32);
|
||||
return;
|
||||
}
|
||||
|
@ -10,31 +10,10 @@
|
||||
#include "maybe.h"
|
||||
#include "status_test_support.h"
|
||||
#include "test_platform.h"
|
||||
#include "test_string_traits.h"
|
||||
|
||||
namespace v8_crdtp {
|
||||
|
||||
// Test-only. Real-life bindings use UTF8/16 conversions as needed.
|
||||
template <>
|
||||
struct ProtocolTypeTraits<std::string> {
|
||||
static bool Deserialize(DeserializerState* state, std::string* value) {
|
||||
if (state->tokenizer()->TokenTag() == cbor::CBORTokenTag::STRING8) {
|
||||
auto cbor_span = state->tokenizer()->GetString8();
|
||||
value->assign(reinterpret_cast<const char*>(cbor_span.data()),
|
||||
cbor_span.size());
|
||||
return true;
|
||||
}
|
||||
state->RegisterError(Error::BINDINGS_STRING8_VALUE_EXPECTED);
|
||||
return false;
|
||||
}
|
||||
|
||||
static void Serialize(const std::string& value, std::vector<uint8_t>* bytes) {
|
||||
cbor::EncodeString8(
|
||||
span<uint8_t>(reinterpret_cast<const uint8_t*>(value.data()),
|
||||
value.size()),
|
||||
bytes);
|
||||
}
|
||||
};
|
||||
|
||||
namespace {
|
||||
using ::testing::Eq;
|
||||
|
||||
|
@ -1,158 +0,0 @@
|
||||
// Copyright 2019 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef V8_CRDTP_SERIALIZER_TRAITS_H_
|
||||
#define V8_CRDTP_SERIALIZER_TRAITS_H_
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "cbor.h"
|
||||
#include "maybe.h"
|
||||
#include "span.h"
|
||||
|
||||
namespace v8_crdtp {
|
||||
// =============================================================================
|
||||
// SerializerTraits - Encodes field values of protocol objects in CBOR.
|
||||
// =============================================================================
|
||||
//
|
||||
// A family of serialization functions which are used by FieldSerializerTraits
|
||||
// (below) to encode field values in CBOR. Conceptually, it's this:
|
||||
//
|
||||
// Serialize(bool value, std::vector<uint8_t>* out);
|
||||
// Serialize(int32_t value, std::vector<uint8_t>* out);
|
||||
// Serialize(double value, std::vector<uint8_t>* out);
|
||||
// ...
|
||||
//
|
||||
// However, if this was to use straight-forward overloading, implicit
|
||||
// type conversions would lead to ambiguity - e.g., a bool could be
|
||||
// represented as an int32_t, but it should really be encoded as a bool.
|
||||
// The template parameterized / specialized structs accomplish this.
|
||||
//
|
||||
// SerializerTraits<bool>::Serialize(bool value, std::vector<uint8_t>* out);
|
||||
// SerializerTraits<int32>::Serialize(int32_t value, std::vector<uint8_t>* out);
|
||||
// SerializerTraits<double>::Serialize(double value, std::vector<uint8_t>* out);
|
||||
template <typename T>
|
||||
struct SerializerTraits {
|
||||
// |Serializable| (defined in serializable.h) already knows how to serialize
|
||||
// to CBOR, so we can just delegate. This covers domain specific types,
|
||||
// protocol::Binary, etc.
|
||||
// However, we use duck-typing here, because Exported, which is part of the V8
|
||||
// headers also comes with AppendSerialized, and logically it's the same type,
|
||||
// but it lives in a different namespace (v8_inspector::protocol::Exported).
|
||||
template <
|
||||
typename LikeSerializable,
|
||||
typename std::enable_if_t<std::is_member_pointer<decltype(
|
||||
&LikeSerializable::AppendSerialized)>{},
|
||||
int> = 0>
|
||||
static void Serialize(const LikeSerializable& value,
|
||||
std::vector<uint8_t>* out) {
|
||||
value.AppendSerialized(out);
|
||||
}
|
||||
};
|
||||
|
||||
// This covers std::string, which is assumed to be UTF-8.
|
||||
// The two other string implementations that are used in the protocol bindings:
|
||||
// - WTF::String, for which the SerializerTraits specialization is located
|
||||
// in third_party/blink/renderer/core/inspector/v8-inspector-string.h.
|
||||
// - v8_inspector::String16, implemented in v8/src/inspector/string-16.h
|
||||
// along with its SerializerTraits specialization.
|
||||
template <>
|
||||
struct SerializerTraits<std::string> {
|
||||
static void Serialize(const std::string& str, std::vector<uint8_t>* out) {
|
||||
cbor::EncodeString8(SpanFrom(str), out);
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct SerializerTraits<bool> {
|
||||
static void Serialize(bool value, std::vector<uint8_t>* out) {
|
||||
out->push_back(value ? cbor::EncodeTrue() : cbor::EncodeFalse());
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct SerializerTraits<int32_t> {
|
||||
static void Serialize(int32_t value, std::vector<uint8_t>* out) {
|
||||
cbor::EncodeInt32(value, out);
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct SerializerTraits<double> {
|
||||
static void Serialize(double value, std::vector<uint8_t>* out) {
|
||||
cbor::EncodeDouble(value, out);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct SerializerTraits<std::vector<T>> {
|
||||
static void Serialize(const std::vector<T>& value,
|
||||
std::vector<uint8_t>* out) {
|
||||
out->push_back(cbor::EncodeIndefiniteLengthArrayStart());
|
||||
for (const T& element : value)
|
||||
SerializerTraits<T>::Serialize(element, out);
|
||||
out->push_back(cbor::EncodeStop());
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct SerializerTraits<std::unique_ptr<T>> {
|
||||
static void Serialize(const std::unique_ptr<T>& value,
|
||||
std::vector<uint8_t>* out) {
|
||||
SerializerTraits<T>::Serialize(*value, out);
|
||||
}
|
||||
};
|
||||
|
||||
// =============================================================================
|
||||
// FieldSerializerTraits - Encodes fields of protocol objects in CBOR
|
||||
// =============================================================================
|
||||
//
|
||||
// The generated code (see TypeBuilder_cpp.template) invokes SerializeField,
|
||||
// which then instantiates the FieldSerializerTraits to emit the appropriate
|
||||
// existence checks / dereference for the field value. This avoids emitting
|
||||
// the field name if the value for an optional field isn't set.
|
||||
template <typename T>
|
||||
struct FieldSerializerTraits {
|
||||
static void Serialize(span<uint8_t> field_name,
|
||||
const T& field_value,
|
||||
std::vector<uint8_t>* out) {
|
||||
cbor::EncodeString8(field_name, out);
|
||||
SerializerTraits<T>::Serialize(field_value, out);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct FieldSerializerTraits<detail::PtrMaybe<T>> {
|
||||
static void Serialize(span<uint8_t> field_name,
|
||||
const detail::PtrMaybe<T>& field_value,
|
||||
std::vector<uint8_t>* out) {
|
||||
if (!field_value.isJust())
|
||||
return;
|
||||
cbor::EncodeString8(field_name, out);
|
||||
SerializerTraits<T>::Serialize(*field_value.fromJust(), out);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct FieldSerializerTraits<detail::ValueMaybe<T>> {
|
||||
static void Serialize(span<uint8_t> field_name,
|
||||
const detail::ValueMaybe<T>& field_value,
|
||||
std::vector<uint8_t>* out) {
|
||||
if (!field_value.isJust())
|
||||
return;
|
||||
cbor::EncodeString8(field_name, out);
|
||||
SerializerTraits<T>::Serialize(field_value.fromJust(), out);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
void SerializeField(span<uint8_t> field_name,
|
||||
const T& field_value,
|
||||
std::vector<uint8_t>* out) {
|
||||
FieldSerializerTraits<T>::Serialize(field_name, field_value, out);
|
||||
}
|
||||
} // namespace v8_crdtp
|
||||
|
||||
#endif // V8_CRDTP_SERIALIZER_TRAITS_H_
|
@ -1,226 +0,0 @@
|
||||
// Copyright 2019 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "serializer_traits.h"
|
||||
|
||||
#include <array>
|
||||
#include "serializable.h"
|
||||
#include "test_platform.h"
|
||||
|
||||
// The purpose of this test is to ensure that the
|
||||
// {Field}SerializerTraits<X>::Serialize methods invoke the appropriate
|
||||
// functions from cbor.h; so, it's usually sufficient to compare with what
|
||||
// cbor.h function invocations would produce, rather than making assertions on
|
||||
// the specific bytes emitted by the SerializerTraits code.
|
||||
|
||||
namespace v8_crdtp {
|
||||
namespace {
|
||||
// =============================================================================
|
||||
// SerializerTraits - Encodes field values of protocol objects in CBOR.
|
||||
// =============================================================================
|
||||
|
||||
TEST(SerializerTraits, Bool) {
|
||||
std::vector<uint8_t> out;
|
||||
SerializerTraits<bool>::Serialize(true, &out);
|
||||
SerializerTraits<bool>::Serialize(false, &out);
|
||||
EXPECT_THAT(out,
|
||||
testing::ElementsAre(cbor::EncodeTrue(), cbor::EncodeFalse()));
|
||||
}
|
||||
|
||||
TEST(SerializerTraits, Double) {
|
||||
std::vector<uint8_t> out;
|
||||
SerializerTraits<double>::Serialize(1.00001, &out);
|
||||
|
||||
std::vector<uint8_t> expected;
|
||||
cbor::EncodeDouble(1.00001, &expected);
|
||||
|
||||
EXPECT_THAT(out, testing::ElementsAreArray(expected));
|
||||
}
|
||||
|
||||
TEST(SerializerTraits, Int32) {
|
||||
std::vector<uint8_t> out;
|
||||
SerializerTraits<int32_t>::Serialize(42, &out);
|
||||
|
||||
std::vector<uint8_t> expected;
|
||||
cbor::EncodeInt32(42, &expected);
|
||||
|
||||
EXPECT_THAT(out, testing::ElementsAreArray(expected));
|
||||
}
|
||||
|
||||
TEST(SerializerTraits, VectorOfInt32) {
|
||||
std::vector<int32_t> ints = {1, 2, 3};
|
||||
|
||||
std::vector<uint8_t> out;
|
||||
SerializerTraits<std::vector<int32_t>>::Serialize(ints, &out);
|
||||
|
||||
std::vector<uint8_t> expected;
|
||||
expected.push_back(cbor::EncodeIndefiniteLengthArrayStart());
|
||||
for (int32_t v : ints)
|
||||
cbor::EncodeInt32(v, &expected);
|
||||
expected.push_back(cbor::EncodeStop());
|
||||
|
||||
EXPECT_THAT(out, testing::ElementsAreArray(expected));
|
||||
}
|
||||
|
||||
// Foo is an example for a domain specific type.
|
||||
class Foo : public Serializable {
|
||||
public:
|
||||
Foo(int32_t value) : value(value) {}
|
||||
|
||||
int32_t value;
|
||||
|
||||
void AppendSerialized(std::vector<uint8_t>* out) const override {
|
||||
// In production, this would be generated code which emits a
|
||||
// CBOR map that has STRING8 keys corresponding to the field names
|
||||
// and field values encoded using SerializerTraits::Serialize.
|
||||
//
|
||||
// For the test we simplify this drastically and just emit the field
|
||||
// value, for conveniently testing std::vector<std::unique_ptr<Foo>>,
|
||||
// as well as the convenience methods for raw pointer and unique_ptr.
|
||||
SerializerTraits<int32_t>::Serialize(value, out);
|
||||
}
|
||||
};
|
||||
|
||||
TEST(SerializerTraits, VectorOfDomainSpecificType) {
|
||||
std::vector<std::unique_ptr<Foo>> foos;
|
||||
foos.push_back(std::make_unique<Foo>(1));
|
||||
foos.push_back(std::make_unique<Foo>(2));
|
||||
foos.push_back(std::make_unique<Foo>(3));
|
||||
|
||||
std::vector<uint8_t> out;
|
||||
SerializerTraits<std::vector<std::unique_ptr<Foo>>>::Serialize(foos, &out);
|
||||
|
||||
std::vector<uint8_t> expected;
|
||||
expected.push_back(cbor::EncodeIndefiniteLengthArrayStart());
|
||||
for (int32_t v : {1, 2, 3})
|
||||
cbor::EncodeInt32(v, &expected);
|
||||
expected.push_back(cbor::EncodeStop());
|
||||
|
||||
EXPECT_THAT(out, testing::ElementsAreArray(expected));
|
||||
}
|
||||
|
||||
TEST(SerializerTraits, ConstRefAndUniquePtr) {
|
||||
// Shows that SerializerTraits<Foo> allows unique_ptr.
|
||||
Foo foo(42);
|
||||
auto bar = std::make_unique<Foo>(21);
|
||||
|
||||
std::vector<uint8_t> out;
|
||||
// In this case, |foo| is taken as a const Foo&.
|
||||
SerializerTraits<Foo>::Serialize(foo, &out);
|
||||
// In this case, |bar| is taken as a const std::unique_ptr<Foo>&.
|
||||
SerializerTraits<std::unique_ptr<Foo>>::Serialize(bar, &out);
|
||||
|
||||
std::vector<uint8_t> expected;
|
||||
cbor::EncodeInt32(42, &expected);
|
||||
cbor::EncodeInt32(21, &expected);
|
||||
|
||||
EXPECT_THAT(out, testing::ElementsAreArray(expected));
|
||||
}
|
||||
|
||||
TEST(SerializerTraits, UTF8String) {
|
||||
std::string msg = "Hello, 🌎.";
|
||||
|
||||
std::vector<uint8_t> out;
|
||||
SerializerTraits<std::string>::Serialize(msg, &out);
|
||||
|
||||
std::vector<uint8_t> expected;
|
||||
cbor::EncodeString8(SpanFrom(msg), &expected);
|
||||
|
||||
EXPECT_THAT(out, testing::ElementsAreArray(expected));
|
||||
}
|
||||
|
||||
// A trivial model of Exported.
|
||||
// (see
|
||||
// https://cs.chromium.org/chromium/src/out/Debug/gen/v8/include/inspector/Debugger.h).
|
||||
struct Exported {
|
||||
std::string msg;
|
||||
void AppendSerialized(std::vector<uint8_t>* out) const {
|
||||
cbor::EncodeString8(SpanFrom(msg), out);
|
||||
}
|
||||
};
|
||||
|
||||
TEST(SerializerTraits, Exported) {
|
||||
Exported exported;
|
||||
exported.msg = "Hello, world.";
|
||||
|
||||
std::vector<uint8_t> out;
|
||||
SerializerTraits<Exported>::Serialize(exported, &out);
|
||||
|
||||
std::vector<uint8_t> expected;
|
||||
cbor::EncodeString8(SpanFrom(exported.msg), &expected);
|
||||
|
||||
EXPECT_THAT(out, testing::ElementsAreArray(expected));
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// FieldSerializerTraits - Encodes fields of protocol objects in CBOR
|
||||
// =============================================================================
|
||||
TEST(FieldSerializerTraits, RequiredField) {
|
||||
std::string value = "Hello, world.";
|
||||
|
||||
std::vector<uint8_t> out;
|
||||
SerializeField(SpanFrom("msg"), value, &out);
|
||||
|
||||
std::vector<uint8_t> expected;
|
||||
cbor::EncodeString8(SpanFrom("msg"), &expected);
|
||||
cbor::EncodeString8(SpanFrom(value), &expected);
|
||||
|
||||
EXPECT_THAT(out, testing::ElementsAreArray(expected));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
class FieldSerializerTraits_MaybeTest : public ::testing::Test {};
|
||||
using MaybeTypes =
|
||||
::testing::Types<detail::ValueMaybe<bool>,
|
||||
detail::ValueMaybe<double>,
|
||||
detail::ValueMaybe<int32_t>,
|
||||
detail::ValueMaybe<std::string>,
|
||||
detail::PtrMaybe<Foo>,
|
||||
detail::PtrMaybe<std::vector<std::unique_ptr<Foo>>>>;
|
||||
TYPED_TEST_SUITE(FieldSerializerTraits_MaybeTest, MaybeTypes);
|
||||
|
||||
TYPED_TEST(FieldSerializerTraits_MaybeTest, NoOutputForFieldsIfNotJust) {
|
||||
std::vector<uint8_t> out;
|
||||
SerializeField(SpanFrom("maybe"), TypeParam(), &out);
|
||||
EXPECT_THAT(out, testing::ElementsAreArray(std::vector<uint8_t>()));
|
||||
}
|
||||
|
||||
TEST(FieldSerializerTraits, MaybeBool) {
|
||||
std::vector<uint8_t> out;
|
||||
SerializeField(SpanFrom("true"), detail::ValueMaybe<bool>(true), &out);
|
||||
SerializeField(SpanFrom("false"), detail::ValueMaybe<bool>(false), &out);
|
||||
|
||||
std::vector<uint8_t> expected;
|
||||
cbor::EncodeString8(SpanFrom("true"), &expected);
|
||||
expected.push_back(cbor::EncodeTrue());
|
||||
cbor::EncodeString8(SpanFrom("false"), &expected);
|
||||
expected.push_back(cbor::EncodeFalse());
|
||||
|
||||
EXPECT_THAT(out, testing::ElementsAreArray(expected));
|
||||
}
|
||||
|
||||
TEST(FieldSerializerTraits, MaybeDouble) {
|
||||
std::vector<uint8_t> out;
|
||||
SerializeField(SpanFrom("dbl"), detail::ValueMaybe<double>(3.14), &out);
|
||||
|
||||
std::vector<uint8_t> expected;
|
||||
cbor::EncodeString8(SpanFrom("dbl"), &expected);
|
||||
cbor::EncodeDouble(3.14, &expected);
|
||||
|
||||
EXPECT_THAT(out, testing::ElementsAreArray(expected));
|
||||
}
|
||||
|
||||
TEST(FieldSerializerTraits, MaybePtrFoo) {
|
||||
std::vector<uint8_t> out;
|
||||
SerializeField(SpanFrom("foo"),
|
||||
detail::PtrMaybe<Foo>(std::make_unique<Foo>(42)), &out);
|
||||
|
||||
std::vector<uint8_t> expected;
|
||||
cbor::EncodeString8(SpanFrom("foo"), &expected);
|
||||
cbor::EncodeInt32(42, &expected); // Simplified relative to production.
|
||||
|
||||
EXPECT_THAT(out, testing::ElementsAreArray(expected));
|
||||
}
|
||||
} // namespace
|
||||
} // namespace v8_crdtp
|
@ -12,11 +12,8 @@
|
||||
{% endif %}
|
||||
#include {{format_include(config.lib.string_header)}}
|
||||
|
||||
#include <cstddef>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
|
||||
#include "{{config.crdtp.dir}}/error_support.h"
|
||||
#include "{{config.crdtp.dir}}/dispatch.h"
|
||||
|
@ -18,7 +18,7 @@ namespace {{namespace}} {
|
||||
{% endfor %}
|
||||
|
||||
{% for namespace in config.protocol.namespace %}
|
||||
} // namespce
|
||||
} // namespace
|
||||
{% endfor %}
|
||||
|
||||
|
||||
|
@ -10,6 +10,11 @@
|
||||
//#include "Allocator.h"
|
||||
//#include "Forward.h"
|
||||
|
||||
#include <memory>
|
||||
#include <unordered_map>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include {{format_include(config.protocol.package, "Forward")}}
|
||||
|
||||
{% for namespace in config.protocol.namespace %}
|
||||
|
@ -27,97 +27,6 @@ using {{"::".join(config.protocol.namespace)}}::StringUtil;
|
||||
namespace {{namespace}} {
|
||||
{% endfor %}
|
||||
|
||||
std::unique_ptr<protocol::Value> toProtocolValue(
|
||||
const base::Value* value, int depth) {
|
||||
if (!value || !depth)
|
||||
return nullptr;
|
||||
if (value->is_none())
|
||||
return protocol::Value::null();
|
||||
if (value->is_bool())
|
||||
return protocol::FundamentalValue::create(value->GetBool());
|
||||
if (value->is_int())
|
||||
return protocol::FundamentalValue::create(value->GetInt());
|
||||
if (value->is_double())
|
||||
return protocol::FundamentalValue::create(value->GetDouble());
|
||||
if (value->is_string())
|
||||
return protocol::StringValue::create(value->GetString());
|
||||
if (value->is_list()) {
|
||||
std::unique_ptr<protocol::ListValue> result = protocol::ListValue::create();
|
||||
for (const base::Value& item : value->GetList()) {
|
||||
std::unique_ptr<protocol::Value> converted =
|
||||
toProtocolValue(&item, depth - 1);
|
||||
if (converted)
|
||||
result->pushValue(std::move(converted));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
if (value->is_dict()) {
|
||||
std::unique_ptr<protocol::DictionaryValue> result =
|
||||
protocol::DictionaryValue::create();
|
||||
for (const auto& it : value->DictItems()) {
|
||||
std::unique_ptr<protocol::Value> converted =
|
||||
toProtocolValue(&it.second, depth - 1);
|
||||
if (converted)
|
||||
result->setValue(it.first, std::move(converted));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::unique_ptr<base::Value> toBaseValue(Value* value, int depth) {
|
||||
if (!value || !depth)
|
||||
return nullptr;
|
||||
if (value->type() == Value::TypeNull)
|
||||
return std::make_unique<base::Value>();
|
||||
if (value->type() == Value::TypeBoolean) {
|
||||
bool inner;
|
||||
value->asBoolean(&inner);
|
||||
return base::WrapUnique(new base::Value(inner));
|
||||
}
|
||||
if (value->type() == Value::TypeInteger) {
|
||||
int inner;
|
||||
value->asInteger(&inner);
|
||||
return base::WrapUnique(new base::Value(inner));
|
||||
}
|
||||
if (value->type() == Value::TypeDouble) {
|
||||
double inner;
|
||||
value->asDouble(&inner);
|
||||
return base::WrapUnique(new base::Value(inner));
|
||||
}
|
||||
if (value->type() == Value::TypeString) {
|
||||
std::string inner;
|
||||
value->asString(&inner);
|
||||
return base::WrapUnique(new base::Value(inner));
|
||||
}
|
||||
if (value->type() == Value::TypeArray) {
|
||||
ListValue* list = ListValue::cast(value);
|
||||
std::unique_ptr<base::Value> result(new base::Value(
|
||||
base::Value::Type::LIST));
|
||||
for (size_t i = 0; i < list->size(); i++) {
|
||||
std::unique_ptr<base::Value> converted =
|
||||
toBaseValue(list->at(i), depth - 1);
|
||||
if (converted)
|
||||
result->Append(std::move(*converted));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
if (value->type() == Value::TypeObject) {
|
||||
DictionaryValue* dict = DictionaryValue::cast(value);
|
||||
std::unique_ptr<base::Value> result(new base::Value(
|
||||
base::Value::Type::DICTIONARY));
|
||||
for (size_t i = 0; i < dict->size(); i++) {
|
||||
DictionaryValue::Entry entry = dict->at(i);
|
||||
std::unique_ptr<base::Value> converted =
|
||||
toBaseValue(entry.second, depth - 1);
|
||||
if (converted)
|
||||
result->SetKey(entry.first, std::move(*converted));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// In Chromium, we do not support big endian architectures, so no conversion is needed
|
||||
// to interpret UTF16LE.
|
||||
// static
|
||||
@ -127,105 +36,88 @@ String StringUtil::fromUTF16LE(const uint16_t* data, size_t length) {
|
||||
return utf8;
|
||||
}
|
||||
|
||||
bool StringUtil::ReadString(DeserializerState* state, String* value) {
|
||||
auto* tokenizer = state->tokenizer();
|
||||
if (tokenizer->TokenTag() == cbor::CBORTokenTag::STRING8) {
|
||||
const auto str = tokenizer->GetString8();
|
||||
*value = StringUtil::fromUTF8(str.data(), str.size());
|
||||
return true;
|
||||
std::unique_ptr<protocol::Value> toProtocolValue(
|
||||
const base::Value& value, int depth) {
|
||||
if (!depth)
|
||||
return nullptr;
|
||||
if (value.is_none())
|
||||
return protocol::Value::null();
|
||||
if (value.is_bool())
|
||||
return protocol::FundamentalValue::create(value.GetBool());
|
||||
if (value.is_int())
|
||||
return protocol::FundamentalValue::create(value.GetInt());
|
||||
if (value.is_double())
|
||||
return protocol::FundamentalValue::create(value.GetDouble());
|
||||
if (value.is_string())
|
||||
return protocol::StringValue::create(value.GetString());
|
||||
if (value.is_list()) {
|
||||
auto result = protocol::ListValue::create();
|
||||
for (const base::Value& item : value.GetList()) {
|
||||
if (auto converted = toProtocolValue(item, depth - 1)) {
|
||||
result->pushValue(std::move(converted));
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
if (tokenizer->TokenTag() == cbor::CBORTokenTag::STRING16) {
|
||||
const auto str = tokenizer->GetString16WireRep();
|
||||
*value = StringUtil::fromUTF16LE(reinterpret_cast<const uint16_t*>(str.data()), str.size() / 2);
|
||||
return true;
|
||||
if (value.is_dict()) {
|
||||
auto result = protocol::DictionaryValue::create();
|
||||
for (auto kv : value.DictItems()) {
|
||||
if (auto converted = toProtocolValue(kv.second, depth - 1)) {
|
||||
result->setValue(kv.first, std::move(converted));
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
state->RegisterError(Error::BINDINGS_STRING_VALUE_EXPECTED);
|
||||
return false;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void StringUtil::WriteString(const String& str, std::vector<uint8_t>* bytes) {
|
||||
cbor::EncodeString8(span<uint8_t>(StringUtil::CharactersUTF8(str),
|
||||
StringUtil::CharacterCount(str)),
|
||||
bytes);
|
||||
}
|
||||
|
||||
Binary::Binary() : bytes_(new base::RefCountedBytes) {}
|
||||
Binary::Binary(const Binary& binary) : bytes_(binary.bytes_) {}
|
||||
Binary::Binary(scoped_refptr<base::RefCountedMemory> bytes) : bytes_(bytes) {}
|
||||
Binary::~Binary() {}
|
||||
|
||||
void Binary::AppendSerialized(std::vector<uint8_t>* out) const {
|
||||
crdtp::cbor::EncodeBinary(crdtp::span<uint8_t>(data(), size()), out);
|
||||
}
|
||||
|
||||
String Binary::toBase64() const {
|
||||
std::string encoded;
|
||||
base::Base64Encode(
|
||||
base::StringPiece(reinterpret_cast<const char*>(bytes_->front()),
|
||||
bytes_->size()),
|
||||
&encoded);
|
||||
return encoded;
|
||||
}
|
||||
|
||||
// static
|
||||
Binary Binary::fromBase64(const String& base64, bool* success) {
|
||||
std::string decoded;
|
||||
*success = base::Base64Decode(base::StringPiece(base64), &decoded);
|
||||
if (*success) {
|
||||
return Binary::fromString(std::move(decoded));
|
||||
base::Value toBaseValue(Value* value, int depth) {
|
||||
if (!value || !depth)
|
||||
return base::Value();
|
||||
if (value->type() == Value::TypeBoolean) {
|
||||
bool inner;
|
||||
value->asBoolean(&inner);
|
||||
return base::Value(inner);
|
||||
}
|
||||
return Binary();
|
||||
}
|
||||
|
||||
// static
|
||||
Binary Binary::fromRefCounted(scoped_refptr<base::RefCountedMemory> memory) {
|
||||
return Binary(memory);
|
||||
}
|
||||
|
||||
// static
|
||||
Binary Binary::fromVector(std::vector<uint8_t> data) {
|
||||
return Binary(base::RefCountedBytes::TakeVector(&data));
|
||||
}
|
||||
|
||||
// static
|
||||
Binary Binary::fromString(std::string data) {
|
||||
return Binary(base::RefCountedString::TakeString(&data));
|
||||
}
|
||||
|
||||
// static
|
||||
Binary Binary::fromSpan(const uint8_t* data, size_t size) {
|
||||
return Binary(scoped_refptr<base::RefCountedBytes>(
|
||||
new base::RefCountedBytes(data, size)));
|
||||
if (value->type() == Value::TypeInteger) {
|
||||
int inner;
|
||||
value->asInteger(&inner);
|
||||
return base::Value(inner);
|
||||
}
|
||||
if (value->type() == Value::TypeDouble) {
|
||||
double inner;
|
||||
value->asDouble(&inner);
|
||||
return base::Value(inner);
|
||||
}
|
||||
if (value->type() == Value::TypeString) {
|
||||
std::string inner;
|
||||
value->asString(&inner);
|
||||
return base::Value(inner);
|
||||
}
|
||||
if (value->type() == Value::TypeArray) {
|
||||
ListValue* list = ListValue::cast(value);
|
||||
base::Value result(base::Value::Type::LIST);
|
||||
for (size_t i = 0; i < list->size(); i++) {
|
||||
base::Value converted = toBaseValue(list->at(i), depth - 1);
|
||||
if (!converted.is_none())
|
||||
result.Append(std::move(converted));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
if (value->type() == Value::TypeObject) {
|
||||
DictionaryValue* dict = DictionaryValue::cast(value);
|
||||
base::Value result(base::Value::Type::DICTIONARY);
|
||||
for (size_t i = 0; i < dict->size(); i++) {
|
||||
DictionaryValue::Entry entry = dict->at(i);
|
||||
base::Value converted = toBaseValue(entry.second, depth - 1);
|
||||
if (!converted.is_none())
|
||||
result.SetKey(entry.first, std::move(converted));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
return base::Value();
|
||||
}
|
||||
|
||||
{% for namespace in config.protocol.namespace %}
|
||||
} // namespace {{namespace}}
|
||||
} // namespace {{namespace}} {
|
||||
{% endfor %}
|
||||
|
||||
namespace {{config.crdtp.namespace}} {
|
||||
|
||||
// static
|
||||
bool ProtocolTypeTraits<Binary>::Deserialize(DeserializerState* state, Binary* value) {
|
||||
auto* tokenizer = state->tokenizer();
|
||||
if (tokenizer->TokenTag() == cbor::CBORTokenTag::BINARY) {
|
||||
const span<uint8_t> bin = tokenizer->GetBinary();
|
||||
*value = Binary::fromSpan(bin.data(), bin.size());
|
||||
return true;
|
||||
}
|
||||
if (tokenizer->TokenTag() == cbor::CBORTokenTag::STRING8) {
|
||||
const auto str_span = tokenizer->GetString8();
|
||||
String str = StringUtil::fromUTF8(str_span.data(), str_span.size());
|
||||
bool success = false;
|
||||
*value = Binary::fromBase64(str, &success);
|
||||
return success;
|
||||
}
|
||||
state->RegisterError(Error::BINDINGS_BINARY_VALUE_EXPECTED);
|
||||
return false;
|
||||
}
|
||||
|
||||
// static
|
||||
void ProtocolTypeTraits<Binary>::Serialize(const Binary& value, std::vector<uint8_t>* bytes) {
|
||||
value.AppendSerialized(bytes);
|
||||
}
|
||||
|
||||
} // namespace {{config.crdtp.namespace}}
|
||||
|
@ -7,28 +7,12 @@
|
||||
#ifndef {{"_".join(config.protocol.namespace)}}_BASE_STRING_ADAPTER_H
|
||||
#define {{"_".join(config.protocol.namespace)}}_BASE_STRING_ADAPTER_H
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "base/logging.h"
|
||||
#include "base/macros.h"
|
||||
#include "base/memory/ref_counted_memory.h"
|
||||
#include "{{config.crdtp.dir}}/serializable.h"
|
||||
#include "{{config.crdtp.dir}}/protocol_core.h"
|
||||
#include "{{config.crdtp.dir}}/chromium/protocol_traits.h"
|
||||
|
||||
{% if config.lib.export_header %}
|
||||
#include "{{config.lib.export_header}}"
|
||||
{% endif %}
|
||||
|
||||
namespace base {
|
||||
class Value;
|
||||
}
|
||||
|
||||
namespace {{config.crdtp.namespace}} {
|
||||
class DeserializerState;
|
||||
}
|
||||
|
||||
{% for namespace in config.protocol.namespace %}
|
||||
namespace {{namespace}} {
|
||||
{% endfor %}
|
||||
@ -36,6 +20,7 @@ namespace {{namespace}} {
|
||||
class Value;
|
||||
|
||||
using String = std::string;
|
||||
using Binary = crdtp::Binary;
|
||||
|
||||
class {{config.lib.export_macro}} StringUtil {
|
||||
public:
|
||||
@ -51,67 +36,13 @@ class {{config.lib.export_macro}} StringUtil {
|
||||
}
|
||||
static const uint16_t* CharactersUTF16(const String& s) { return nullptr; }
|
||||
static size_t CharacterCount(const String& s) { return s.size(); }
|
||||
|
||||
static bool ReadString({{config.crdtp.namespace}}::DeserializerState* state, String* str);
|
||||
static void WriteString(const String& str, std::vector<uint8_t>* bytes);
|
||||
};
|
||||
|
||||
// A read-only sequence of uninterpreted bytes with reference-counted storage.
|
||||
class {{config.lib.export_macro}} Binary : public {{config.crdtp.namespace}}::Serializable {
|
||||
public:
|
||||
Binary(const Binary&);
|
||||
Binary();
|
||||
~Binary();
|
||||
std::unique_ptr<Value> toProtocolValue(const base::Value& value, int depth);
|
||||
base::Value toBaseValue(Value* value, int depth);
|
||||
|
||||
// Implements Serializable.
|
||||
void AppendSerialized(std::vector<uint8_t>* out) const override;
|
||||
|
||||
const uint8_t* data() const { return bytes_->front(); }
|
||||
size_t size() const { return bytes_->size(); }
|
||||
scoped_refptr<base::RefCountedMemory> bytes() const { return bytes_; }
|
||||
|
||||
String toBase64() const;
|
||||
|
||||
static Binary fromBase64(const String& base64, bool* success);
|
||||
static Binary fromRefCounted(scoped_refptr<base::RefCountedMemory> memory);
|
||||
static Binary fromVector(std::vector<uint8_t> data);
|
||||
static Binary fromString(std::string data);
|
||||
static Binary fromSpan(const uint8_t* data, size_t size);
|
||||
|
||||
private:
|
||||
explicit Binary(scoped_refptr<base::RefCountedMemory> bytes);
|
||||
scoped_refptr<base::RefCountedMemory> bytes_;
|
||||
};
|
||||
|
||||
std::unique_ptr<Value> toProtocolValue(const base::Value* value, int depth);
|
||||
std::unique_ptr<base::Value> toBaseValue(Value* value, int depth);
|
||||
{% for namespace in config.protocol.namespace %}
|
||||
} // namespace {{namespace}}
|
||||
{% endfor %}
|
||||
|
||||
namespace {{config.crdtp.namespace}} {
|
||||
|
||||
template <>
|
||||
struct ProtocolTypeTraits<{{"::".join(config.protocol.namespace)}}::String> {
|
||||
static bool Deserialize(DeserializerState* state, {{"::".join(config.protocol.namespace)}}::String* value) {
|
||||
return {{"::".join(config.protocol.namespace)}}::StringUtil::ReadString(state, value);
|
||||
}
|
||||
static void Serialize(const {{"::".join(config.protocol.namespace)}}::String& value, std::vector<uint8_t>* bytes) {
|
||||
{{"::".join(config.protocol.namespace)}}::StringUtil::WriteString(value, bytes);
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct ProtocolTypeTraits<{{"::".join(config.protocol.namespace)}}::Binary> {
|
||||
static bool Deserialize(DeserializerState* state, {{"::".join(config.protocol.namespace)}}::Binary* value);
|
||||
static void Serialize(const {{"::".join(config.protocol.namespace)}}::Binary& value, std::vector<uint8_t>* bytes);
|
||||
};
|
||||
|
||||
template <>
|
||||
struct {{config.crdtp.namespace}}::detail::MaybeTypedef<{{"::".join(config.protocol.namespace)}}::Binary> {
|
||||
typedef ValueMaybe<{{"::".join(config.protocol.namespace)}}::Binary> type;
|
||||
};
|
||||
|
||||
} // {{config.crdtp.namespace}}
|
||||
|
||||
#endif // !defined({{"_".join(config.protocol.namespace)}}_BASE_STRING_ADAPTER_H)
|
||||
|
Loading…
Reference in New Issue
Block a user