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:
Andrey Kosyakov 2022-01-21 11:59:55 -08:00 committed by V8 LUCI CQ
parent 49fd384551
commit 21e5104388
17 changed files with 110 additions and 706 deletions

View File

@ -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

View File

@ -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_

View File

@ -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

View File

@ -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> {

View File

@ -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",

View File

@ -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

View File

@ -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()

View File

@ -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()

View File

@ -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;
}

View File

@ -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;

View File

@ -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_

View File

@ -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

View File

@ -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"

View File

@ -18,7 +18,7 @@ namespace {{namespace}} {
{% endfor %}
{% for namespace in config.protocol.namespace %}
} // namespce
} // namespace
{% endfor %}

View File

@ -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 %}

View File

@ -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}}

View File

@ -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)