11cb0ef41Sopenharmony_ci#ifndef SRC_BLOB_SERIALIZER_DESERIALIZER_INL_H_ 21cb0ef41Sopenharmony_ci#define SRC_BLOB_SERIALIZER_DESERIALIZER_INL_H_ 31cb0ef41Sopenharmony_ci 41cb0ef41Sopenharmony_ci#if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS 51cb0ef41Sopenharmony_ci 61cb0ef41Sopenharmony_ci#include "blob_serializer_deserializer.h" 71cb0ef41Sopenharmony_ci 81cb0ef41Sopenharmony_ci#include <ostream> 91cb0ef41Sopenharmony_ci#include <sstream> 101cb0ef41Sopenharmony_ci#include <string> 111cb0ef41Sopenharmony_ci#include <type_traits> 121cb0ef41Sopenharmony_ci#include <utility> 131cb0ef41Sopenharmony_ci 141cb0ef41Sopenharmony_ci#include "debug_utils-inl.h" 151cb0ef41Sopenharmony_ci 161cb0ef41Sopenharmony_ci// This is related to the blob that is used in snapshots and has nothing to do 171cb0ef41Sopenharmony_ci// with `node_blob.h`. 181cb0ef41Sopenharmony_ci 191cb0ef41Sopenharmony_cinamespace node { 201cb0ef41Sopenharmony_ci 211cb0ef41Sopenharmony_cistruct EnvSerializeInfo; 221cb0ef41Sopenharmony_cistruct PropInfo; 231cb0ef41Sopenharmony_cistruct RealmSerializeInfo; 241cb0ef41Sopenharmony_ci 251cb0ef41Sopenharmony_cinamespace builtins { 261cb0ef41Sopenharmony_cistruct CodeCacheInfo; 271cb0ef41Sopenharmony_ci} // namespace builtins 281cb0ef41Sopenharmony_ci 291cb0ef41Sopenharmony_ci// These operator<< overload declarations are needed because 301cb0ef41Sopenharmony_ci// BlobSerializerDeserializer::ToStr() uses these. 311cb0ef41Sopenharmony_ci 321cb0ef41Sopenharmony_cistd::ostream& operator<<(std::ostream& output, 331cb0ef41Sopenharmony_ci const builtins::CodeCacheInfo& info); 341cb0ef41Sopenharmony_ci 351cb0ef41Sopenharmony_cistd::ostream& operator<<(std::ostream& output, 361cb0ef41Sopenharmony_ci const std::vector<builtins::CodeCacheInfo>& vec); 371cb0ef41Sopenharmony_ci 381cb0ef41Sopenharmony_cistd::ostream& operator<<(std::ostream& output, const std::vector<uint8_t>& vec); 391cb0ef41Sopenharmony_ci 401cb0ef41Sopenharmony_cistd::ostream& operator<<(std::ostream& output, 411cb0ef41Sopenharmony_ci const std::vector<PropInfo>& vec); 421cb0ef41Sopenharmony_ci 431cb0ef41Sopenharmony_cistd::ostream& operator<<(std::ostream& output, const PropInfo& info); 441cb0ef41Sopenharmony_ci 451cb0ef41Sopenharmony_cistd::ostream& operator<<(std::ostream& output, 461cb0ef41Sopenharmony_ci const std::vector<std::string>& vec); 471cb0ef41Sopenharmony_ci 481cb0ef41Sopenharmony_cistd::ostream& operator<<(std::ostream& output, const RealmSerializeInfo& i); 491cb0ef41Sopenharmony_ci 501cb0ef41Sopenharmony_cistd::ostream& operator<<(std::ostream& output, const EnvSerializeInfo& i); 511cb0ef41Sopenharmony_ci 521cb0ef41Sopenharmony_citemplate <typename... Args> 531cb0ef41Sopenharmony_civoid BlobSerializerDeserializer::Debug(const char* format, 541cb0ef41Sopenharmony_ci Args&&... args) const { 551cb0ef41Sopenharmony_ci if (is_debug) { 561cb0ef41Sopenharmony_ci FPrintF(stderr, format, std::forward<Args>(args)...); 571cb0ef41Sopenharmony_ci } 581cb0ef41Sopenharmony_ci} 591cb0ef41Sopenharmony_ci 601cb0ef41Sopenharmony_citemplate <typename T> 611cb0ef41Sopenharmony_cistd::string BlobSerializerDeserializer::ToStr(const T& arg) const { 621cb0ef41Sopenharmony_ci std::stringstream ss; 631cb0ef41Sopenharmony_ci ss << arg; 641cb0ef41Sopenharmony_ci return ss.str(); 651cb0ef41Sopenharmony_ci} 661cb0ef41Sopenharmony_ci 671cb0ef41Sopenharmony_citemplate <typename T> 681cb0ef41Sopenharmony_cistd::string BlobSerializerDeserializer::GetName() const { 691cb0ef41Sopenharmony_ci#define TYPE_LIST(V) \ 701cb0ef41Sopenharmony_ci V(builtins::CodeCacheInfo) \ 711cb0ef41Sopenharmony_ci V(PropInfo) \ 721cb0ef41Sopenharmony_ci V(std::string) 731cb0ef41Sopenharmony_ci 741cb0ef41Sopenharmony_ci#define V(TypeName) \ 751cb0ef41Sopenharmony_ci if constexpr (std::is_same_v<T, TypeName>) { \ 761cb0ef41Sopenharmony_ci return #TypeName; \ 771cb0ef41Sopenharmony_ci } else // NOLINT(readability/braces) 781cb0ef41Sopenharmony_ci TYPE_LIST(V) 791cb0ef41Sopenharmony_ci#undef V 801cb0ef41Sopenharmony_ci 811cb0ef41Sopenharmony_ci if constexpr (std::is_arithmetic_v<T>) { 821cb0ef41Sopenharmony_ci return (std::is_unsigned_v<T> ? "uint" 831cb0ef41Sopenharmony_ci : std::is_integral_v<T> ? "int" 841cb0ef41Sopenharmony_ci : "float") + 851cb0ef41Sopenharmony_ci std::to_string(sizeof(T) * 8) + "_t"; 861cb0ef41Sopenharmony_ci } 871cb0ef41Sopenharmony_ci return ""; 881cb0ef41Sopenharmony_ci} 891cb0ef41Sopenharmony_ci 901cb0ef41Sopenharmony_ci// Helper for reading numeric types. 911cb0ef41Sopenharmony_citemplate <typename Impl> 921cb0ef41Sopenharmony_citemplate <typename T> 931cb0ef41Sopenharmony_ciT BlobDeserializer<Impl>::ReadArithmetic() { 941cb0ef41Sopenharmony_ci static_assert(std::is_arithmetic_v<T>, "Not an arithmetic type"); 951cb0ef41Sopenharmony_ci T result; 961cb0ef41Sopenharmony_ci ReadArithmetic(&result, 1); 971cb0ef41Sopenharmony_ci return result; 981cb0ef41Sopenharmony_ci} 991cb0ef41Sopenharmony_ci 1001cb0ef41Sopenharmony_ci// Layout of vectors: 1011cb0ef41Sopenharmony_ci// [ 4/8 bytes ] count 1021cb0ef41Sopenharmony_ci// [ ... ] contents (count * size of individual elements) 1031cb0ef41Sopenharmony_citemplate <typename Impl> 1041cb0ef41Sopenharmony_citemplate <typename T> 1051cb0ef41Sopenharmony_cistd::vector<T> BlobDeserializer<Impl>::ReadVector() { 1061cb0ef41Sopenharmony_ci if (is_debug) { 1071cb0ef41Sopenharmony_ci std::string name = GetName<T>(); 1081cb0ef41Sopenharmony_ci Debug("\nReadVector<%s>()(%d-byte)\n", name.c_str(), sizeof(T)); 1091cb0ef41Sopenharmony_ci } 1101cb0ef41Sopenharmony_ci size_t count = static_cast<size_t>(ReadArithmetic<size_t>()); 1111cb0ef41Sopenharmony_ci if (count == 0) { 1121cb0ef41Sopenharmony_ci return std::vector<T>(); 1131cb0ef41Sopenharmony_ci } 1141cb0ef41Sopenharmony_ci if (is_debug) { 1151cb0ef41Sopenharmony_ci Debug("Reading %d vector elements...\n", count); 1161cb0ef41Sopenharmony_ci } 1171cb0ef41Sopenharmony_ci std::vector<T> result; 1181cb0ef41Sopenharmony_ci if constexpr (std::is_arithmetic_v<T>) { 1191cb0ef41Sopenharmony_ci result = ReadArithmeticVector<T>(count); 1201cb0ef41Sopenharmony_ci } else { 1211cb0ef41Sopenharmony_ci result = ReadNonArithmeticVector<T>(count); 1221cb0ef41Sopenharmony_ci } 1231cb0ef41Sopenharmony_ci if (is_debug) { 1241cb0ef41Sopenharmony_ci std::string str = std::is_arithmetic_v<T> ? "" : ToStr(result); 1251cb0ef41Sopenharmony_ci std::string name = GetName<T>(); 1261cb0ef41Sopenharmony_ci Debug("ReadVector<%s>() read %s\n", name.c_str(), str.c_str()); 1271cb0ef41Sopenharmony_ci } 1281cb0ef41Sopenharmony_ci return result; 1291cb0ef41Sopenharmony_ci} 1301cb0ef41Sopenharmony_ci 1311cb0ef41Sopenharmony_citemplate <typename Impl> 1321cb0ef41Sopenharmony_cistd::string BlobDeserializer<Impl>::ReadString() { 1331cb0ef41Sopenharmony_ci size_t length = ReadArithmetic<size_t>(); 1341cb0ef41Sopenharmony_ci 1351cb0ef41Sopenharmony_ci if (is_debug) { 1361cb0ef41Sopenharmony_ci Debug("ReadString(), length=%d: ", length); 1371cb0ef41Sopenharmony_ci } 1381cb0ef41Sopenharmony_ci 1391cb0ef41Sopenharmony_ci CHECK_GT(length, 0); // There should be no empty strings. 1401cb0ef41Sopenharmony_ci MallocedBuffer<char> buf(length + 1); 1411cb0ef41Sopenharmony_ci memcpy(buf.data, sink.data() + read_total, length + 1); 1421cb0ef41Sopenharmony_ci std::string result(buf.data, length); // This creates a copy of buf.data. 1431cb0ef41Sopenharmony_ci 1441cb0ef41Sopenharmony_ci if (is_debug) { 1451cb0ef41Sopenharmony_ci Debug("\"%s\", read %zu bytes\n", result.c_str(), length + 1); 1461cb0ef41Sopenharmony_ci } 1471cb0ef41Sopenharmony_ci 1481cb0ef41Sopenharmony_ci read_total += length + 1; 1491cb0ef41Sopenharmony_ci return result; 1501cb0ef41Sopenharmony_ci} 1511cb0ef41Sopenharmony_ci 1521cb0ef41Sopenharmony_ci// Helper for reading an array of numeric types. 1531cb0ef41Sopenharmony_citemplate <typename Impl> 1541cb0ef41Sopenharmony_citemplate <typename T> 1551cb0ef41Sopenharmony_civoid BlobDeserializer<Impl>::ReadArithmetic(T* out, size_t count) { 1561cb0ef41Sopenharmony_ci static_assert(std::is_arithmetic_v<T>, "Not an arithmetic type"); 1571cb0ef41Sopenharmony_ci DCHECK_GT(count, 0); // Should not read contents for vectors of size 0. 1581cb0ef41Sopenharmony_ci if (is_debug) { 1591cb0ef41Sopenharmony_ci std::string name = GetName<T>(); 1601cb0ef41Sopenharmony_ci Debug("Read<%s>()(%d-byte), count=%d: ", name.c_str(), sizeof(T), count); 1611cb0ef41Sopenharmony_ci } 1621cb0ef41Sopenharmony_ci 1631cb0ef41Sopenharmony_ci size_t size = sizeof(T) * count; 1641cb0ef41Sopenharmony_ci memcpy(out, sink.data() + read_total, size); 1651cb0ef41Sopenharmony_ci 1661cb0ef41Sopenharmony_ci if (is_debug) { 1671cb0ef41Sopenharmony_ci std::string str = 1681cb0ef41Sopenharmony_ci "{ " + std::to_string(out[0]) + (count > 1 ? ", ... }" : " }"); 1691cb0ef41Sopenharmony_ci Debug("%s, read %zu bytes\n", str.c_str(), size); 1701cb0ef41Sopenharmony_ci } 1711cb0ef41Sopenharmony_ci read_total += size; 1721cb0ef41Sopenharmony_ci} 1731cb0ef41Sopenharmony_ci 1741cb0ef41Sopenharmony_ci// Helper for reading numeric vectors. 1751cb0ef41Sopenharmony_citemplate <typename Impl> 1761cb0ef41Sopenharmony_citemplate <typename Number> 1771cb0ef41Sopenharmony_cistd::vector<Number> BlobDeserializer<Impl>::ReadArithmeticVector(size_t count) { 1781cb0ef41Sopenharmony_ci static_assert(std::is_arithmetic_v<Number>, "Not an arithmetic type"); 1791cb0ef41Sopenharmony_ci DCHECK_GT(count, 0); // Should not read contents for vectors of size 0. 1801cb0ef41Sopenharmony_ci std::vector<Number> result(count); 1811cb0ef41Sopenharmony_ci ReadArithmetic(result.data(), count); 1821cb0ef41Sopenharmony_ci return result; 1831cb0ef41Sopenharmony_ci} 1841cb0ef41Sopenharmony_ci 1851cb0ef41Sopenharmony_ci// Helper for reading non-numeric vectors. 1861cb0ef41Sopenharmony_citemplate <typename Impl> 1871cb0ef41Sopenharmony_citemplate <typename T> 1881cb0ef41Sopenharmony_cistd::vector<T> BlobDeserializer<Impl>::ReadNonArithmeticVector(size_t count) { 1891cb0ef41Sopenharmony_ci static_assert(!std::is_arithmetic_v<T>, "Arithmetic type"); 1901cb0ef41Sopenharmony_ci DCHECK_GT(count, 0); // Should not read contents for vectors of size 0. 1911cb0ef41Sopenharmony_ci std::vector<T> result; 1921cb0ef41Sopenharmony_ci result.reserve(count); 1931cb0ef41Sopenharmony_ci bool original_is_debug = is_debug; 1941cb0ef41Sopenharmony_ci is_debug = original_is_debug && !std::is_same_v<T, std::string>; 1951cb0ef41Sopenharmony_ci for (size_t i = 0; i < count; ++i) { 1961cb0ef41Sopenharmony_ci if (is_debug) { 1971cb0ef41Sopenharmony_ci Debug("\n[%d] ", i); 1981cb0ef41Sopenharmony_ci } 1991cb0ef41Sopenharmony_ci result.push_back(ReadElement<T>()); 2001cb0ef41Sopenharmony_ci } 2011cb0ef41Sopenharmony_ci is_debug = original_is_debug; 2021cb0ef41Sopenharmony_ci 2031cb0ef41Sopenharmony_ci return result; 2041cb0ef41Sopenharmony_ci} 2051cb0ef41Sopenharmony_ci 2061cb0ef41Sopenharmony_citemplate <typename Impl> 2071cb0ef41Sopenharmony_citemplate <typename T> 2081cb0ef41Sopenharmony_ciT BlobDeserializer<Impl>::ReadElement() { 2091cb0ef41Sopenharmony_ci if constexpr (std::is_arithmetic_v<T>) { 2101cb0ef41Sopenharmony_ci return ReadArithmetic<T>(); 2111cb0ef41Sopenharmony_ci } else if constexpr (std::is_same_v<T, std::string>) { 2121cb0ef41Sopenharmony_ci return ReadString(); 2131cb0ef41Sopenharmony_ci } else { 2141cb0ef41Sopenharmony_ci return impl()->template Read<T>(); 2151cb0ef41Sopenharmony_ci } 2161cb0ef41Sopenharmony_ci} 2171cb0ef41Sopenharmony_ci 2181cb0ef41Sopenharmony_ci// Helper for writing numeric types. 2191cb0ef41Sopenharmony_citemplate <typename Impl> 2201cb0ef41Sopenharmony_citemplate <typename T> 2211cb0ef41Sopenharmony_cisize_t BlobSerializer<Impl>::WriteArithmetic(const T& data) { 2221cb0ef41Sopenharmony_ci static_assert(std::is_arithmetic_v<T>, "Not an arithmetic type"); 2231cb0ef41Sopenharmony_ci return WriteArithmetic(&data, 1); 2241cb0ef41Sopenharmony_ci} 2251cb0ef41Sopenharmony_ci 2261cb0ef41Sopenharmony_ci// Layout of vectors: 2271cb0ef41Sopenharmony_ci// [ 4/8 bytes ] count 2281cb0ef41Sopenharmony_ci// [ ... ] contents (count * size of individual elements) 2291cb0ef41Sopenharmony_citemplate <typename Impl> 2301cb0ef41Sopenharmony_citemplate <typename T> 2311cb0ef41Sopenharmony_cisize_t BlobSerializer<Impl>::WriteVector(const std::vector<T>& data) { 2321cb0ef41Sopenharmony_ci if (is_debug) { 2331cb0ef41Sopenharmony_ci std::string str = std::is_arithmetic_v<T> ? "" : ToStr(data); 2341cb0ef41Sopenharmony_ci std::string name = GetName<T>(); 2351cb0ef41Sopenharmony_ci Debug("\nWriteVector<%s>() (%d-byte), count=%d: %s\n", 2361cb0ef41Sopenharmony_ci name.c_str(), 2371cb0ef41Sopenharmony_ci sizeof(T), 2381cb0ef41Sopenharmony_ci data.size(), 2391cb0ef41Sopenharmony_ci str.c_str()); 2401cb0ef41Sopenharmony_ci } 2411cb0ef41Sopenharmony_ci 2421cb0ef41Sopenharmony_ci size_t written_total = WriteArithmetic<size_t>(data.size()); 2431cb0ef41Sopenharmony_ci if (data.size() == 0) { 2441cb0ef41Sopenharmony_ci return written_total; 2451cb0ef41Sopenharmony_ci } 2461cb0ef41Sopenharmony_ci 2471cb0ef41Sopenharmony_ci if constexpr (std::is_arithmetic_v<T>) { 2481cb0ef41Sopenharmony_ci written_total += WriteArithmeticVector<T>(data); 2491cb0ef41Sopenharmony_ci } else { 2501cb0ef41Sopenharmony_ci written_total += WriteNonArithmeticVector<T>(data); 2511cb0ef41Sopenharmony_ci } 2521cb0ef41Sopenharmony_ci 2531cb0ef41Sopenharmony_ci if (is_debug) { 2541cb0ef41Sopenharmony_ci std::string name = GetName<T>(); 2551cb0ef41Sopenharmony_ci Debug("WriteVector<%s>() wrote %d bytes\n", name.c_str(), written_total); 2561cb0ef41Sopenharmony_ci } 2571cb0ef41Sopenharmony_ci 2581cb0ef41Sopenharmony_ci return written_total; 2591cb0ef41Sopenharmony_ci} 2601cb0ef41Sopenharmony_ci 2611cb0ef41Sopenharmony_ci// The layout of a written string: 2621cb0ef41Sopenharmony_ci// [ 4/8 bytes ] length 2631cb0ef41Sopenharmony_ci// [ |length| bytes ] contents 2641cb0ef41Sopenharmony_citemplate <typename Impl> 2651cb0ef41Sopenharmony_cisize_t BlobSerializer<Impl>::WriteString(const std::string& data) { 2661cb0ef41Sopenharmony_ci CHECK_GT(data.size(), 0); // No empty strings should be written. 2671cb0ef41Sopenharmony_ci size_t written_total = WriteArithmetic<size_t>(data.size()); 2681cb0ef41Sopenharmony_ci if (is_debug) { 2691cb0ef41Sopenharmony_ci std::string str = ToStr(data); 2701cb0ef41Sopenharmony_ci Debug("WriteString(), length=%zu: \"%s\"\n", data.size(), data.c_str()); 2711cb0ef41Sopenharmony_ci } 2721cb0ef41Sopenharmony_ci 2731cb0ef41Sopenharmony_ci // Write the null-terminated string. 2741cb0ef41Sopenharmony_ci size_t length = data.size() + 1; 2751cb0ef41Sopenharmony_ci sink.insert(sink.end(), data.c_str(), data.c_str() + length); 2761cb0ef41Sopenharmony_ci written_total += length; 2771cb0ef41Sopenharmony_ci 2781cb0ef41Sopenharmony_ci if (is_debug) { 2791cb0ef41Sopenharmony_ci Debug("WriteString() wrote %zu bytes\n", written_total); 2801cb0ef41Sopenharmony_ci } 2811cb0ef41Sopenharmony_ci 2821cb0ef41Sopenharmony_ci return written_total; 2831cb0ef41Sopenharmony_ci} 2841cb0ef41Sopenharmony_ci 2851cb0ef41Sopenharmony_ci// Helper for writing an array of numeric types. 2861cb0ef41Sopenharmony_citemplate <typename Impl> 2871cb0ef41Sopenharmony_citemplate <typename T> 2881cb0ef41Sopenharmony_cisize_t BlobSerializer<Impl>::WriteArithmetic(const T* data, size_t count) { 2891cb0ef41Sopenharmony_ci static_assert(std::is_arithmetic_v<T>, "Arithmetic type"); 2901cb0ef41Sopenharmony_ci DCHECK_GT(count, 0); // Should not write contents for vectors of size 0. 2911cb0ef41Sopenharmony_ci if (is_debug) { 2921cb0ef41Sopenharmony_ci std::string str = 2931cb0ef41Sopenharmony_ci "{ " + std::to_string(data[0]) + (count > 1 ? ", ... }" : " }"); 2941cb0ef41Sopenharmony_ci std::string name = GetName<T>(); 2951cb0ef41Sopenharmony_ci Debug("Write<%s>() (%zu-byte), count=%zu: %s", 2961cb0ef41Sopenharmony_ci name.c_str(), 2971cb0ef41Sopenharmony_ci sizeof(T), 2981cb0ef41Sopenharmony_ci count, 2991cb0ef41Sopenharmony_ci str.c_str()); 3001cb0ef41Sopenharmony_ci } 3011cb0ef41Sopenharmony_ci 3021cb0ef41Sopenharmony_ci size_t size = sizeof(T) * count; 3031cb0ef41Sopenharmony_ci const char* pos = reinterpret_cast<const char*>(data); 3041cb0ef41Sopenharmony_ci sink.insert(sink.end(), pos, pos + size); 3051cb0ef41Sopenharmony_ci 3061cb0ef41Sopenharmony_ci if (is_debug) { 3071cb0ef41Sopenharmony_ci Debug(", wrote %zu bytes\n", size); 3081cb0ef41Sopenharmony_ci } 3091cb0ef41Sopenharmony_ci return size; 3101cb0ef41Sopenharmony_ci} 3111cb0ef41Sopenharmony_ci 3121cb0ef41Sopenharmony_ci// Helper for writing numeric vectors. 3131cb0ef41Sopenharmony_citemplate <typename Impl> 3141cb0ef41Sopenharmony_citemplate <typename Number> 3151cb0ef41Sopenharmony_cisize_t BlobSerializer<Impl>::WriteArithmeticVector( 3161cb0ef41Sopenharmony_ci const std::vector<Number>& data) { 3171cb0ef41Sopenharmony_ci static_assert(std::is_arithmetic_v<Number>, "Arithmetic type"); 3181cb0ef41Sopenharmony_ci return WriteArithmetic(data.data(), data.size()); 3191cb0ef41Sopenharmony_ci} 3201cb0ef41Sopenharmony_ci 3211cb0ef41Sopenharmony_ci// Helper for writing non-numeric vectors. 3221cb0ef41Sopenharmony_citemplate <typename Impl> 3231cb0ef41Sopenharmony_citemplate <typename T> 3241cb0ef41Sopenharmony_cisize_t BlobSerializer<Impl>::WriteNonArithmeticVector( 3251cb0ef41Sopenharmony_ci const std::vector<T>& data) { 3261cb0ef41Sopenharmony_ci static_assert(!std::is_arithmetic_v<T>, "Arithmetic type"); 3271cb0ef41Sopenharmony_ci DCHECK_GT(data.size(), 3281cb0ef41Sopenharmony_ci 0); // Should not write contents for vectors of size 0. 3291cb0ef41Sopenharmony_ci size_t written_total = 0; 3301cb0ef41Sopenharmony_ci bool original_is_debug = is_debug; 3311cb0ef41Sopenharmony_ci is_debug = original_is_debug && !std::is_same_v<T, std::string>; 3321cb0ef41Sopenharmony_ci for (size_t i = 0; i < data.size(); ++i) { 3331cb0ef41Sopenharmony_ci if (is_debug) { 3341cb0ef41Sopenharmony_ci Debug("\n[%d] ", i); 3351cb0ef41Sopenharmony_ci } 3361cb0ef41Sopenharmony_ci written_total += WriteElement<T>(data[i]); 3371cb0ef41Sopenharmony_ci } 3381cb0ef41Sopenharmony_ci is_debug = original_is_debug; 3391cb0ef41Sopenharmony_ci 3401cb0ef41Sopenharmony_ci return written_total; 3411cb0ef41Sopenharmony_ci} 3421cb0ef41Sopenharmony_ci 3431cb0ef41Sopenharmony_citemplate <typename Impl> 3441cb0ef41Sopenharmony_citemplate <typename T> 3451cb0ef41Sopenharmony_cisize_t BlobSerializer<Impl>::WriteElement(const T& data) { 3461cb0ef41Sopenharmony_ci if constexpr (std::is_arithmetic_v<T>) { 3471cb0ef41Sopenharmony_ci return WriteArithmetic<T>(data); 3481cb0ef41Sopenharmony_ci } else if constexpr (std::is_same_v<T, std::string>) { 3491cb0ef41Sopenharmony_ci return WriteString(data); 3501cb0ef41Sopenharmony_ci } else { 3511cb0ef41Sopenharmony_ci return impl()->template Write<T>(data); 3521cb0ef41Sopenharmony_ci } 3531cb0ef41Sopenharmony_ci} 3541cb0ef41Sopenharmony_ci 3551cb0ef41Sopenharmony_ci} // namespace node 3561cb0ef41Sopenharmony_ci 3571cb0ef41Sopenharmony_ci#endif // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS 3581cb0ef41Sopenharmony_ci 3591cb0ef41Sopenharmony_ci#endif // SRC_BLOB_SERIALIZER_DESERIALIZER_INL_H_ 360