From 6ab9a059f28e286e79d4dbc6e5b9edd4a440d589 Mon Sep 17 00:00:00 2001 From: rsgowman Date: Wed, 23 May 2018 10:03:10 -0400 Subject: Deserialize NoDocument instances (#1311) Note that it isn't possible to *serialize* NoDocuments. Still TODO: - Error handling --- .../src/firebase/firestore/remote/serializer.cc | 114 +++++++++++++++------ 1 file changed, 80 insertions(+), 34 deletions(-) (limited to 'Firestore/core/src/firebase/firestore') diff --git a/Firestore/core/src/firebase/firestore/remote/serializer.cc b/Firestore/core/src/firebase/firestore/remote/serializer.cc index 47c2abf..6ea5844 100644 --- a/Firestore/core/src/firebase/firestore/remote/serializer.cc +++ b/Firestore/core/src/firebase/firestore/remote/serializer.cc @@ -499,45 +499,91 @@ Serializer::DecodeMaybeDocument(const uint8_t* bytes, size_t length) const { std::unique_ptr Serializer::DecodeBatchGetDocumentsResponse( Reader* reader) const { - Tag tag = reader->ReadTag(); if (!reader->status().ok()) return nullptr; - // Ensure the tag matches the wire type - switch (tag.field_number) { - case google_firestore_v1beta1_BatchGetDocumentsResponse_found_tag: - case google_firestore_v1beta1_BatchGetDocumentsResponse_missing_tag: - if (tag.wire_type != PB_WT_STRING) { - reader->set_status( - Status(FirestoreErrorCode::DataLoss, - "Input proto bytes cannot be parsed (mismatch between " - "the wiretype and the field number (tag))")); - } - break; + // Initialize BatchGetDocumentsResponse fields to their default values + std::unique_ptr found; + std::string missing; + // TODO(rsgowman): transaction + SnapshotVersion read_time = SnapshotVersion::None(); - default: - reader->set_status(Status( - FirestoreErrorCode::DataLoss, - "Input proto bytes cannot be parsed (invalid field number (tag))")); - } + while (reader->bytes_left()) { + Tag tag = reader->ReadTag(); + if (!reader->status().ok()) return nullptr; - if (!reader->status().ok()) return nullptr; + // Ensure the tag matches the wire type + switch (tag.field_number) { + case google_firestore_v1beta1_BatchGetDocumentsResponse_found_tag: + case google_firestore_v1beta1_BatchGetDocumentsResponse_missing_tag: + case google_firestore_v1beta1_BatchGetDocumentsResponse_read_time_tag: + if (tag.wire_type != PB_WT_STRING) { + reader->set_status( + Status(FirestoreErrorCode::DataLoss, + "Input proto bytes cannot be parsed (mismatch between " + "the wiretype and the field number (tag))")); + } + break; - switch (tag.field_number) { - case google_firestore_v1beta1_BatchGetDocumentsResponse_found_tag: - return reader->ReadNestedMessage>( - [this](Reader* reader) -> std::unique_ptr { - return DecodeDocument(reader); - }); - case google_firestore_v1beta1_BatchGetDocumentsResponse_missing_tag: - // TODO(rsgowman): Right now, we only support Document (and don't support - // NoDocument). That should change in the next PR or so. - abort(); - default: - // This indicates an internal error as we've already ensured that this is - // a valid field_number. - HARD_FAIL( - "Somehow got an unexpected field number (tag) after verifying that " - "the field number was expected."); + case google_firestore_v1beta1_BatchGetDocumentsResponse_transaction_tag: + // TODO(rsgowman) + abort(); + + default: + reader->set_status(Status( + FirestoreErrorCode::DataLoss, + "Input proto bytes cannot be parsed (invalid field number (tag))")); + } + + if (!reader->status().ok()) return nullptr; + + switch (tag.field_number) { + case google_firestore_v1beta1_BatchGetDocumentsResponse_found_tag: + // 'found' and 'missing' are part of a oneof. The proto docs claim that + // if both are set on the wire, the last one wins. + missing = ""; + + // TODO(rsgowman): If multiple 'found' values are found, we should merge + // them (rather than using the last one.) + found = reader->ReadNestedMessage>( + [this](Reader* reader) -> std::unique_ptr { + return DecodeDocument(reader); + }); + break; + + case google_firestore_v1beta1_BatchGetDocumentsResponse_missing_tag: + // 'found' and 'missing' are part of a oneof. The proto docs claim that + // if both are set on the wire, the last one wins. + found = nullptr; + + missing = reader->ReadString(); + break; + + case google_firestore_v1beta1_BatchGetDocumentsResponse_transaction_tag: + // TODO(rsgowman) + abort(); + + case google_firestore_v1beta1_BatchGetDocumentsResponse_read_time_tag: + read_time = SnapshotVersion{ + reader->ReadNestedMessage(DecodeTimestamp)}; + break; + + default: + // This indicates an internal error as we've already ensured that this + // is a valid field_number. + HARD_FAIL( + "Somehow got an unexpected field number (tag) after verifying that " + "the field number was expected."); + } + } + + if (found != nullptr) { + return found; + } else if (!missing.empty()) { + return absl::make_unique(DecodeKey(missing), read_time); + } else { + // Neither 'found' nor 'missing' fields were set. + // TODO(rsgowman): Handle the error case. + abort(); } } -- cgit v1.2.3