diff options
author | rsgowman <rgowman@google.com> | 2018-05-23 10:03:10 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-05-23 10:03:10 -0400 |
commit | 6ab9a059f28e286e79d4dbc6e5b9edd4a440d589 (patch) | |
tree | 46acd39e7f76e8647a1aa1d7c8d86f552c74022f /Firestore/core/src/firebase/firestore/remote/serializer.cc | |
parent | af19a1b07245b7d0be4fd492bd3731964937c7c6 (diff) |
Deserialize NoDocument instances (#1311)
Note that it isn't possible to *serialize* NoDocuments.
Still TODO:
- Error handling
Diffstat (limited to 'Firestore/core/src/firebase/firestore/remote/serializer.cc')
-rw-r--r-- | Firestore/core/src/firebase/firestore/remote/serializer.cc | 114 |
1 files changed, 80 insertions, 34 deletions
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<MaybeDocument> 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<MaybeDocument> 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<std::unique_ptr<MaybeDocument>>( - [this](Reader* reader) -> std::unique_ptr<MaybeDocument> { - 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<std::unique_ptr<MaybeDocument>>( + [this](Reader* reader) -> std::unique_ptr<MaybeDocument> { + 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<Timestamp>(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<NoDocument>(DecodeKey(missing), read_time); + } else { + // Neither 'found' nor 'missing' fields were set. + // TODO(rsgowman): Handle the error case. + abort(); } } |