/src/node/src/inspector/node_json.cc
Line | Count | Source |
1 | | #include "node_json.h" |
2 | | |
3 | | #include "crdtp/json.h" |
4 | | |
5 | | namespace node { |
6 | | namespace inspector { |
7 | | |
8 | | using crdtp::ParserHandler; |
9 | | using crdtp::span; |
10 | | using crdtp::Status; |
11 | | using protocol::Binary; |
12 | | using protocol::BinaryValue; |
13 | | using protocol::DictionaryValue; |
14 | | using protocol::FundamentalValue; |
15 | | using protocol::ListValue; |
16 | | using protocol::String; |
17 | | using protocol::StringUtil; |
18 | | using protocol::StringValue; |
19 | | using protocol::Value; |
20 | | |
21 | | namespace { |
22 | | |
23 | | // Uses the parsing events received from driver of `ParserHandler` |
24 | | // (e.g. crdtp::json::ParseJSON) into a protocol::Value instance. |
25 | | class ValueParserHandler : public ParserHandler { |
26 | | public: |
27 | | // Provides the parsed protocol::Value. |
28 | 0 | std::unique_ptr<Value> ReleaseRoot() { return std::move(root_); } |
29 | | |
30 | | // The first parsing error encountered; `status().ok()` is the default. |
31 | 0 | Status status() const { return status_; } |
32 | | |
33 | | private: |
34 | | // Implementation of `ParserHandler`. |
35 | 0 | void HandleMapBegin() override { |
36 | 0 | if (!status_.ok()) return; |
37 | 0 | std::unique_ptr<DictionaryValue> dict = DictionaryValue::create(); |
38 | 0 | DictionaryValue* dict_ptr = dict.get(); |
39 | 0 | AddValueToParent(std::move(dict)); |
40 | 0 | stack_.emplace_back(dict_ptr); |
41 | 0 | } |
42 | | |
43 | 0 | void HandleMapEnd() override { |
44 | 0 | if (!status_.ok()) return; |
45 | 0 | DCHECK(!stack_.empty()); |
46 | 0 | DCHECK(stack_.back().is_dict); |
47 | 0 | stack_.pop_back(); |
48 | 0 | } |
49 | | |
50 | 0 | void HandleArrayBegin() override { |
51 | 0 | if (!status_.ok()) return; |
52 | 0 | std::unique_ptr<ListValue> list = ListValue::create(); |
53 | 0 | ListValue* list_ptr = list.get(); |
54 | 0 | AddValueToParent(std::move(list)); |
55 | 0 | stack_.emplace_back(list_ptr); |
56 | 0 | } |
57 | | |
58 | 0 | void HandleArrayEnd() override { |
59 | 0 | if (!status_.ok()) return; |
60 | 0 | DCHECK(!stack_.empty()); |
61 | 0 | DCHECK(!stack_.back().is_dict); |
62 | 0 | stack_.pop_back(); |
63 | 0 | } |
64 | | |
65 | 0 | void HandleString8(span<uint8_t> chars) override { |
66 | 0 | AddStringToParent(StringUtil::fromUTF8(chars.data(), chars.size())); |
67 | 0 | } |
68 | | |
69 | 0 | void HandleString16(span<uint16_t> chars) override { |
70 | 0 | AddStringToParent(StringUtil::fromUTF16(chars.data(), chars.size())); |
71 | 0 | } |
72 | | |
73 | 0 | void HandleBinary(span<uint8_t> bytes) override { |
74 | 0 | AddValueToParent( |
75 | 0 | BinaryValue::create(Binary::fromSpan(bytes.data(), bytes.size()))); |
76 | 0 | } |
77 | | |
78 | 0 | void HandleDouble(double value) override { |
79 | 0 | AddValueToParent(FundamentalValue::create(value)); |
80 | 0 | } |
81 | | |
82 | 0 | void HandleInt32(int32_t value) override { |
83 | 0 | AddValueToParent(FundamentalValue::create(value)); |
84 | 0 | } |
85 | | |
86 | 0 | void HandleBool(bool value) override { |
87 | 0 | AddValueToParent(FundamentalValue::create(value)); |
88 | 0 | } |
89 | | |
90 | 0 | void HandleNull() override { AddValueToParent(Value::null()); } |
91 | | |
92 | 0 | void HandleError(Status error) override { status_ = error; } |
93 | | |
94 | | // Adding strings and values to the parent value. |
95 | | // Strings are handled separately because they can be keys for |
96 | | // dictionary values. |
97 | 0 | void AddStringToParent(String str) { |
98 | 0 | if (!status_.ok()) return; |
99 | 0 | if (!root_) { |
100 | 0 | DCHECK(!key_is_pending_); |
101 | 0 | root_ = StringValue::create(str); |
102 | 0 | } else if (stack_.back().is_dict) { |
103 | | // If we already have a pending key, then this is the value of the |
104 | | // key/value pair. Otherwise, it's the new pending key. |
105 | 0 | if (key_is_pending_) { |
106 | 0 | stack_.back().dict->setString(pending_key_, str); |
107 | 0 | key_is_pending_ = false; |
108 | 0 | } else { |
109 | 0 | pending_key_ = std::move(str); |
110 | 0 | key_is_pending_ = true; |
111 | 0 | } |
112 | 0 | } else { // Top of the stack is a list. |
113 | 0 | DCHECK(!key_is_pending_); |
114 | 0 | stack_.back().list->pushValue(StringValue::create(str)); |
115 | 0 | } |
116 | 0 | } |
117 | | |
118 | 0 | void AddValueToParent(std::unique_ptr<Value> value) { |
119 | 0 | if (!status_.ok()) return; |
120 | 0 | if (!root_) { |
121 | 0 | DCHECK(!key_is_pending_); |
122 | 0 | root_ = std::move(value); |
123 | 0 | } else if (stack_.back().is_dict) { |
124 | 0 | DCHECK(key_is_pending_); |
125 | 0 | stack_.back().dict->setValue(pending_key_, std::move(value)); |
126 | 0 | key_is_pending_ = false; |
127 | 0 | } else { // Top of the stack is a list. |
128 | 0 | DCHECK(!key_is_pending_); |
129 | 0 | stack_.back().list->pushValue(std::move(value)); |
130 | 0 | } |
131 | 0 | } |
132 | | |
133 | | // `status_.ok()` is the default; if we receive an error event |
134 | | // we keep the first one and stop modifying any other state. |
135 | | Status status_; |
136 | | |
137 | | // The root of the parsed protocol::Value tree. |
138 | | std::unique_ptr<Value> root_; |
139 | | |
140 | | // If root_ is a list or a dictionary, this stack keeps track of |
141 | | // the container we're currently parsing as well as its ancestors. |
142 | | struct ContainerState { |
143 | | explicit ContainerState(DictionaryValue* dict) |
144 | 0 | : is_dict(true), dict(dict) {} |
145 | 0 | explicit ContainerState(ListValue* list) : is_dict(false), list(list) {} |
146 | | |
147 | | bool is_dict; |
148 | | union { |
149 | | DictionaryValue* dict; |
150 | | ListValue* list; |
151 | | }; |
152 | | }; |
153 | | std::vector<ContainerState> stack_; |
154 | | |
155 | | // For maps, keys and values are alternating events, so we keep the |
156 | | // key around and process it when the value arrives. |
157 | | bool key_is_pending_ = false; |
158 | | String pending_key_; |
159 | | }; |
160 | | } // anonymous namespace |
161 | | |
162 | 0 | std::unique_ptr<Value> JsonUtil::ParseJSON(const uint8_t* chars, size_t size) { |
163 | 0 | ValueParserHandler handler; |
164 | 0 | crdtp::json::ParseJSON(span<uint8_t>(chars, size), &handler); |
165 | 0 | if (handler.status().ok()) return handler.ReleaseRoot(); |
166 | 0 | return nullptr; |
167 | 0 | } |
168 | | |
169 | 0 | std::unique_ptr<Value> JsonUtil::ParseJSON(const uint16_t* chars, size_t size) { |
170 | 0 | ValueParserHandler handler; |
171 | 0 | crdtp::json::ParseJSON(span<uint16_t>(chars, size), &handler); |
172 | 0 | if (handler.status().ok()) return handler.ReleaseRoot(); |
173 | 0 | return nullptr; |
174 | 0 | } |
175 | | |
176 | 0 | std::unique_ptr<Value> JsonUtil::parseJSON(const std::string_view string) { |
177 | 0 | if (string.empty()) return nullptr; |
178 | | |
179 | 0 | return ParseJSON(reinterpret_cast<const uint8_t*>(string.data()), |
180 | 0 | string.size()); |
181 | 0 | } |
182 | | |
183 | 0 | std::unique_ptr<Value> JsonUtil::parseJSON(v8_inspector::StringView string) { |
184 | 0 | if (string.length() == 0) return nullptr; |
185 | 0 | if (string.is8Bit()) return ParseJSON(string.characters8(), string.length()); |
186 | 0 | return ParseJSON(string.characters16(), string.length()); |
187 | 0 | } |
188 | | |
189 | | } // namespace inspector |
190 | | } // namespace node |