From 54440e87b64b3ae584071c19166f26ddb9bc3a89 Mon Sep 17 00:00:00 2001 From: Philippe G Date: Tue, 4 Jan 2022 17:22:32 -0800 Subject: [PATCH] more crap --- .../spotify/cspot/bell/src/BellSocket.cpp | 21 ++ .../spotify/cspot/bell/src/HTTPClient.cpp | 273 ++++++++++++++++++ components/spotify/cspot/include/PbCommon.h | 42 --- components/spotify/cspot/include/PbReader.h | 42 --- components/spotify/cspot/include/PbWireType.h | 15 - components/spotify/cspot/include/PbWriter.h | 39 --- .../spotify/cspot/include/ProtoHelper.h | 37 --- components/spotify/cspot/src/PbReader.cpp | 116 -------- components/spotify/cspot/src/PbWriter.cpp | 142 --------- components/spotify/cspot/src/Protobuf.cpp | 193 ------------- 10 files changed, 294 insertions(+), 626 deletions(-) create mode 100644 components/spotify/cspot/bell/src/BellSocket.cpp create mode 100644 components/spotify/cspot/bell/src/HTTPClient.cpp delete mode 100644 components/spotify/cspot/include/PbCommon.h delete mode 100644 components/spotify/cspot/include/PbReader.h delete mode 100644 components/spotify/cspot/include/PbWireType.h delete mode 100644 components/spotify/cspot/include/PbWriter.h delete mode 100644 components/spotify/cspot/include/ProtoHelper.h delete mode 100644 components/spotify/cspot/src/PbReader.cpp delete mode 100644 components/spotify/cspot/src/PbWriter.cpp delete mode 100644 components/spotify/cspot/src/Protobuf.cpp diff --git a/components/spotify/cspot/bell/src/BellSocket.cpp b/components/spotify/cspot/bell/src/BellSocket.cpp new file mode 100644 index 00000000..144e9be8 --- /dev/null +++ b/components/spotify/cspot/bell/src/BellSocket.cpp @@ -0,0 +1,21 @@ +// Copyright (c) Kuba SzczodrzyƄski 2021-12-21. + +#include "BellSocket.h" +#include + +void bell::Socket::open(const std::string &url) { + auto *urlStr = url.c_str(); + bool https = urlStr[4] == 's'; + uint16_t port = https ? 443 : 80; + auto *hostname = urlStr + (https ? 8 : 7); + auto *hostnameEnd = strchr(hostname, ':'); + auto *path = strchr(hostname, '/'); + if (hostnameEnd == nullptr) { + hostnameEnd = path; + } else { + port = strtol(hostnameEnd + 1, nullptr, 10); + } + auto hostnameStr = std::string(hostname, (const char *)hostnameEnd); + + this->open(hostnameStr, port); +} diff --git a/components/spotify/cspot/bell/src/HTTPClient.cpp b/components/spotify/cspot/bell/src/HTTPClient.cpp new file mode 100644 index 00000000..e3d2b730 --- /dev/null +++ b/components/spotify/cspot/bell/src/HTTPClient.cpp @@ -0,0 +1,273 @@ +// Copyright (c) Kuba SzczodrzyƄski 2021-12-21. + +#include "HTTPClient.h" +#include "TCPSocket.h" + +using namespace bell; + +struct HTTPClient::HTTPResponse *HTTPClient::execute(const struct HTTPRequest &request) { + auto *response = new HTTPResponse(); + auto *url = request.url.c_str(); + HTTPClient::executeImpl(request, url, response); + return response; +} + +void HTTPClient::executeImpl(const struct HTTPRequest &request, const char *url, struct HTTPResponse *&response) { + bool https = url[4] == 's'; + uint16_t port = https ? 443 : 80; + auto *hostname = url + (https ? 8 : 7); + auto *hostnameEnd = strchr(hostname, ':'); + auto *path = strchr(hostname, '/'); + if (hostnameEnd == nullptr) { + hostnameEnd = path; + } else { + port = strtol(hostnameEnd + 1, nullptr, 10); + } + auto hostnameStr = std::string(hostname, (const char *)hostnameEnd); + + if (https) { + response->socket = std::make_shared(); + } else { + response->socket = std::make_shared(); + } + response->socket->open(hostnameStr, port); + + const char *endl = "\r\n"; + std::stringstream stream; + switch (request.method) { + case HTTPMethod::GET: + stream << "GET "; + break; + case HTTPMethod::POST: + stream << "POST "; + break; + } + stream << path << " HTTP/1.1" << endl; + stream << "Host: " << hostnameStr << ":" << port << endl; + stream << "Accept: */*" << endl; + if (!request.body.empty()) { + stream << "Content-Type: " << request.contentType << endl; + stream << "Content-Length: " << request.body.size() << endl; + } + for (const auto &header : request.headers) { + stream << header.first << ": " << header.second << endl; + } + stream << endl; + stream << request.body; + std::string data = stream.str(); + + size_t len = response->socket->write((uint8_t *)data.c_str(), data.size()); + if (len != data.size()) { + response->close(); + BELL_LOG(error, "http", "Writing failed: wrote %d of %d bytes", len, data.size()); + free(response); + response = nullptr; + return; + } + + response->readHeaders(); + + if (response->isRedirect && (request.maxRedirects < 0 || response->redirectCount < request.maxRedirects)) { + response->redirectCount++; + response->close(); // close the previous socket + HTTPClient::executeImpl(request, response->location.c_str(), response); + } +} + +bool HTTPClient::readHeader(const char *&header, const char *name) { + size_t len = strlen(name); + if (strncasecmp(header, name, len) == 0) { + header += len; + while (*header == ' ') + header++; + return true; + } + return false; +} + +size_t HTTPClient::HTTPResponse::readRaw(char *dst) { + size_t len = this->socket->read((uint8_t *)dst, BUF_SIZE); + // BELL_LOG(debug, "http", "Read %d bytes", len); + this->bodyRead += len; // after reading headers this gets overwritten + dst[len] = '\0'; + return len; +} + +void HTTPClient::HTTPResponse::readHeaders() { + size_t len; + char *line, *lineEnd; + bool complete = false; + std::string lineBuf; + + if (this->buf == nullptr) { // allocate a buffer + this->buf = static_cast(malloc(BUF_SIZE + 1)); + this->bufPtr = this->buf; + } + + // reset everything after a redirect + this->statusCode = 0; + this->contentLength = 0; + this->isChunked = false; + this->isGzip = false; + this->isComplete = false; + this->isRedirect = false; + this->isStreaming = false; + do { + len = this->readRaw(this->buf); + line = this->buf; + do { + lineEnd = strstr(line, "\r\n"); + if (!lineEnd) { + lineBuf += std::string(line, this->buf + len); + break; + } + lineBuf += std::string(line, lineEnd); + if (lineBuf.empty()) { + complete = true; + // if body is present in buf, move the reading pointer + if (lineEnd + 2 < this->buf + len) { + this->bufPtr = lineEnd + 2; + this->bufRemaining = len - (this->bufPtr - this->buf); + this->bodyRead = this->bufRemaining; + this->isStreaming = + !this->isComplete && !this->contentLength && (len < BUF_SIZE || this->socket->poll() == 0); + } + break; + } + + auto *header = lineBuf.c_str(); + if (strncmp(header, "HTTP/", 5) == 0) { + header += 9; // skip "1.1 " + this->statusCode = strtol(header, nullptr, 10); + } else if (readHeader(header, "content-type:")) { + this->contentType = std::string(header); + } else if (readHeader(header, "content-length:")) { + this->contentLength = strtol(header, nullptr, 10); + if (!this->contentLength) + this->isComplete = true; // forbid reading of the body + } else if (readHeader(header, "transfer-encoding:")) { + this->isChunked = strncmp(header, "chunked", 7) == 0; + } else if (readHeader(header, "location:")) { + this->isRedirect = true; + this->location = std::string(header); + } else { + char *colonPtr = (char*) strchr(header, ':'); + if (colonPtr) { + auto *valuePtr = colonPtr + 1; + while (*valuePtr == ' ') + valuePtr++; + *colonPtr = '\0'; + for (auto *p = (char *)header; *p; ++p) // convert header name to lower case + *p = (char)tolower(*p); + this->headers[std::string(header)] = std::string(valuePtr); + } + } + + lineBuf.clear(); + line = lineEnd + 2; // skip \r\n + } while (true); + } while (!complete); +} + +bool HTTPClient::HTTPResponse::skip(size_t len, bool dontRead) { + size_t skip = 0; + if (len > bufRemaining) { + skip = len - bufRemaining; + len = bufRemaining; + } + bufRemaining -= len; + bufPtr += len; + if (!bufRemaining && !dontRead) { // don't read more data after a chunk's \r\n + if (isComplete || (contentLength && bodyRead >= contentLength && !chunkRemaining)) { + isComplete = true; + return false; + } + bufRemaining = this->readRaw(this->buf); + if (!bufRemaining) + return false; // no more data - shouldn't happen for valid responses + bufPtr = this->buf + skip; + bufRemaining -= skip; + if (!contentLength && bufRemaining < BUF_SIZE) { + // no content length set and the TCP buffer is not yielding more data, yet + isStreaming = true; + } + } + return true; +} + +size_t HTTPClient::HTTPResponse::read(char *dst, size_t toRead) { + if (isComplete) { + // end of chunked stream was found OR complete body was read + dst[0] = '\0'; + return 0; + } + auto *dstStart = dst; + size_t read = 0; + while (toRead) { // this loop ends after original toRead + skip(0); // ensure the buffer contains data, wait if necessary + if (isChunked && !chunkRemaining) { + if (*bufPtr == '0') { // all chunks were read *and emitted* + isComplete = true; + break; + } + auto *endPtr = bufPtr; + if (strchr(bufPtr, '\r') == nullptr) { // buf doesn't contain complete chunk size + auto size = std::string(bufPtr, bufPtr + bufRemaining); // take the rest of the buffer + if (!skip(bufRemaining)) // skip the rest, read another buf + break; // -> no more data + endPtr = strchr(bufPtr, '\r'); // find the end of the actual number + if (endPtr == nullptr) // something's wrong + break; // - give up + size += std::string(bufPtr, endPtr); // append the newly read size + chunkRemaining = std::stoul(size, nullptr, 16); // read the hex size + } else { + chunkRemaining = strtol(bufPtr, &endPtr, 16); // read the hex size + } + if (!skip(endPtr - bufPtr + 2)) // skip the size and \r\n + break; // -> no more data, break out of main loop + } else if (contentLength && !chunkRemaining) { + chunkRemaining = contentLength; + } + + while (chunkRemaining && toRead) { + size_t count = std::min(toRead, std::min(bufRemaining, chunkRemaining)); + strncpy(dst, bufPtr, count); + dst += count; // move the dst pointer + read += count; // increment read counter + chunkRemaining -= count; // decrease chunk remaining size + toRead -= count; // decrease local remaining size + if (!skip(count)) { // eat some buffer + toRead = 0; // -> no more data, break out of main loop + break; + } + if (isChunked && !chunkRemaining && !skip(2, isStreaming)) // skip the \r\n for chunked encoding + toRead = 0; // -> no more data, break out of main loop + } + if (isStreaming && !bufRemaining) { // stream with no buffer available, just yield the current chunk + break; + } + } + if (!isChunked && contentLength && !chunkRemaining) + isComplete = true; + // BELL_LOG(debug, "http", "Read %d of %d bytes", bodyRead, contentLength); + dstStart[read] = '\0'; + return read; +} + +std::string HTTPClient::HTTPResponse::readToString() { + if (this->contentLength) { + std::string result(this->contentLength, '\0'); + this->read(result.data(), this->contentLength); + this->close(); + return result; + } + std::string result; + char buffer[BUF_SIZE]; + size_t len; + do { + len = this->read(buffer, BUF_SIZE); + result += std::string(buffer); + } while (len); + this->close(); + return result; +} diff --git a/components/spotify/cspot/include/PbCommon.h b/components/spotify/cspot/include/PbCommon.h deleted file mode 100644 index 5b3eb747..00000000 --- a/components/spotify/cspot/include/PbCommon.h +++ /dev/null @@ -1,42 +0,0 @@ -#ifndef PBCOMMON_H -#define PBCOMMON_H - -#include -#include -#include -#include -class BaseProtobufMessage -{ -private: -public: - bool firstField = true; - uint32_t lastMessagePosition; - void parseFromVector(std::vector const &rawData) - { - auto reader = std::make_shared(rawData); - parseWithReader(reader); - } - void encodeToVector(std::vector &rawData) - { - auto writer = std::make_shared(rawData); - encodeWithWriter(writer); - } - - void parseWithReader(std::shared_ptr reader) - { - firstField = true; - while (reader->next()) - { - if (!decodeField(reader)) - { - reader->skip(); - } else { - firstField = false; - } - } - } - virtual void encodeWithWriter(std::shared_ptr writer) = 0; - virtual bool decodeField(std::shared_ptr reader) = 0; -}; - -#endif \ No newline at end of file diff --git a/components/spotify/cspot/include/PbReader.h b/components/spotify/cspot/include/PbReader.h deleted file mode 100644 index 6d7dec17..00000000 --- a/components/spotify/cspot/include/PbReader.h +++ /dev/null @@ -1,42 +0,0 @@ -#ifndef PBREADER_H -#define PBREADER_H - -#include -#include -#include -#include - -class PbReader -{ -private: - std::vector const &rawData; - uint32_t currentWireValue = 0; - uint64_t skipVarIntDump = 0; - uint32_t nextFieldLength = 0; - int64_t decodeZigzag(uint64_t value); - -public: - PbReader(std::vector const &rawData); - uint32_t maxPosition = 0; - - PbWireType currentWireType = PbWireType::unknown; - uint32_t currentTag = 0; - uint32_t pos = 0; - - template - T decodeVarInt(); - - template - T decodeFixed(); - - template - T decodeSVarInt(); - void decodeString(std::string &target); - void decodeVector(std::vector &target); - - bool next(); - void skip(); - void resetMaxPosition(); -}; - -#endif \ No newline at end of file diff --git a/components/spotify/cspot/include/PbWireType.h b/components/spotify/cspot/include/PbWireType.h deleted file mode 100644 index 60852612..00000000 --- a/components/spotify/cspot/include/PbWireType.h +++ /dev/null @@ -1,15 +0,0 @@ -#ifndef PBWIRETYPE_H -#define PBWIRETYPE_H - -#include - -enum class PbWireType : uint32_t -{ - varint = 0, // int32/64, uint32/64, sint32/64, bool, enum - fixed64 = 1, // fixed64, sfixed64, double - length_delimited = 2, // string, bytes, nested messages, packed repeated fields - fixed32 = 5, // fixed32, sfixed32, float - unknown = 99 -}; - -#endif \ No newline at end of file diff --git a/components/spotify/cspot/include/PbWriter.h b/components/spotify/cspot/include/PbWriter.h deleted file mode 100644 index e6465541..00000000 --- a/components/spotify/cspot/include/PbWriter.h +++ /dev/null @@ -1,39 +0,0 @@ -#ifndef PBWRITER_H -#define PBWRITER_H - -#include -#include -#include -#include - -class PbWriter -{ -private: - std::vector &rawData; - uint32_t pos; - uint32_t msgStartPos = 0; - void encodeVarInt(uint32_t low, uint32_t high, int32_t atIndex = 0); - uint32_t encodeZigzag32(int32_t value); - uint64_t encodeZigzag64(int64_t value); -public: - PbWriter(std::vector &rawData); - - template - void encodeVarInt(T, int32_t atIndex = 0); - template - void encodeFixed(T); - void addSVarInt32(uint32_t tag, int32_t); - void addSVarInt64(uint32_t tag, int64_t); - void addString(uint32_t tag, std::string &target); - void addVector(uint32_t tag, std::vector &target); - - template - void addVarInt(uint32_t tag, T intType); - void addBool(uint32_t tag, bool value); - - void addField(uint32_t tag, PbWireType wiretype); - uint32_t startMessage(); - void finishMessage(uint32_t tag, uint32_t pos); -}; - -#endif \ No newline at end of file diff --git a/components/spotify/cspot/include/ProtoHelper.h b/components/spotify/cspot/include/ProtoHelper.h deleted file mode 100644 index 1b53bb4b..00000000 --- a/components/spotify/cspot/include/ProtoHelper.h +++ /dev/null @@ -1,37 +0,0 @@ -#ifndef PROTOBUF_H -#define PROTOBUF_H -#include -#include -#include "protobuf.h" -#include -#include - -std::optional findFieldWithProtobufTag(AnyRef ref, uint32_t tag); -void decodeField(std::shared_ptr reader, AnyRef any); -void decodeProtobuf(std::shared_ptr reader, AnyRef any); -void encodeProtobuf(std::shared_ptr writer, AnyRef any, uint32_t protobufTag = 0); - -template -std::vector encodePb(T & data) -{ - auto ref = AnyRef::of(&data); - std::vector rawData;; - auto writer = std::make_shared(rawData); - encodeProtobuf(writer, ref); - - return rawData; -} - - -template -T decodePb(std::vector & bytes) -{ - T data = {}; - auto ref = AnyRef::of(&data); - auto writer = std::make_shared(bytes); - decodeProtobuf(writer, ref); - - return data; -} - -#endif \ No newline at end of file diff --git a/components/spotify/cspot/src/PbReader.cpp b/components/spotify/cspot/src/PbReader.cpp deleted file mode 100644 index e216e870..00000000 --- a/components/spotify/cspot/src/PbReader.cpp +++ /dev/null @@ -1,116 +0,0 @@ -#include "PbReader.h" -#include - -PbReader::PbReader(std::vector const &rawData) : rawData(rawData) -{ - maxPosition = rawData.size(); -} - -template -T PbReader::decodeVarInt() -{ - uint8_t byte; - uint_fast8_t bitpos = 0; - uint64_t storago = 0; - do - { - byte = this->rawData[pos]; - pos++; - - storago |= (uint64_t)(byte & 0x7F) << bitpos; - bitpos = (uint_fast8_t)(bitpos + 7); - } while (byte & 0x80); - return static_cast(storago); -} - -template -T PbReader::decodeFixed() -{ - pos += sizeof(T); - return *(T*)(&this->rawData[pos - sizeof(T)]); -} - - -template int32_t PbReader::decodeFixed(); -template int64_t PbReader::decodeFixed(); - -template uint32_t PbReader::decodeVarInt(); -template int64_t PbReader::decodeVarInt(); -template int32_t PbReader::decodeVarInt(); -template bool PbReader::decodeVarInt(); - -void PbReader::resetMaxPosition() -{ - maxPosition = rawData.size(); -} - -void PbReader::decodeString(std::string &target) -{ - nextFieldLength = decodeVarInt(); - target.resize(nextFieldLength); - // std::cout << "rawData.size() = " << rawData.size() << " pos = " << pos << " nextFieldLength =" << nextFieldLength; - // printf("\n%d, \n", currentTag); - // if (pos + nextFieldLength >= rawData.size()) - // { - // std::cout << " \nBAD -- pos + nextFieldLength >= rawData.size() MSVC IS LITERLALLY SHAKING AND CRYING RN"; - // } - // std::cout << std::endl; - std::copy(rawData.begin() + pos, rawData.begin() + pos + nextFieldLength, target.begin()); - pos += nextFieldLength; -} - -void PbReader::decodeVector(std::vector &target) -{ - nextFieldLength = decodeVarInt(); - target.resize(nextFieldLength); - std::copy(rawData.begin() + pos, rawData.begin() + pos + nextFieldLength, target.begin()); - pos += nextFieldLength; -} - -bool PbReader::next() -{ - if (pos >= maxPosition) - return false; - - currentWireValue = decodeVarInt(); - currentTag = currentWireValue >> 3U; - currentWireType = PbWireType(currentWireValue & 0x07U); - return true; -} - -int64_t PbReader::decodeZigzag(uint64_t value) -{ - return static_cast((value >> 1U) ^ static_cast(-static_cast(value & 1U))); -} - -template -T PbReader::decodeSVarInt() -{ - skipVarIntDump = decodeVarInt(); - return static_cast(decodeZigzag(skipVarIntDump)); -} - -template int32_t PbReader::decodeSVarInt(); -template int64_t PbReader::decodeSVarInt(); - -void PbReader::skip() -{ - switch (currentWireType) - { - case PbWireType::varint: - skipVarIntDump = decodeVarInt(); - break; - case PbWireType::fixed64: - pos += 8; - break; - case PbWireType::length_delimited: - nextFieldLength = decodeVarInt(); - pos += nextFieldLength; - break; - case PbWireType::fixed32: - pos += 4; - break; - default: - break; - } -} diff --git a/components/spotify/cspot/src/PbWriter.cpp b/components/spotify/cspot/src/PbWriter.cpp deleted file mode 100644 index b21a80cc..00000000 --- a/components/spotify/cspot/src/PbWriter.cpp +++ /dev/null @@ -1,142 +0,0 @@ -#include "PbWriter.h" - -PbWriter::PbWriter(std::vector &rawData) : rawData(rawData) -{ -} - -void PbWriter::encodeVarInt(uint32_t low, uint32_t high, int32_t indexOffset) -{ - size_t i = 0; - uint8_t byte = (uint8_t)(low & 0x7F); - low >>= 7; - - while (i < 4 && (low != 0 || high != 0)) - { - byte |= 0x80; - rawData.insert(rawData.end() + indexOffset, byte); - i++; - byte = (uint8_t)(low & 0x7F); - low >>= 7; - } - - if (high) - { - byte = (uint8_t)(byte | ((high & 0x07) << 4)); - high >>= 3; - - while (high) - { - byte |= 0x80; - rawData.insert(rawData.end() + indexOffset, byte); - i++; - byte = (uint8_t)(high & 0x7F); - high >>= 7; - } - } - - rawData.insert(rawData.end() + indexOffset, byte); -} - -template void PbWriter::encodeVarInt(uint8_t, int32_t); -template void PbWriter::encodeVarInt(uint32_t, int32_t); -template void PbWriter::encodeVarInt(uint64_t, int32_t); -template void PbWriter::encodeVarInt(long long, int32_t); - -template -void PbWriter::encodeVarInt(T data, int32_t offset) -{ - auto value = static_cast(data); - if (value <= 0x7F) - { - rawData.insert(rawData.end() + offset, (uint8_t)value); - } - else - { - encodeVarInt((uint32_t)value, (uint32_t)(value >> 32), offset); - } -} - -uint32_t PbWriter::encodeZigzag32(int32_t value) { - return (static_cast(value) << 1U) ^ static_cast(-static_cast(static_cast(value) >> 31U)); -} - -uint64_t PbWriter::encodeZigzag64(int64_t value) { - return (static_cast(value) << 1U) ^ static_cast(-static_cast(static_cast(value) >> 63U)); -} - -void PbWriter::addSVarInt32(uint32_t tag, int32_t data) { - auto val = encodeZigzag32(data); - addVarInt(tag, val); -} - -template -void PbWriter::encodeFixed(T data) { - auto val = reinterpret_cast(&data); - rawData.insert(rawData.end(), val, val + sizeof(T)); -} - -template void PbWriter::encodeFixed(int64_t); -template void PbWriter::encodeFixed(int32_t); - -void PbWriter::addSVarInt64(uint32_t tag, int64_t data) { - auto val = encodeZigzag64(data); - addVarInt(tag, val); -} - -void PbWriter::addString(uint32_t tag, std::string &target) -{ - addField(tag, PbWireType::length_delimited); - uint32_t stringSize = target.size(); - encodeVarInt(stringSize); - - rawData.insert(rawData.end(), target.begin(), target.end()); -} - -void PbWriter::addVector(uint32_t tag, std::vector &target) -{ - addField(tag, PbWireType::length_delimited); - uint32_t vectorSize = target.size(); - encodeVarInt(vectorSize); - - rawData.insert(rawData.end(), target.begin(), target.end()); -} - -template -void PbWriter::addVarInt(uint32_t tag, T intType) -{ - addField(tag, PbWireType::varint); - encodeVarInt(intType); -} - -void PbWriter::addBool(uint32_t tag, bool value) -{ - addField(tag, PbWireType::varint); - rawData.push_back(char(value)); -} - -template void PbWriter::addVarInt(uint32_t, uint8_t); -template void PbWriter::addVarInt(uint32_t, uint32_t); -template void PbWriter::addVarInt(uint32_t, uint64_t); -template void PbWriter::addVarInt(uint32_t, int64_t); -template void PbWriter::addVarInt(uint32_t, bool); - -void PbWriter::addField(uint32_t tag, PbWireType wiretype) -{ - const uint32_t value = (tag << 3U) | uint32_t(wiretype); - encodeVarInt(value); -} - -uint32_t PbWriter::startMessage() -{ - return rawData.size(); -} - -void PbWriter::finishMessage(uint32_t tag, uint32_t lastMessagePosition) -{ - uint32_t finalMessageSize = rawData.size() - lastMessagePosition; - uint32_t msgHeader = (tag << 3U) | uint32_t(PbWireType::length_delimited); - - int32_t offset = -finalMessageSize; - encodeVarInt(msgHeader, offset); - encodeVarInt(finalMessageSize, offset); -} diff --git a/components/spotify/cspot/src/Protobuf.cpp b/components/spotify/cspot/src/Protobuf.cpp deleted file mode 100644 index a725e797..00000000 --- a/components/spotify/cspot/src/Protobuf.cpp +++ /dev/null @@ -1,193 +0,0 @@ -#include "ProtoHelper.h" - - -std::optional findFieldWithProtobufTag(AnyRef ref, uint32_t tag) -{ - auto info = ref.reflectType(); - for (int i = 0; i < info->fields.size(); i++) - { - - if (tag == info->fields[i].protobufTag) - { - return std::make_optional(ref.getField(i)); - } - } - - return std::nullopt; -} - -void decodeField(std::shared_ptr reader, AnyRef any) -{ - auto fieldInfo = any.reflectType(); - - if (fieldInfo->kind == ReflectTypeKind::Optional) - { - auto optionalRef = AnyOptionalRef(any); - optionalRef.emplaceEmpty(); - return decodeField(reader, optionalRef.get()); - } - - if (fieldInfo->kind == ReflectTypeKind::Class) - { - // Handle submessage - auto lastMaxPosition = reader->maxPosition; - auto messageSize = reader->decodeVarInt(); - - reader->maxPosition = messageSize + reader->pos; - while (reader->next()) - { - auto res = findFieldWithProtobufTag(any, reader->currentTag); - if (res.has_value()) - { - decodeField(reader, res.value()); - } - else - { - reader->skip(); - } - } - reader->maxPosition = lastMaxPosition; - return; - } else if (any.is>()) - { - reader->decodeVector(*any.as>()); - } - // Handle repeated - else if (fieldInfo->kind == ReflectTypeKind::Vector) - { - auto aVec = AnyVectorRef(any); - aVec.emplace_back(); - auto value = aVec.at(aVec.size() - 1); - auto valInfo = value.reflectType(); - - // Represents packed repeated encoding - if (valInfo->kind == ReflectTypeKind::Primitive && !value.is() && !value.is>()) - { - // *any.as() = reader->decodeVarInt(); - reader->skip(); - } - else - { - decodeField(reader, value); - } - } - else if (fieldInfo->kind == ReflectTypeKind::Enum) - { - *any.as() = reader->decodeVarInt(); - } - else if (any.is()) - { - reader->decodeString(*any.as()); - } - else if (any.is()) - { - *any.as() = reader->decodeVarInt(); - } - else if (any.is()) - { - *any.as() = reader->decodeVarInt(); - } - else if (any.is()) - { - *any.as() = reader->decodeVarInt(); - } - else if (any.is()) - { - *any.as() = reader->decodeVarInt(); - } - else - { - reader->skip(); - } -} - -void decodeProtobuf(std::shared_ptr reader, AnyRef any) -{ - while (reader->next()) - { - auto res = findFieldWithProtobufTag(any, reader->currentTag); - if (res.has_value()) - { - decodeField(reader, res.value()); - } - else - { - reader->skip(); - } - } -} - -void encodeProtobuf(std::shared_ptr writer, AnyRef any, uint32_t protobufTag) -{ - auto info = any.reflectType(); - - // Handle optionals, only encode if have value - if (info->kind == ReflectTypeKind::Optional) - { - auto optionalRef = AnyOptionalRef(any); - if (!optionalRef.has_value()) - { - return; - } - else - { - return encodeProtobuf(writer, optionalRef.get(), protobufTag); - } - } - if (info->kind == ReflectTypeKind::Class) - { - uint32_t startMsgPosition; - // 0 - default value, indicating top level message - if (protobufTag > 0) - { - startMsgPosition = writer->startMessage(); - } - - for (int i = 0; i < info->fields.size(); i++) - { - auto field = any.getField(i); - encodeProtobuf(writer, field, info->fields[i].protobufTag); - } - - if (protobufTag > 0) - { - writer->finishMessage(protobufTag, startMsgPosition); - } - } else if (any.is>()) - { - writer->addVector(protobufTag, *any.as>()); - } - else if (info->kind == ReflectTypeKind::Vector) { - auto aVec = AnyVectorRef(any); - auto size = aVec.size(); - for (size_t i = 0; i < size; i++) - { - auto valueAt = aVec.at(i); - encodeProtobuf(writer, valueAt, protobufTag); - } - } - else if (info->kind == ReflectTypeKind::Enum) { - writer->addVarInt(protobufTag, *any.as()); - } - else if (info->kind == ReflectTypeKind::Primitive) - { - if (any.is()) - { - writer->addString(protobufTag, *any.as()); - } - else if (any.is()) - { - writer->addVarInt(protobufTag, *any.as()); - } - else if (any.is()) - { - writer->addVarInt(protobufTag, *any.as()); - } - else if (any.is()) { - writer->addVarInt(protobufTag, *any.as()); - } else if (any.is()) - { - writer->addVarInt(protobufTag, *any.as()); - } - } -} \ No newline at end of file