diff --git a/runtime-light/stdlib/rpc/rpc-api.h b/runtime-light/stdlib/rpc/rpc-api.h index 3bc683594e..65d1a1dd73 100644 --- a/runtime-light/stdlib/rpc/rpc-api.h +++ b/runtime-light/stdlib/rpc/rpc-api.h @@ -112,7 +112,7 @@ inline bool f$store_string(const string& v) noexcept { } inline bool f$store_string2(const string& v) noexcept { - tl::string{.value = {v.c_str(), v.size()}}.store2(RpcServerInstanceState::get().tl_storer); + tl2::string{.value = {v.c_str(), v.size()}}.store(RpcServerInstanceState::get().tl_storer); return true; } @@ -175,7 +175,7 @@ inline string f$fetch_string() noexcept { } inline string f$fetch_string2() noexcept { - if (tl::string val{}; val.fetch2(RpcServerInstanceState::get().tl_fetcher)) [[likely]] { + if (tl2::string val{}; val.fetch(RpcServerInstanceState::get().tl_fetcher)) [[likely]] { return {val.value.data(), static_cast(val.value.size())}; } THROW_EXCEPTION(kphp::rpc::exception::cant_fetch_string::make()); diff --git a/runtime-light/tl/tl-functions.cpp b/runtime-light/tl/tl-functions.cpp index d57a113232..565c356110 100644 --- a/runtime-light/tl/tl-functions.cpp +++ b/runtime-light/tl/tl-functions.cpp @@ -18,11 +18,11 @@ bool K2InvokeJobWorker::fetch(tl::fetcher& tlf) noexcept { tl::magic magic{}; tl::mask flags{}; bool ok{magic.fetch(tlf) && magic.expect(K2_INVOKE_JOB_WORKER_MAGIC)}; - ok &= flags.fetch(tlf); - ok &= image_id.fetch(tlf); - ok &= job_id.fetch(tlf); - ok &= timeout_ns.fetch(tlf); - ok &= body.fetch(tlf); + ok = ok && flags.fetch(tlf); + ok = ok && image_id.fetch(tlf); + ok = ok && job_id.fetch(tlf); + ok = ok && timeout_ns.fetch(tlf); + ok = ok && body.fetch(tlf); ignore_answer = static_cast(flags.value & IGNORE_ANSWER_FLAG); return ok; } @@ -42,14 +42,14 @@ bool K2InvokeHttp::fetch(tl::fetcher& tlf) noexcept { tl::magic magic{}; tl::mask flags{}; bool ok{magic.fetch(tlf) && magic.expect(K2_INVOKE_HTTP_MAGIC)}; - ok &= flags.fetch(tlf); - ok &= connection.fetch(tlf); - ok &= version.fetch(tlf); - ok &= method.fetch(tlf); - ok &= uri.fetch(tlf); - ok &= headers.fetch(tlf); + ok = ok && flags.fetch(tlf); + ok = ok && connection.fetch(tlf); + ok = ok && version.fetch(tlf); + ok = ok && method.fetch(tlf); + ok = ok && uri.fetch(tlf); + ok = ok && headers.fetch(tlf); const auto opt_body{tlf.fetch_bytes(tlf.remaining())}; - ok &= opt_body.has_value(); + ok = ok && opt_body.has_value(); body = opt_body.value_or(std::span{}); diff --git a/runtime-light/tl/tl-functions.h b/runtime-light/tl/tl-functions.h index 9340eea470..8674cdfc3d 100644 --- a/runtime-light/tl/tl-functions.h +++ b/runtime-light/tl/tl-functions.h @@ -314,14 +314,14 @@ class K2InvokeRpc final { bool fetch(tl::fetcher& tlf) noexcept { tl::magic magic{}; bool ok{magic.fetch(tlf) && magic.expect(K2_INVOKE_RPC_MAGIC)}; - ok &= flags.fetch(tlf); - ok &= query_id.fetch(tlf); - ok &= net_pid.fetch(tlf); + ok = ok && flags.fetch(tlf); + ok = ok && query_id.fetch(tlf); + ok = ok && net_pid.fetch(tlf); if (static_cast(flags.value & ACTOR_ID_FLAG)) { - ok &= opt_actor_id.emplace().fetch(tlf); + ok = ok && opt_actor_id.emplace().fetch(tlf); } if (static_cast(flags.value & EXTRA_FLAG)) { - ok &= opt_extra.emplace().fetch(tlf); + ok = ok && opt_extra.emplace().fetch(tlf); } const auto opt_query{tlf.fetch_bytes(tlf.remaining())}; query = opt_query.value_or(std::span{}); diff --git a/runtime-light/tl/tl-types.cpp b/runtime-light/tl/tl-types.cpp index 6797c0e6c0..46c83bb095 100644 --- a/runtime-light/tl/tl-types.cpp +++ b/runtime-light/tl/tl-types.cpp @@ -7,6 +7,7 @@ #include #include #include +#include #include #include "runtime-light/stdlib/diagnostics/logs.h" @@ -25,22 +26,19 @@ bool string::fetch(tl::fetcher& tlf) noexcept { uint8_t size_len{}; uint64_t string_len{}; switch (first_byte) { - case LARGE_STRING_MAGIC: { - if (tlf.remaining() < LARGE_STRING_SIZE_LEN) [[unlikely]] { + case HUGE_STRING_MAGIC: { + if (tlf.remaining() < HUGE_STRING_SIZE_LEN) [[unlikely]] { return false; } - size_len = LARGE_STRING_SIZE_LEN + 1; - const auto first{static_cast(*tlf.fetch_trivial())}; - const auto second{static_cast(*tlf.fetch_trivial()) << 8}; - const auto third{static_cast(*tlf.fetch_trivial()) << 16}; - const auto fourth{static_cast(*tlf.fetch_trivial()) << 24}; - const auto fifth{static_cast(*tlf.fetch_trivial()) << 32}; - const auto sixth{static_cast(*tlf.fetch_trivial()) << 40}; - const auto seventh{static_cast(*tlf.fetch_trivial()) << 48}; - string_len = first | second | third | fourth | fifth | sixth | seventh; + size_len = HUGE_STRING_SIZE_LEN + 1; + auto len_bytes{*tlf.fetch_bytes(HUGE_STRING_SIZE_LEN)}; + string_len = static_cast(len_bytes[0]) | (static_cast(len_bytes[1]) << 8) | (static_cast(len_bytes[2]) << 16) | + (static_cast(len_bytes[3]) << 24) | (static_cast(len_bytes[4]) << 32) | (static_cast(len_bytes[5]) << 40) | + (static_cast(len_bytes[6]) << 48); if (string_len <= MEDIUM_STRING_MAX_LEN) [[unlikely]] { kphp::log::warning("large string's length is less than (1 << 24) - 1 (length = {})", string_len); + return false; } break; } @@ -49,18 +47,17 @@ bool string::fetch(tl::fetcher& tlf) noexcept { return false; } size_len = MEDIUM_STRING_SIZE_LEN + 1; - const auto first{static_cast(*tlf.fetch_trivial())}; - const auto second{static_cast(*tlf.fetch_trivial()) << 8}; - const auto third{static_cast(*tlf.fetch_trivial()) << 16}; - string_len = first | second | third; + auto len_bytes{*tlf.fetch_bytes(MEDIUM_STRING_SIZE_LEN)}; + string_len = static_cast(len_bytes[0]) | (static_cast(len_bytes[1]) << 8) | (static_cast(len_bytes[2]) << 16); - if (string_len <= SMALL_STRING_MAX_LEN) [[unlikely]] { + if (string_len <= TINY_STRING_MAX_LEN) [[unlikely]] { kphp::log::warning("long string's length is less than 254 (length = {})", string_len); + return false; } break; } default: { - size_len = SMALL_STRING_SIZE_LEN; + size_len = TINY_STRING_SIZE_LEN; string_len = static_cast(first_byte); break; } @@ -83,21 +80,27 @@ void string::store(tl::storer& tls) const noexcept { const char* str_buf{value.data()}; size_t str_len{value.size()}; uint8_t size_len{}; - if (str_len <= SMALL_STRING_MAX_LEN) { - size_len = SMALL_STRING_SIZE_LEN; + if (str_len <= TINY_STRING_MAX_LEN) { + size_len = TINY_STRING_SIZE_LEN; tls.store_trivial(str_len); } else if (str_len <= MEDIUM_STRING_MAX_LEN) { size_len = MEDIUM_STRING_SIZE_LEN + 1; tls.store_trivial(MEDIUM_STRING_MAGIC); - tls.store_trivial(str_len & 0xff); - tls.store_trivial((str_len >> 8) & 0xff); - tls.store_trivial((str_len >> 16) & 0xff); + std::array len_bytes{static_cast(str_len & 0xff), static_cast((str_len >> 8) & 0xff), + static_cast((str_len >> 16) & 0xff)}; + tls.store_bytes(len_bytes); + } else if (str_len <= HUGE_STRING_MAX_LEN) { + size_len = HUGE_STRING_SIZE_LEN + 1; + tls.store_trivial(HUGE_STRING_MAGIC); + std::array len_bytes{static_cast(str_len & 0xff), static_cast((str_len >> 8) & 0xff), + static_cast((str_len >> 16) & 0xff), static_cast((str_len >> 24) & 0xff), + static_cast((str_len >> 32) & 0xff), static_cast((str_len >> 40) & 0xff), + static_cast((str_len >> 48) & 0xff)}; + tls.store_bytes(len_bytes); } else { - kphp::log::warning("large strings aren't supported"); - size_len = SMALL_STRING_SIZE_LEN; - str_len = 0; - tls.store_trivial(str_len); + kphp::log::error("string length exceeds maximum allowed length: max allowed -> {}, actual -> {}", HUGE_STRING_MAX_LEN, str_len); } + tls.store_bytes({reinterpret_cast(str_buf), str_len}); const auto total_len{size_len + str_len}; @@ -108,90 +111,6 @@ void string::store(tl::storer& tls) const noexcept { tls.store_bytes({reinterpret_cast(padding_array.data()), padding}); } -bool string::fetch2_len(tl::fetcher& tlf, uint64_t& string_len) noexcept { - uint8_t first_byte{}; - if (const auto opt_first_byte{tlf.fetch_trivial()}; opt_first_byte) [[likely]] { - first_byte = *opt_first_byte; - } else { - return false; - } - - switch (first_byte) { - case LARGE_STRING_MAGIC: { - if (tlf.remaining() < 8) [[unlikely]] { - return false; - } - const auto first{static_cast(*tlf.fetch_trivial())}; - const auto second{static_cast(*tlf.fetch_trivial()) << 8}; - const auto third{static_cast(*tlf.fetch_trivial()) << 16}; - const auto fourth{static_cast(*tlf.fetch_trivial()) << 24}; - const auto fifth{static_cast(*tlf.fetch_trivial()) << 32}; - const auto sixth{static_cast(*tlf.fetch_trivial()) << 40}; - const auto seventh{static_cast(*tlf.fetch_trivial()) << 48}; - const auto eighth{static_cast(*tlf.fetch_trivial()) << 56}; - string_len = first | second | third | fourth | fifth | sixth | seventh | eighth; - // we allow non-canonical length to speed up some rare implementations - return true; - } - case MEDIUM_STRING_MAGIC: { - if (tlf.remaining() < 2) [[unlikely]] { - return false; - } - const auto first{static_cast(*tlf.fetch_trivial())}; - const auto second{static_cast(*tlf.fetch_trivial()) << 8}; - string_len = MEDIUM_STRING_MAGIC + (first | second); - return true; - } - default: { - string_len = static_cast(first_byte); - return true; - } - } -} - -bool string::fetch2(tl::fetcher& tlf) noexcept { - uint64_t string_len{}; - if (!string::fetch2_len(tlf, string_len)) { - return false; - } - if (tlf.remaining() < string_len) [[unlikely]] { - return false; - } - - value = {reinterpret_cast(std::next(tlf.view().data(), tlf.pos())), static_cast(string_len)}; - tlf.adjust(string_len); - return true; -} - -void string::store2_len(tl::storer& tls, uint64_t str_len) noexcept { - if (str_len < MEDIUM_STRING_MAGIC) { - tls.store_trivial(str_len); - return; - } - if (str_len < MEDIUM_STRING_MAGIC + static_cast(1 << 16)) { - str_len -= MEDIUM_STRING_MAGIC; - tls.store_trivial(MEDIUM_STRING_MAGIC); - tls.store_trivial(str_len & 0xff); - tls.store_trivial((str_len >> 8) & 0xff); - return; - } - tls.store_trivial(LARGE_STRING_MAGIC); - tls.store_trivial(str_len & 0xff); - tls.store_trivial((str_len >> 8) & 0xff); - tls.store_trivial((str_len >> 16) & 0xff); - tls.store_trivial((str_len >> 24) & 0xff); - tls.store_trivial((str_len >> 32) & 0xff); - tls.store_trivial((str_len >> 40) & 0xff); - tls.store_trivial((str_len >> 48) & 0xff); - tls.store_trivial((str_len >> 56) & 0xff); -} - -void string::store2(tl::storer& tls) const noexcept { - uint64_t str_len = value.size(); - string::store2_len(tls, str_len); - tls.store_bytes({reinterpret_cast(value.data()), str_len}); -} - bool CertInfoItem::fetch(tl::fetcher& tlf) noexcept { tl::magic magic{}; if (!magic.fetch(tlf)) [[unlikely]] { @@ -230,28 +149,28 @@ bool CertInfoItem::fetch(tl::fetcher& tlf) noexcept { bool rpcInvokeReqExtra::fetch(tl::fetcher& tlf) noexcept { bool ok{flags.fetch(tlf)}; if (ok && static_cast(flags.value & WAIT_BINLOG_POS_FLAG)) { - ok &= opt_wait_binlog_pos.emplace().fetch(tlf); + ok = ok && opt_wait_binlog_pos.emplace().fetch(tlf); } if (ok && static_cast(flags.value & STRING_FORWARD_KEYS_FLAG)) { - ok &= opt_string_forward_keys.emplace().fetch(tlf); + ok = ok && opt_string_forward_keys.emplace().fetch(tlf); } if (ok && static_cast(flags.value & INT_FORWARD_KEYS_FLAG)) { - ok &= opt_int_forward_keys.emplace().fetch(tlf); + ok = ok && opt_int_forward_keys.emplace().fetch(tlf); } if (ok && static_cast(flags.value & STRING_FORWARD_FLAG)) { - ok &= opt_string_forward.emplace().fetch(tlf); + ok = ok && opt_string_forward.emplace().fetch(tlf); } if (ok && static_cast(flags.value & INT_FORWARD_FLAG)) { - ok &= opt_int_forward.emplace().fetch(tlf); + ok = ok && opt_int_forward.emplace().fetch(tlf); } if (ok && static_cast(flags.value & CUSTOM_TIMEOUT_MS_FLAG)) { - ok &= opt_custom_timeout_ms.emplace().fetch(tlf); + ok = ok && opt_custom_timeout_ms.emplace().fetch(tlf); } if (ok && static_cast(flags.value & SUPPORTED_COMPRESSION_VERSION_FLAG)) { - ok &= opt_supported_compression_version.emplace().fetch(tlf); + ok = ok && opt_supported_compression_version.emplace().fetch(tlf); } if (ok && static_cast(flags.value & RANDOM_DELAY_FLAG)) { - ok &= opt_random_delay.emplace().fetch(tlf); + ok = ok && opt_random_delay.emplace().fetch(tlf); } return_binlog_pos = static_cast(flags.value & RETURN_BINLOG_POS_FLAG); @@ -327,3 +246,63 @@ size_t rpcReqResultExtra::footprint() const noexcept { } } // namespace tl + +namespace tl2 { + +bool string::fetch(tl::fetcher& tlf) noexcept { + uint8_t first_byte{}; + if (const auto opt_first_byte{tlf.fetch_trivial()}; opt_first_byte) [[likely]] { + first_byte = *opt_first_byte; + } else { + return false; + } + + uint64_t string_len{}; + switch (first_byte) { + case HUGE_STRING_MAGIC: { + if (tlf.remaining() < HUGE_STRING_SIZE_LEN) [[unlikely]] { + return false; + } + // we allow non-canonical length to speed up some rare implementations + string_len = *tlf.fetch_trivial(); + break; + } + case MEDIUM_STRING_MAGIC: { + if (tlf.remaining() < MEDIUM_STRING_SIZE_LEN) [[unlikely]] { + return false; + } + string_len = MEDIUM_STRING_MAGIC + *tlf.fetch_trivial(); + break; + } + default: { + string_len = static_cast(first_byte); + break; + } + } + + if (auto remaining{tlf.remaining()}; remaining < string_len) [[unlikely]] { + kphp::log::warning("not enough space in buffer to fetch string: required {} bytes, remain {} bytes", string_len, remaining); + return false; + } + + value = {reinterpret_cast(std::next(tlf.view().data(), tlf.pos())), static_cast(string_len)}; + tlf.adjust(string_len); + return true; +} + +void string::store(tl::storer& tls) const noexcept { + const size_t str_len{value.size()}; + + if (str_len <= TINY_STRING_MAX_LEN) { + tls.store_trivial(str_len); + } else if (str_len <= MEDIUM_STRING_MAX_LEN) { + tls.store_trivial(MEDIUM_STRING_MAGIC); + tls.store_trivial(str_len - MEDIUM_STRING_MAGIC); + } else { + tls.store_trivial(HUGE_STRING_MAGIC); + tls.store_trivial(str_len); + } + tls.store_bytes({reinterpret_cast(value.data()), str_len}); +} + +} // namespace tl2 diff --git a/runtime-light/tl/tl-types.h b/runtime-light/tl/tl-types.h index 6e196cb4e5..94fef84975 100644 --- a/runtime-light/tl/tl-types.h +++ b/runtime-light/tl/tl-types.h @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -355,15 +356,15 @@ struct Either final { }; class string final { - static constexpr auto SMALL_STRING_SIZE_LEN = 1; + static constexpr auto TINY_STRING_SIZE_LEN = 1; static constexpr auto MEDIUM_STRING_SIZE_LEN = 3; - static constexpr auto LARGE_STRING_SIZE_LEN = 7; + static constexpr auto HUGE_STRING_SIZE_LEN = 7; - static constexpr uint64_t SMALL_STRING_MAX_LEN = 253; + static constexpr uint64_t TINY_STRING_MAX_LEN = 253; static constexpr uint64_t MEDIUM_STRING_MAX_LEN = (static_cast(1) << 24) - 1; - static constexpr uint64_t LARGE_STRING_MAX_LEN = (static_cast(1) << 56) - 1; + static constexpr uint64_t HUGE_STRING_MAX_LEN = (static_cast(1) << 56) - 1; - static constexpr uint8_t LARGE_STRING_MAGIC = 0xff; + static constexpr uint8_t HUGE_STRING_MAGIC = 0xff; static constexpr uint8_t MEDIUM_STRING_MAGIC = 0xfe; public: @@ -374,26 +375,20 @@ class string final { void store(tl::storer& tls) const noexcept; constexpr size_t footprint() const noexcept { - size_t str_len{value.size()}; + const size_t str_len{value.size()}; size_t size_len{}; - if (str_len <= SMALL_STRING_MAX_LEN) { - size_len = SMALL_STRING_SIZE_LEN; + if (str_len <= TINY_STRING_MAX_LEN) { + size_len = TINY_STRING_SIZE_LEN; } else if (str_len <= MEDIUM_STRING_MAX_LEN) { size_len = MEDIUM_STRING_SIZE_LEN + 1; } else { - size_len = LARGE_STRING_SIZE_LEN + 1; + size_len = HUGE_STRING_SIZE_LEN + 1; } const auto total_len{size_len + str_len}; const auto total_len_with_padding{(total_len + 3) & ~3}; return total_len_with_padding; } - - // TL2 functions are here for now - static bool fetch2_len(tl::fetcher& tlf, uint64_t& string_len) noexcept; - bool fetch2(tl::fetcher& tlf) noexcept; - static void store2_len(tl::storer& tls, uint64_t string_len) noexcept; - void store2(tl::storer& tls) const noexcept; }; struct String final { @@ -706,11 +701,7 @@ class K2JobWorkerResponse final { bool fetch(tl::fetcher& tlf) noexcept { tl::magic magic{}; - bool ok{magic.fetch(tlf) && magic.expect(MAGIC)}; - ok &= tl::mask{}.fetch(tlf); - ok &= job_id.fetch(tlf); - ok &= body.fetch(tlf); - return ok; + return magic.fetch(tlf) && magic.expect(MAGIC) && tl::mask{}.fetch(tlf) && job_id.fetch(tlf) && body.fetch(tlf); } void store(tl::storer& tls) const noexcept { @@ -871,14 +862,14 @@ class httpUri final { bool ok{flags.fetch(tlf)}; if (ok && static_cast(flags.value & SCHEME_FLAG)) [[likely]] { - ok &= opt_scheme.emplace().fetch(tlf); + ok = ok && opt_scheme.emplace().fetch(tlf); } if (ok && static_cast(flags.value & HOST_FLAG)) { - ok &= opt_host.emplace().fetch(tlf); + ok = ok && opt_host.emplace().fetch(tlf); } - ok &= path.fetch(tlf); + ok = ok && path.fetch(tlf); if (ok && static_cast(flags.value & QUERY_FLAG)) { - ok &= opt_query.emplace().fetch(tlf); + ok = ok && opt_query.emplace().fetch(tlf); } return ok; } @@ -911,11 +902,7 @@ struct httpConnection final { tl::i32 remote_port{}; bool fetch(tl::fetcher& tlf) noexcept { - bool ok{server_addr.fetch(tlf)}; - ok &= server_port.fetch(tlf); - ok &= remote_addr.fetch(tlf); - ok &= remote_port.fetch(tlf); - return ok; + return server_addr.fetch(tlf) && server_port.fetch(tlf) && remote_addr.fetch(tlf) && remote_port.fetch(tlf); } }; @@ -1136,8 +1123,7 @@ class InterComponentSessionResponseHeader final { bool fetch(tl::fetcher& tlf) noexcept { tl::magic magic{}; - bool ok{magic.fetch(tlf) && magic.expect(INTER_COMPONENT_SESSION_RESPONSE_HEADER_MAGIC) && id.fetch(tlf) && size.fetch(tlf)}; - return ok; + return magic.fetch(tlf) && magic.expect(INTER_COMPONENT_SESSION_RESPONSE_HEADER_MAGIC) && id.fetch(tlf) && size.fetch(tlf); } constexpr size_t footprint() const noexcept { @@ -1156,8 +1142,7 @@ class WebError final { bool fetch(tl::fetcher& tlf) noexcept { tl::magic magic{}; - bool ok{magic.fetch(tlf) && magic.expect(WEB_ERROR_MAGIC) && code.fetch(tlf) && description.fetch(tlf)}; - return ok; + return magic.fetch(tlf) && magic.expect(WEB_ERROR_MAGIC) && code.fetch(tlf) && description.fetch(tlf); } constexpr size_t footprint() const noexcept { @@ -1238,8 +1223,7 @@ class WebTransferGetPropertiesResultOk final { bool fetch(tl::fetcher& tlf) noexcept { tl::magic magic{}; - bool ok{magic.fetch(tlf) && magic.expect(WEB_TRANSFER_GET_PROPERTIES_RESULT_OK_MAGIC) && properties.fetch(tlf)}; - return ok; + return magic.fetch(tlf) && magic.expect(WEB_TRANSFER_GET_PROPERTIES_RESULT_OK_MAGIC) && properties.fetch(tlf); } constexpr size_t footprint() const noexcept { @@ -1268,8 +1252,7 @@ class SimpleWebTransferOpenResultOk final { bool fetch(tl::fetcher& tlf) noexcept { tl::magic magic{}; - bool ok{magic.fetch(tlf) && magic.expect(SIMPLE_WEB_TRANSFER_OPEN_RESULT_OK_MAGIC) && descriptor.fetch(tlf)}; - return ok; + return magic.fetch(tlf) && magic.expect(SIMPLE_WEB_TRANSFER_OPEN_RESULT_OK_MAGIC) && descriptor.fetch(tlf); } constexpr size_t footprint() const noexcept { @@ -1283,8 +1266,7 @@ class SimpleWebTransferResponseResultOk final { public: bool fetch(tl::fetcher& tlf) noexcept { tl::magic magic{}; - bool ok{magic.fetch(tlf) && magic.expect(SIMPLE_WEB_TRANSFER_RESPONSE_RESULT_OK_MAGIC)}; - return ok; + return magic.fetch(tlf) && magic.expect(SIMPLE_WEB_TRANSFER_RESPONSE_RESULT_OK_MAGIC); } constexpr size_t footprint() const noexcept { @@ -1298,8 +1280,7 @@ class SimpleWebTransferCloseResultOk final { public: bool fetch(tl::fetcher& tlf) noexcept { tl::magic magic{}; - bool ok{magic.fetch(tlf) && magic.expect(SIMPLE_WEB_TRANSFER_CLOSE_RESULT_OK_MAGIC)}; - return ok; + return magic.fetch(tlf) && magic.expect(SIMPLE_WEB_TRANSFER_CLOSE_RESULT_OK_MAGIC); } constexpr size_t footprint() const noexcept { @@ -1313,8 +1294,7 @@ class SimpleWebTransferResetResultOk final { public: bool fetch(tl::fetcher& tlf) noexcept { tl::magic magic{}; - bool ok{magic.fetch(tlf) && magic.expect(SIMPLE_WEB_TRANSFER_RESET_RESULT_OK_MAGIC)}; - return ok; + return magic.fetch(tlf) && magic.expect(SIMPLE_WEB_TRANSFER_RESET_RESULT_OK_MAGIC); } constexpr size_t footprint() const noexcept { @@ -1344,8 +1324,7 @@ class CompositeWebTransferOpenResultOk final { bool fetch(tl::fetcher& tlf) noexcept { tl::magic magic{}; - bool ok{magic.fetch(tlf) && magic.expect(COMPOSITE_WEB_TRANSFER_OPEN_RESULT_OK_MAGIC) && descriptor.fetch(tlf)}; - return ok; + return magic.fetch(tlf) && magic.expect(COMPOSITE_WEB_TRANSFER_OPEN_RESULT_OK_MAGIC) && descriptor.fetch(tlf); } constexpr size_t footprint() const noexcept { @@ -1359,8 +1338,7 @@ class CompositeWebTransferAddResultOk final { public: bool fetch(tl::fetcher& tlf) noexcept { tl::magic magic{}; - bool ok{magic.fetch(tlf) && magic.expect(COMPOSITE_WEB_TRANSFER_ADD_RESULT_OK_MAGIC)}; - return ok; + return magic.fetch(tlf) && magic.expect(COMPOSITE_WEB_TRANSFER_ADD_RESULT_OK_MAGIC); } constexpr size_t footprint() const noexcept { @@ -1374,8 +1352,7 @@ class CompositeWebTransferRemoveResultOk final { public: bool fetch(tl::fetcher& tlf) noexcept { tl::magic magic{}; - bool ok{magic.fetch(tlf) && magic.expect(COMPOSITE_WEB_TRANSFER_REMOVE_RESULT_OK_MAGIC)}; - return ok; + return magic.fetch(tlf) && magic.expect(COMPOSITE_WEB_TRANSFER_REMOVE_RESULT_OK_MAGIC); } constexpr size_t footprint() const noexcept { @@ -1391,8 +1368,7 @@ class CompositeWebTransferPerformResultOk final { bool fetch(tl::fetcher& tlf) noexcept { tl::magic magic{}; - bool ok{magic.fetch(tlf) && magic.expect(COMPOSITE_WEB_TRANSFER_PERFORM_RESULT_OK_MAGIC) && remaining.fetch(tlf)}; - return ok; + return magic.fetch(tlf) && magic.expect(COMPOSITE_WEB_TRANSFER_PERFORM_RESULT_OK_MAGIC) && remaining.fetch(tlf); } constexpr size_t footprint() const noexcept { @@ -1406,8 +1382,7 @@ class CompositeWebTransferCloseResultOk final { public: bool fetch(tl::fetcher& tlf) noexcept { tl::magic magic{}; - bool ok{magic.fetch(tlf) && magic.expect(COMPOSITE_WEB_TRANSFER_CLOSE_RESULT_OK_MAGIC)}; - return ok; + return magic.fetch(tlf) && magic.expect(COMPOSITE_WEB_TRANSFER_CLOSE_RESULT_OK_MAGIC); } constexpr size_t footprint() const noexcept { @@ -1423,8 +1398,7 @@ class CompositeWebTransferWaitUpdatesResultOk final { bool fetch(tl::fetcher& tlf) noexcept { tl::magic magic{}; - bool ok{magic.fetch(tlf) && magic.expect(COMPOSITE_WEB_TRANSFER_WAIT_UPDATES_RESULT_OK_MAGIC) && updated_descriptors_num.fetch(tlf)}; - return ok; + return magic.fetch(tlf) && magic.expect(COMPOSITE_WEB_TRANSFER_WAIT_UPDATES_RESULT_OK_MAGIC) && updated_descriptors_num.fetch(tlf); } constexpr size_t footprint() const noexcept { @@ -1433,3 +1407,41 @@ class CompositeWebTransferWaitUpdatesResultOk final { }; } // namespace tl + +namespace tl2 { + +class string final { + static constexpr uint8_t HUGE_STRING_MAGIC = 0xff; + static constexpr uint8_t MEDIUM_STRING_MAGIC = 0xfe; + + static constexpr auto TINY_STRING_SIZE_LEN = 1; + static constexpr auto MEDIUM_STRING_SIZE_LEN = 2; + static constexpr auto HUGE_STRING_SIZE_LEN = 8; + + static constexpr uint64_t TINY_STRING_MAX_LEN = 253; + static constexpr uint64_t MEDIUM_STRING_MAX_LEN = MEDIUM_STRING_MAGIC + std::numeric_limits::max(); + static constexpr uint64_t HUGE_STRING_MAX_LEN = std::numeric_limits::max(); + +public: + std::string_view value; + + bool fetch(tl::fetcher& tlf) noexcept; + + void store(tl::storer& tls) const noexcept; + + constexpr size_t footprint() const noexcept { + const size_t str_len{value.size()}; + size_t size_len{}; + if (str_len <= TINY_STRING_MAX_LEN) { + size_len = TINY_STRING_SIZE_LEN; + } else if (str_len <= MEDIUM_STRING_MAX_LEN) { + size_len = MEDIUM_STRING_SIZE_LEN + 1; + } else { + size_len = HUGE_STRING_SIZE_LEN + 1; + } + + return size_len + str_len; + } +}; + +} // namespace tl2