Coverage Report

Created: 2025-12-30 08:42

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/node/src/inspector/node_string.cc
Line
Count
Source
1
#include "node_string.h"
2
#include "crdtp/json.h"
3
#include "node/inspector/protocol/Protocol.h"
4
#include "simdutf.h"
5
#include "util-inl.h"
6
7
namespace crdtp {
8
9
bool ProtocolTypeTraits<std::string>::Deserialize(DeserializerState* state,
10
0
                                                  std::string* value) {
11
0
  if (state->tokenizer()->TokenTag() == cbor::CBORTokenTag::STRING8) {
12
0
    span<uint8_t> cbor_span = state->tokenizer()->GetString8();
13
0
    value->assign(reinterpret_cast<const char*>(cbor_span.data()),
14
0
                  cbor_span.size());
15
0
    return true;
16
0
  }
17
0
  CHECK(state->tokenizer()->TokenTag() == cbor::CBORTokenTag::STRING16);
18
0
  span<uint8_t> utf16le = state->tokenizer()->GetString16WireRep();
19
20
0
  value->assign(node::inspector::protocol::StringUtil::fromUTF16LE(
21
0
      reinterpret_cast<const uint16_t*>(utf16le.data()),
22
0
      utf16le.size() / sizeof(uint16_t)));
23
0
  return true;
24
0
}
25
26
void ProtocolTypeTraits<std::string>::Serialize(const std::string& value,
27
0
                                                std::vector<uint8_t>* bytes) {
28
0
  cbor::EncodeString8(SpanFrom(value), bytes);
29
0
}
30
31
bool ProtocolTypeTraits<node::inspector::protocol::Binary>::Deserialize(
32
0
    DeserializerState* state, node::inspector::protocol::Binary* value) {
33
0
  CHECK(state->tokenizer()->TokenTag() == cbor::CBORTokenTag::BINARY);
34
0
  span<uint8_t> cbor_span = state->tokenizer()->GetBinary();
35
0
  *value = node::inspector::protocol::Binary::fromSpan(cbor_span);
36
0
  return true;
37
0
}
38
39
void ProtocolTypeTraits<node::inspector::protocol::Binary>::Serialize(
40
    const node::inspector::protocol::Binary& value,
41
0
    std::vector<uint8_t>* bytes) {
42
0
  cbor::EncodeString8(SpanFrom(value.toBase64()), bytes);
43
0
}
44
45
}  // namespace crdtp
46
47
namespace node {
48
namespace inspector {
49
namespace protocol {
50
51
0
String StringUtil::StringViewToUtf8(v8_inspector::StringView view) {
52
0
  if (view.length() == 0)
53
0
    return "";
54
0
  if (view.is8Bit()) {
55
0
    return std::string(reinterpret_cast<const char*>(view.characters8()),
56
0
                       view.length());
57
0
  }
58
0
  return fromUTF16(view.characters16(), view.length());
59
0
}
60
61
0
String StringUtil::fromUTF16(const uint16_t* data, size_t length) {
62
0
  auto casted_data = reinterpret_cast<const char16_t*>(data);
63
0
  size_t expected_utf8_length =
64
0
      simdutf::utf8_length_from_utf16(casted_data, length);
65
0
  MaybeStackBuffer<char> buffer(expected_utf8_length);
66
  // simdutf::convert_utf16_to_utf8 returns zero in case of error.
67
0
  size_t utf8_length =
68
0
      simdutf::convert_utf16_to_utf8(casted_data, length, buffer.out());
69
  // We have that utf8_length == expected_utf8_length if and only
70
  // if the input was a valid UTF-16 string. Otherwise, utf8_length
71
  // must be zero.
72
0
  CHECK(utf8_length == 0 || utf8_length == expected_utf8_length);
73
  // An invalid UTF-16 input will generate the empty string:
74
0
  return String(buffer.out(), utf8_length);
75
0
}
76
77
0
String StringUtil::fromUTF8(const uint8_t* data, size_t length) {
78
0
  return std::string(reinterpret_cast<const char*>(data), length);
79
0
}
80
81
0
String StringUtil::fromUTF16LE(const uint16_t* data, size_t length) {
82
0
  auto casted_data = reinterpret_cast<const char16_t*>(data);
83
0
  size_t expected_utf8_length =
84
0
      simdutf::utf8_length_from_utf16le(casted_data, length);
85
0
  MaybeStackBuffer<char> buffer(expected_utf8_length);
86
  // simdutf::convert_utf16le_to_utf8 returns zero in case of error.
87
0
  size_t utf8_length =
88
0
      simdutf::convert_utf16le_to_utf8(casted_data, length, buffer.out());
89
  // We have that utf8_length == expected_utf8_length if and only
90
  // if the input was a valid UTF-16 string. Otherwise, utf8_length
91
  // must be zero.
92
0
  CHECK(utf8_length == 0 || utf8_length == expected_utf8_length);
93
  // An invalid UTF-16 input will generate the empty string:
94
0
  return String(buffer.out(), utf8_length);
95
0
}
96
97
0
const uint8_t* StringUtil::CharactersUTF8(const std::string_view s) {
98
0
  return reinterpret_cast<const uint8_t*>(s.data());
99
0
}
100
101
0
size_t StringUtil::CharacterCount(const std::string_view s) {
102
  // Return the length of underlying representation storage.
103
  // E.g. for std::basic_string_view<char>, return its byte length.
104
  // If we adopt a variant underlying store string type, like
105
  // `v8_inspector::StringView`, for UTF16, return the length of the
106
  // underlying uint16_t store.
107
0
  return s.length();
108
0
}
109
110
0
String Binary::toBase64() const {
111
0
  size_t expected_base64_length =
112
0
      simdutf::base64_length_from_binary(bytes_->size());
113
0
  MaybeStackBuffer<char> buffer(expected_base64_length);
114
115
0
  size_t len =
116
0
      simdutf::binary_to_base64(reinterpret_cast<const char*>(bytes_->data()),
117
0
                                bytes_->size(),
118
0
                                buffer.out());
119
0
  CHECK_EQ(len, expected_base64_length);
120
0
  return buffer.ToString();
121
0
}
122
123
// static
124
0
Binary Binary::concat(const std::vector<Binary>& binaries) {
125
0
  size_t total_size = 0;
126
0
  for (const auto& binary : binaries) {
127
0
    total_size += binary.size();
128
0
  }
129
0
  auto bytes = std::make_shared<std::vector<uint8_t>>(total_size);
130
0
  uint8_t* data_ptr = bytes->data();
131
0
  for (const auto& binary : binaries) {
132
0
    memcpy(data_ptr, binary.data(), binary.size());
133
0
    data_ptr += binary.size();
134
0
  }
135
0
  return Binary(bytes);
136
0
}
137
138
// static
139
0
Binary Binary::fromBase64(const String& base64, bool* success) {
140
0
  Binary binary{};
141
0
  size_t base64_len = simdutf::maximal_binary_length_from_base64(
142
0
      base64.data(), base64.length());
143
0
  binary.bytes_->resize(base64_len);
144
145
0
  simdutf::result result;
146
0
  result =
147
0
      simdutf::base64_to_binary(base64.data(),
148
0
                                base64.length(),
149
0
                                reinterpret_cast<char*>(binary.bytes_->data()));
150
0
  CHECK_EQ(result.error, simdutf::error_code::SUCCESS);
151
0
  return binary;
152
0
}
153
154
// static
155
0
Binary Binary::fromUint8Array(v8::Local<v8::Uint8Array> data) {
156
0
  auto bytes = std::make_shared<std::vector<uint8_t>>(data->ByteLength());
157
0
  size_t size = data->CopyContents(bytes->data(), data->ByteLength());
158
0
  CHECK_EQ(size, data->ByteLength());
159
0
  return Binary(bytes);
160
0
}
161
162
}  // namespace protocol
163
}  // namespace inspector
164
}  // namespace node