5
5
#include < memory>
6
6
#include < optional>
7
7
#include < string>
8
+ #include < system_error>
8
9
#include < type_traits>
9
10
#include < utility>
10
11
#include < vector>
@@ -43,16 +44,16 @@ using Schema = std::vector<SchemaTree::Node::id_t>;
43
44
/* *
44
45
* Deserializes the parent ID of a schema tree node.
45
46
* @param reader
46
- * @param parent_id Returns the deserialized result.
47
- * @return IRErrorCode::IRErrorCode_Success on success.
48
- * @return IRErrorCode::IRErrorCode_Incomplete_IR if the stream is truncated.
49
- * @return IRErrorCode::IRErrorCode_Corrupted_IR if the next packet in the stream isn't a parent ID.
50
- * @return Forwards `deserialize_tag`'s return values on any other failure.
47
+ * @return A result containing a pair or an error code indicating the failure:
48
+ * - The pair:
49
+ * - Whether the node ID is for an auto-generated node.
50
+ * - The decoded node ID.
51
+ * - The possible error codes:
52
+ * - Forwards `deserialize_tag`'s return values.
53
+ * @return Forwards `deserialize_and_decode_schema_tree_node_id`'s return values.
51
54
*/
52
- [[nodiscard]] auto deserialize_schema_tree_node_parent_id (
53
- ReaderInterface& reader,
54
- SchemaTree::Node::id_t & parent_id
55
- ) -> IRErrorCode;
55
+ [[nodiscard]] auto deserialize_schema_tree_node_parent_id (ReaderInterface& reader
56
+ ) -> OUTCOME_V2_NAMESPACE::std_result<std::pair<bool, SchemaTree::Node::id_t>>;
56
57
57
58
/* *
58
59
* Deserializes the key name of a schema tree node.
@@ -100,13 +101,14 @@ deserialize_int_val(ReaderInterface& reader, encoded_tag_t tag, value_int_t& val
100
101
* Deserializes the IDs of all keys in a log event.
101
102
* @param reader
102
103
* @param tag Takes the current tag as input and returns the last tag read.
103
- * @param schema Returns the deserialized schema.
104
- * @return IRErrorCode::IRErrorCode_Success on success.
105
- * @return IRErrorCode::IRErrorCode_Incomplete_IR if the stream is truncated.
106
- * @return Forwards `deserialize_tag`'s return values on any other failure.
104
+ * @return A result containing the deserialized schema or an error code indicating the failure:
105
+ * - std::err::protocol_not_supported if the IR stream contains auto-generated keys (TODO: Remove
106
+ * this once auto-generated keys are fully supported).
107
+ * - Forwards `deserialize_tag`'s return values.
108
+ * - Forwards `deserialize_and_decode_schema_tree_node_id`'s return values.
107
109
*/
108
- [[nodiscard]] auto
109
- deserialize_schema (ReaderInterface& reader, encoded_tag_t & tag, Schema& schema) -> IRErrorCode ;
110
+ [[nodiscard]] auto deserialize_schema (ReaderInterface& reader, encoded_tag_t & tag)
111
+ -> OUTCOME_V2_NAMESPACE::std_result<Schema> ;
110
112
111
113
/* *
112
114
* Deserializes the next value and pushes the result into `node_id_value_pairs`.
@@ -170,10 +172,17 @@ requires(std::is_same_v<ir::four_byte_encoded_variable_t, encoded_variable_t>
170
172
) -> IRErrorCode;
171
173
172
174
/* *
175
+ * @param tag
173
176
* @return Whether the given tag can be a valid leading tag of a log event IR unit.
174
177
*/
175
178
[[nodiscard]] auto is_log_event_ir_unit_tag (encoded_tag_t tag) -> bool;
176
179
180
+ /* *
181
+ * @param tag
182
+ * @return Whether the given tag represents a valid encoded key ID.
183
+ */
184
+ [[nodiscard]] auto is_encoded_key_id_tag (encoded_tag_t tag) -> bool;
185
+
177
186
auto schema_tree_node_tag_to_type (encoded_tag_t tag) -> std::optional<SchemaTree::Node::Type> {
178
187
switch (tag) {
179
188
case cProtocol::Payload::SchemaTreeNodeInt:
@@ -193,30 +202,16 @@ auto schema_tree_node_tag_to_type(encoded_tag_t tag) -> std::optional<SchemaTree
193
202
}
194
203
}
195
204
196
- auto deserialize_schema_tree_node_parent_id (
197
- ReaderInterface& reader,
198
- SchemaTree::Node::id_t & parent_id
199
- ) -> IRErrorCode {
205
+ auto deserialize_schema_tree_node_parent_id (ReaderInterface& reader
206
+ ) -> OUTCOME_V2_NAMESPACE::std_result<std::pair<bool, SchemaTree::Node::id_t>> {
200
207
encoded_tag_t tag{};
201
208
if (auto const err{deserialize_tag (reader, tag)}; IRErrorCode::IRErrorCode_Success != err) {
202
- return err;
203
- }
204
- if (cProtocol::Payload::SchemaTreeNodeParentIdUByte == tag) {
205
- uint8_t deserialized_id{};
206
- if (false == deserialize_int (reader, deserialized_id)) {
207
- return IRErrorCode::IRErrorCode_Incomplete_IR;
208
- }
209
- parent_id = static_cast <SchemaTree::Node::id_t >(deserialized_id);
210
- } else if (cProtocol::Payload::SchemaTreeNodeParentIdUShort == tag) {
211
- uint16_t deserialized_id{};
212
- if (false == deserialize_int (reader, deserialized_id)) {
213
- return IRErrorCode::IRErrorCode_Incomplete_IR;
214
- }
215
- parent_id = static_cast <SchemaTree::Node::id_t >(deserialized_id);
216
- } else {
217
- return IRErrorCode::IRErrorCode_Corrupted_IR;
209
+ return ir_error_code_to_errc (err);
218
210
}
219
- return IRErrorCode_Success;
211
+ return deserialize_and_decode_schema_tree_node_id<
212
+ cProtocol::Payload::EncodedSchemaTreeNodeParentIdByte,
213
+ cProtocol::Payload::EncodedSchemaTreeNodeParentIdShort,
214
+ cProtocol::Payload::EncodedSchemaTreeNodeParentIdInt>(tag, reader);
220
215
}
221
216
222
217
auto deserialize_schema_tree_node_key_name (ReaderInterface& reader, std::string& key_name)
@@ -297,32 +292,35 @@ auto deserialize_string(ReaderInterface& reader, encoded_tag_t tag, std::string&
297
292
return IRErrorCode::IRErrorCode_Success;
298
293
}
299
294
300
- auto deserialize_schema (ReaderInterface& reader, encoded_tag_t & tag, Schema& schema )
301
- -> IRErrorCode {
302
- schema. clear () ;
295
+ auto deserialize_schema (ReaderInterface& reader, encoded_tag_t & tag)
296
+ -> OUTCOME_V2_NAMESPACE::std_result<Schema> {
297
+ Schema schema;
303
298
while (true ) {
304
- if (cProtocol::Payload::KeyIdUByte == tag) {
305
- uint8_t id{};
306
- if (false == deserialize_int (reader, id)) {
307
- return IRErrorCode::IRErrorCode_Incomplete_IR;
308
- }
309
- schema.push_back (static_cast <SchemaTree::Node::id_t >(id));
310
- } else if (cProtocol::Payload::KeyIdUShort == tag) {
311
- uint16_t id{};
312
- if (false == deserialize_int (reader, id)) {
313
- return IRErrorCode::IRErrorCode_Incomplete_IR;
314
- }
315
- schema.push_back (static_cast <SchemaTree::Node::id_t >(id));
316
- } else {
299
+ if (false == is_encoded_key_id_tag (tag)) {
300
+ // The log event must be an empty value.
317
301
break ;
318
302
}
319
303
304
+ auto const schema_tree_node_id_result{deserialize_and_decode_schema_tree_node_id<
305
+ cProtocol::Payload::EncodedSchemaTreeNodeIdByte,
306
+ cProtocol::Payload::EncodedSchemaTreeNodeIdShort,
307
+ cProtocol::Payload::EncodedSchemaTreeNodeIdInt>(tag, reader)};
308
+ if (schema_tree_node_id_result.has_error ()) {
309
+ return schema_tree_node_id_result.error ();
310
+ }
311
+ auto const [is_auto_generated, node_id]{schema_tree_node_id_result.value ()};
312
+ if (is_auto_generated) {
313
+ // Currently, we don't support auto-generated keys.
314
+ return std::errc::protocol_not_supported;
315
+ }
316
+ schema.push_back (node_id);
317
+
320
318
if (auto const err{deserialize_tag (reader, tag)}; IRErrorCode::IRErrorCode_Success != err) {
321
- return err;
319
+ return ir_error_code_to_errc ( err) ;
322
320
}
323
321
}
324
322
325
- return IRErrorCode::IRErrorCode_Success ;
323
+ return schema ;
326
324
}
327
325
328
326
auto deserialize_value_and_insert_to_node_id_value_pairs (
@@ -469,12 +467,24 @@ auto is_log_event_ir_unit_tag(encoded_tag_t tag) -> bool {
469
467
// The log event is an empty object
470
468
return true ;
471
469
}
472
- if (cProtocol::Payload::KeyIdUByte == tag || cProtocol::Payload::KeyIdUShort == tag ) {
470
+ if (is_encoded_key_id_tag ( tag) ) {
473
471
// If not empty, the log event must start with a tag byte indicating the key ID
474
472
return true ;
475
473
}
476
474
return false ;
477
475
}
476
+
477
+ auto is_encoded_key_id_tag (encoded_tag_t tag) -> bool {
478
+ // Ideally, we could check whether the tag is within the range of
479
+ // [EncodedKeyIdByte, EncodedKeyIdInt], but we don't for two reasons:
480
+ // - We optimize for streams that have few key IDs, meaning we can short circuit in the first
481
+ // branch below.
482
+ // - Using a range check assumes all length indicators are defined continuously, in order, but
483
+ // we don't have static checks for this assumption.
484
+ return cProtocol::Payload::EncodedSchemaTreeNodeIdByte == tag
485
+ || cProtocol::Payload::EncodedSchemaTreeNodeIdShort == tag
486
+ || cProtocol::Payload::EncodedSchemaTreeNodeIdInt == tag;
487
+ }
478
488
} // namespace
479
489
480
490
auto get_ir_unit_type_from_tag (encoded_tag_t tag) -> std::optional<IrUnitType> {
@@ -508,11 +518,14 @@ auto deserialize_ir_unit_schema_tree_node_insertion(
508
518
return ir_error_code_to_errc (IRErrorCode::IRErrorCode_Corrupted_IR);
509
519
}
510
520
511
- SchemaTree::Node::id_t parent_id{};
512
- if (auto const err{deserialize_schema_tree_node_parent_id (reader, parent_id)};
513
- IRErrorCode_Success != err)
514
- {
515
- return ir_error_code_to_errc (err);
521
+ auto const parent_node_id_result{deserialize_schema_tree_node_parent_id (reader)};
522
+ if (parent_node_id_result.has_error ()) {
523
+ return parent_node_id_result.error ();
524
+ }
525
+ auto const [is_auto_generated, parent_id]{parent_node_id_result.value ()};
526
+ if (is_auto_generated) {
527
+ // Currently, we don't support auto-generated keys.
528
+ return std::errc::protocol_not_supported;
516
529
}
517
530
518
531
if (auto const err{deserialize_schema_tree_node_key_name (reader, key_name)};
@@ -541,12 +554,11 @@ auto deserialize_ir_unit_kv_pair_log_event(
541
554
std::shared_ptr<SchemaTree> schema_tree,
542
555
UtcOffset utc_offset
543
556
) -> OUTCOME_V2_NAMESPACE::std_result<KeyValuePairLogEvent> {
544
- Schema schema;
545
- if (auto const err{deserialize_schema (reader, tag, schema)};
546
- IRErrorCode::IRErrorCode_Success != err)
547
- {
548
- return ir_error_code_to_errc (err);
557
+ auto const schema_result{deserialize_schema (reader, tag)};
558
+ if (schema_result.has_error ()) {
559
+ return schema_result.error ();
549
560
}
561
+ auto const & schema{schema_result.value ()};
550
562
551
563
KeyValuePairLogEvent::NodeIdValuePairs node_id_value_pairs;
552
564
if (false == schema.empty ()) {
0 commit comments