mirror of
https://github.com/nodejs/node.git
synced 2025-05-09 19:38:23 +00:00

Fixes: https://github.com/nodejs/node/issues/25808 PR-URL: https://github.com/nodejs/node/pull/26303 Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Refael Ackermann <refack@gmail.com>
305 lines
9.2 KiB
Plaintext
305 lines
9.2 KiB
Plaintext
// This file is generated by DispatcherBase_cpp.template.
|
|
|
|
// 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 {{format_include(config.protocol.package, "base_string_adapter")}}
|
|
#include {{format_include(config.protocol.package, "Protocol")}}
|
|
|
|
#include <utility>
|
|
#include "base/base64.h"
|
|
#include "base/json/json_reader.h"
|
|
#include "base/memory/ptr_util.h"
|
|
#include "base/strings/string16.h"
|
|
#include "base/strings/stringprintf.h"
|
|
#include "base/strings/utf_string_conversions.h"
|
|
#include "base/values.h"
|
|
|
|
{% for namespace in config.protocol.namespace %}
|
|
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()) {
|
|
bool inner;
|
|
value->GetAsBoolean(&inner);
|
|
return protocol::FundamentalValue::create(inner);
|
|
}
|
|
if (value->is_int()) {
|
|
int inner;
|
|
value->GetAsInteger(&inner);
|
|
return protocol::FundamentalValue::create(inner);
|
|
}
|
|
if (value->is_double()) {
|
|
double inner;
|
|
value->GetAsDouble(&inner);
|
|
return protocol::FundamentalValue::create(inner);
|
|
}
|
|
if (value->is_string()) {
|
|
std::string inner;
|
|
value->GetAsString(&inner);
|
|
return protocol::StringValue::create(inner);
|
|
}
|
|
if (value->is_list()) {
|
|
const base::ListValue* list = nullptr;
|
|
value->GetAsList(&list);
|
|
std::unique_ptr<protocol::ListValue> result = protocol::ListValue::create();
|
|
for (size_t i = 0; i < list->GetSize(); i++) {
|
|
const base::Value* item = nullptr;
|
|
list->Get(i, &item);
|
|
std::unique_ptr<protocol::Value> converted =
|
|
toProtocolValue(item, depth - 1);
|
|
if (converted)
|
|
result->pushValue(std::move(converted));
|
|
}
|
|
return std::move(result);
|
|
}
|
|
if (value->is_dict()) {
|
|
const base::DictionaryValue* dictionary = nullptr;
|
|
value->GetAsDictionary(&dictionary);
|
|
std::unique_ptr<protocol::DictionaryValue> result =
|
|
protocol::DictionaryValue::create();
|
|
for (base::DictionaryValue::Iterator it(*dictionary);
|
|
!it.IsAtEnd(); it.Advance()) {
|
|
std::unique_ptr<protocol::Value> converted =
|
|
toProtocolValue(&it.value(), depth - 1);
|
|
if (converted)
|
|
result->setValue(it.key(), std::move(converted));
|
|
}
|
|
return std::move(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::ListValue> result(new base::ListValue());
|
|
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 std::move(result);
|
|
}
|
|
if (value->type() == Value::TypeObject) {
|
|
DictionaryValue* dict = DictionaryValue::cast(value);
|
|
std::unique_ptr<base::DictionaryValue> result(new base::DictionaryValue());
|
|
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->SetWithoutPathExpansion(entry.first, std::move(converted));
|
|
}
|
|
return std::move(result);
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
// static
|
|
std::unique_ptr<Value> StringUtil::parseMessage(
|
|
const std::string& message, bool binary) {
|
|
if (binary) {
|
|
return Value::parseBinary(
|
|
reinterpret_cast<const uint8_t*>(message.data()),
|
|
message.length());
|
|
}
|
|
std::unique_ptr<base::Value> value = base::JSONReader::Read(message);
|
|
return toProtocolValue(value.get(), 1000);
|
|
}
|
|
|
|
// static
|
|
ProtocolMessage StringUtil::jsonToMessage(String message) {
|
|
return message;
|
|
}
|
|
|
|
// static
|
|
ProtocolMessage StringUtil::binaryToMessage(std::vector<uint8_t> message) {
|
|
// TODO(pfeldman): figure out what to do with this copy.
|
|
return std::string(reinterpret_cast<const char*>(message.data()), message.size());
|
|
}
|
|
|
|
StringBuilder::StringBuilder() {}
|
|
|
|
StringBuilder::~StringBuilder() {}
|
|
|
|
void StringBuilder::append(const std::string& s) {
|
|
string_ += s;
|
|
}
|
|
|
|
void StringBuilder::append(char c) {
|
|
string_ += c;
|
|
}
|
|
|
|
void StringBuilder::append(const char* characters, size_t length) {
|
|
string_.append(characters, length);
|
|
}
|
|
|
|
// static
|
|
void StringUtil::builderAppendQuotedString(StringBuilder& builder,
|
|
const String& str) {
|
|
builder.append('"');
|
|
base::string16 str16 = base::UTF8ToUTF16(str);
|
|
escapeWideStringForJSON(reinterpret_cast<const uint16_t*>(&str16[0]),
|
|
str16.length(), &builder);
|
|
builder.append('"');
|
|
}
|
|
|
|
std::string StringBuilder::toString() {
|
|
return string_;
|
|
}
|
|
|
|
void StringBuilder::reserveCapacity(size_t capacity) {
|
|
string_.reserve(capacity);
|
|
}
|
|
|
|
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() {}
|
|
|
|
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));
|
|
}
|
|
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)));
|
|
}
|
|
|
|
namespace {
|
|
int32_t ReadEnvelopeSize(const uint8_t* in) {
|
|
return (in[0] << 24) + (in[1] << 16) + (in[2] << 8) + in[3];
|
|
}
|
|
|
|
void WriteEnvelopeSize(uint32_t value, uint8_t* out) {
|
|
*(out++) = (value >> 24) & 0xFF;
|
|
*(out++) = (value >> 16) & 0xFF;
|
|
*(out++) = (value >> 8) & 0xFF;
|
|
*(out++) = (value) & 0xFF;
|
|
}
|
|
|
|
}
|
|
|
|
bool AppendStringValueToMapBinary(base::StringPiece in,
|
|
base::StringPiece key, base::StringPiece value, std::string* out) {
|
|
if (in.size() < 1 + 1 + 4 + 1 + 1)
|
|
return false;
|
|
const uint8_t* envelope = reinterpret_cast<const uint8_t*>(in.data());
|
|
if (cbor::kInitialByteForEnvelope != envelope[0])
|
|
return false;
|
|
if (cbor::kInitialByteFor32BitLengthByteString != envelope[1])
|
|
return false;
|
|
if (cbor::kInitialByteIndefiniteLengthMap != envelope[6])
|
|
return false;
|
|
|
|
uint32_t envelope_size = ReadEnvelopeSize(envelope + 2);
|
|
if (envelope_size + 2 + 4 != in.size())
|
|
return false;
|
|
if (cbor::kStopByte != static_cast<uint8_t>(*in.rbegin()))
|
|
return false;
|
|
|
|
std::vector<uint8_t> encoded_entry;
|
|
encoded_entry.reserve(1 + 4 + key.size() + 1 + 4 + value.size());
|
|
span<uint8_t> key_span(
|
|
reinterpret_cast<const uint8_t*>(key.data()), key.size());
|
|
EncodeString8(key_span, &encoded_entry);
|
|
span<uint8_t> value_span(
|
|
reinterpret_cast<const uint8_t*>(value.data()), value.size());
|
|
EncodeString8(value_span, &encoded_entry);
|
|
|
|
out->clear();
|
|
out->reserve(in.size() + encoded_entry.size());
|
|
out->append(in.begin(), in.end() - 1);
|
|
out->append(reinterpret_cast<const char*>(encoded_entry.data()),
|
|
encoded_entry.size());
|
|
out->append(1, static_cast<char>(cbor::kStopByte));
|
|
std::size_t new_size = envelope_size + out->size() - in.size();
|
|
if (new_size > static_cast<std::size_t>(
|
|
std::numeric_limits<uint32_t>::max())) {
|
|
return false;
|
|
}
|
|
WriteEnvelopeSize(new_size, reinterpret_cast<uint8_t*>(&*out->begin() + 2));
|
|
return true;
|
|
}
|
|
|
|
bool AppendStringValueToMapJSON(base::StringPiece in,
|
|
base::StringPiece key, base::StringPiece value, std::string* out) {
|
|
if (!in.length() || *in.rbegin() != '}')
|
|
return false;
|
|
std::string suffix =
|
|
base::StringPrintf(", \"%s\": \"%s\"}", key.begin(), value.begin());
|
|
out->clear();
|
|
out->reserve(in.length() + suffix.length() - 1);
|
|
out->append(in.data(), in.length() - 1);
|
|
out->append(suffix);
|
|
return true;
|
|
}
|
|
|
|
{% for namespace in config.protocol.namespace %}
|
|
} // namespace {{namespace}}
|
|
{% endfor %}
|