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