diff options
Diffstat (limited to 'Firestore/core/src/firebase/firestore/remote/serializer.cc')
-rw-r--r-- | Firestore/core/src/firebase/firestore/remote/serializer.cc | 88 |
1 files changed, 83 insertions, 5 deletions
diff --git a/Firestore/core/src/firebase/firestore/remote/serializer.cc b/Firestore/core/src/firebase/firestore/remote/serializer.cc index d3cdd3f..e503d09 100644 --- a/Firestore/core/src/firebase/firestore/remote/serializer.cc +++ b/Firestore/core/src/firebase/firestore/remote/serializer.cc @@ -16,16 +16,94 @@ #include "Firestore/core/src/firebase/firestore/remote/serializer.h" -// TODO(rsgowman): These are (currently!) unnecessary includes. Adding for now -// to ensure we can find nanopb's generated header files. -#include "Firestore/Protos/nanopb/google/firestore/v1beta1/document.pb.h" -#include "Firestore/Protos/nanopb/google/protobuf/timestamp.pb.h" +#include <pb_decode.h> +#include <pb_encode.h> namespace firebase { namespace firestore { namespace remote { -Serializer::Serializer() { +using firebase::firestore::model::FieldValue; + +Serializer::TypedValue Serializer::EncodeFieldValue( + const FieldValue& field_value) { + Serializer::TypedValue proto_value{ + field_value.type(), google_firestore_v1beta1_Value_init_default}; + switch (field_value.type()) { + case FieldValue::Type::Null: + proto_value.value.null_value = google_protobuf_NullValue_NULL_VALUE; + break; + default: + // TODO(rsgowman): implement the other types + abort(); + } + return proto_value; +} + +void Serializer::EncodeTypedValue(const TypedValue& value, + std::vector<uint8_t>* out_bytes) { + bool status; + // TODO(rsgowman): how large should the output buffer be? Do some + // investigation to see if we can get nanopb to tell us how much space it's + // going to need. + uint8_t buf[1024]; + pb_ostream_t stream = pb_ostream_from_buffer(buf, sizeof(buf)); + switch (value.type) { + case FieldValue::Type::Null: + status = pb_encode_tag(&stream, PB_WT_VARINT, + google_firestore_v1beta1_Value_null_value_tag); + if (!status) { + // TODO(rsgowman): figure out error handling + abort(); + } + + status = pb_encode_varint(&stream, value.value.null_value); + if (!status) { + // TODO(rsgowman): figure out error handling + abort(); + } + + out_bytes->insert(out_bytes->end(), buf, buf + stream.bytes_written); + + break; + + default: + // TODO(rsgowman): implement the other types + abort(); + } +} + +FieldValue Serializer::DecodeFieldValue( + const Serializer::TypedValue& value_proto) { + switch (value_proto.type) { + case FieldValue::Type::Null: + return FieldValue::NullValue(); + default: + // TODO(rsgowman): implement the other types + abort(); + } +} + +Serializer::TypedValue Serializer::DecodeTypedValue(const uint8_t* bytes, + size_t length) { + pb_istream_t stream = pb_istream_from_buffer(bytes, length); + pb_wire_type_t wire_type; + uint32_t tag; + bool eof; + bool status = pb_decode_tag(&stream, &wire_type, &tag, &eof); + if (!status || wire_type != PB_WT_VARINT) { + // TODO(rsgowman): figure out error handling + abort(); + } + + switch (tag) { + case google_firestore_v1beta1_Value_null_value_tag: + return Serializer::TypedValue{ + FieldValue::Type::Null, google_firestore_v1beta1_Value_init_default}; + default: + // TODO(rsgowman): figure out error handling + abort(); + } } } // namespace remote |