serializer.h 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353
  1. /*
  2. * Copyright 2018 Google
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. #ifndef FIRESTORE_CORE_SRC_REMOTE_SERIALIZER_H_
  17. #define FIRESTORE_CORE_SRC_REMOTE_SERIALIZER_H_
  18. #include <stddef.h>
  19. #include <cstdint>
  20. #include <memory>
  21. #include <string>
  22. #include <unordered_map>
  23. #include <vector>
  24. #include "Firestore/Protos/nanopb/google/firestore/v1/document.nanopb.h"
  25. #include "Firestore/Protos/nanopb/google/firestore/v1/firestore.nanopb.h"
  26. #include "Firestore/Protos/nanopb/google/type/latlng.nanopb.h"
  27. #include "Firestore/core/src/core/composite_filter.h"
  28. #include "Firestore/core/src/core/core_fwd.h"
  29. #include "Firestore/core/src/core/field_filter.h"
  30. #include "Firestore/core/src/core/filter.h"
  31. #include "Firestore/core/src/core/order_by.h"
  32. #include "Firestore/core/src/model/database_id.h"
  33. #include "Firestore/core/src/model/model_fwd.h"
  34. #include "Firestore/core/src/model/resource_path.h"
  35. #include "Firestore/core/src/nanopb/byte_string.h"
  36. #include "Firestore/core/src/nanopb/writer.h"
  37. #include "Firestore/core/src/remote/watch_change.h"
  38. #include "Firestore/core/src/util/read_context.h"
  39. #include "Firestore/core/src/util/status_fwd.h"
  40. #include "absl/base/attributes.h"
  41. #include "absl/strings/string_view.h"
  42. namespace firebase {
  43. namespace firestore {
  44. namespace local {
  45. class LocalSerializer;
  46. class TargetData;
  47. enum class QueryPurpose;
  48. } // namespace local
  49. namespace remote {
  50. core::Target InvalidTarget();
  51. /**
  52. * @brief Converts internal model objects to their equivalent protocol buffer
  53. * form, and protocol buffer objects to their equivalent bytes.
  54. *
  55. * Methods starting with "Encode" convert from a model object to a nanopb
  56. * protocol buffer, and methods starting with "Decode" convert from a nanopb
  57. * protocol buffer to a model object.
  58. *
  59. * For encoded messages, `nanopb::FreeNanopbMessage()` must be called on the
  60. * returned nanopb proto buffer or a memory leak will occur.
  61. *
  62. * All errors that occur during serialization are fatal.
  63. *
  64. * All deserialization methods (that can fail) take a nanopb::Reader parameter
  65. * whose status will be set to failed upon an error. Callers must check this
  66. * before using the returned value via `reader->status()`. A deserialization
  67. * method might fail if a protocol buffer is missing a critical field or has a
  68. * value we can't interpret. On error, the return value from a deserialization
  69. * method is unspecified.
  70. */
  71. class Serializer {
  72. public:
  73. /**
  74. * @param database_id Must remain valid for the lifetime of this Serializer
  75. * object.
  76. */
  77. explicit Serializer(model::DatabaseId database_id);
  78. /**
  79. * Encodes the string to nanopb bytes.
  80. *
  81. * This method allocates memory; the caller is responsible for freeing it.
  82. * Typically, the returned value will be added to a pointer field within a
  83. * nanopb proto struct. Calling pb_release() on the resulting struct will
  84. * cause all proto fields to be freed.
  85. */
  86. static pb_bytes_array_t* EncodeString(const std::string& str);
  87. /**
  88. * Decodes the nanopb bytes to a std::string. If the input pointer is null,
  89. * then this method will return an empty string.
  90. */
  91. static std::string DecodeString(const pb_bytes_array_t* str);
  92. /**
  93. * Returns the database ID, such as
  94. * `projects/{project_id}/databases/{database_id}`.
  95. */
  96. pb_bytes_array_t* EncodeDatabaseName() const;
  97. /**
  98. * Encodes the given document key as a fully qualified name. This includes the
  99. * DatabaseId associated with this Serializer and the key path.
  100. */
  101. pb_bytes_array_t* EncodeKey(
  102. const firebase::firestore::model::DocumentKey& key) const;
  103. /**
  104. * Decodes the given document key from a fully qualified name.
  105. */
  106. firebase::firestore::model::DocumentKey DecodeKey(
  107. util::ReadContext* context, const pb_bytes_array_t* name) const;
  108. /**
  109. * @brief Converts the Document (i.e. key/value) into bytes.
  110. */
  111. google_firestore_v1_Document EncodeDocument(
  112. const model::DocumentKey& key, const model::ObjectValue& value) const;
  113. /**
  114. * @brief Converts from nanopb proto to the model Document format.
  115. */
  116. model::MutableDocument DecodeMaybeDocument(
  117. util::ReadContext* context,
  118. google_firestore_v1_BatchGetDocumentsResponse& response) const;
  119. google_firestore_v1_Write EncodeMutation(
  120. const model::Mutation& mutation) const;
  121. model::Mutation DecodeMutation(util::ReadContext* context,
  122. google_firestore_v1_Write& mutation) const;
  123. static google_firestore_v1_Precondition EncodePrecondition(
  124. const model::Precondition& precondition);
  125. static model::Precondition DecodePrecondition(
  126. util::ReadContext* context,
  127. const google_firestore_v1_Precondition& precondition);
  128. static google_firestore_v1_DocumentMask EncodeFieldMask(
  129. const model::FieldMask& mask);
  130. static model::FieldMask DecodeFieldMask(
  131. util::ReadContext* context, const google_firestore_v1_DocumentMask& mask);
  132. google_firestore_v1_DocumentTransform_FieldTransform EncodeFieldTransform(
  133. const model::FieldTransform& field_transform) const;
  134. model::FieldTransform DecodeFieldTransform(
  135. util::ReadContext* context,
  136. google_firestore_v1_DocumentTransform_FieldTransform& proto) const;
  137. model::MutationResult DecodeMutationResult(
  138. util::ReadContext* context,
  139. google_firestore_v1_WriteResult& write_result,
  140. const model::SnapshotVersion& commit_version) const;
  141. std::vector<google_firestore_v1_ListenRequest_LabelsEntry>
  142. EncodeListenRequestLabels(const local::TargetData& target_data) const;
  143. static pb_bytes_array_t* EncodeFieldPath(const model::FieldPath& field_path);
  144. static model::FieldPath DecodeFieldPath(util::ReadContext* context,
  145. const pb_bytes_array_t* field_path);
  146. static google_protobuf_Timestamp EncodeVersion(
  147. const model::SnapshotVersion& version);
  148. static google_protobuf_Timestamp EncodeTimestamp(
  149. const Timestamp& timestamp_value);
  150. static model::SnapshotVersion DecodeVersion(
  151. util::ReadContext* context, const google_protobuf_Timestamp& proto);
  152. static Timestamp DecodeTimestamp(
  153. util::ReadContext* context,
  154. const google_protobuf_Timestamp& timestamp_proto);
  155. google_firestore_v1_Target EncodeTarget(
  156. const local::TargetData& target_data) const;
  157. google_firestore_v1_Target_DocumentsTarget EncodeDocumentsTarget(
  158. const core::Target& target) const;
  159. core::Target DecodeDocumentsTarget(
  160. util::ReadContext* context,
  161. const google_firestore_v1_Target_DocumentsTarget& proto) const;
  162. google_firestore_v1_Target_QueryTarget EncodeQueryTarget(
  163. const core::Target& target) const;
  164. /**
  165. * Decodes the query target. Modifies the provided proto to release ownership
  166. * of any Value messages.
  167. */
  168. core::Target DecodeQueryTarget(
  169. util::ReadContext* context,
  170. google_firestore_v1_Target_QueryTarget& query) const;
  171. core::Target DecodeStructuredQuery(
  172. util::ReadContext* context,
  173. pb_bytes_array_t* parent,
  174. google_firestore_v1_StructuredQuery& query) const;
  175. /**
  176. * Decodes the watch change. Modifies the provided proto to release
  177. * ownership of any Value messages.
  178. */
  179. std::unique_ptr<remote::WatchChange> DecodeWatchChange(
  180. util::ReadContext* context,
  181. google_firestore_v1_ListenResponse& watch_change) const;
  182. model::SnapshotVersion DecodeVersionFromListenResponse(
  183. util::ReadContext* context,
  184. const google_firestore_v1_ListenResponse& listen_response) const;
  185. /**
  186. * Decodes the structured query. Modifies the provided proto to release
  187. * ownership of any Value messages.
  188. */
  189. std::vector<core::Filter> DecodeFilters(
  190. util::ReadContext* context,
  191. google_firestore_v1_StructuredQuery_Filter& proto) const;
  192. /**
  193. * Encodes a database ID and resource path into the following form:
  194. * /projects/$project_id/database/$database_id/documents/$path
  195. *
  196. * Does not verify that the database_id matches the current instance.
  197. */
  198. pb_bytes_array_t* EncodeResourceName(const model::DatabaseId& database_id,
  199. const model::ResourcePath& path) const;
  200. bool IsLocalResourceName(const model::ResourcePath& path) const;
  201. bool IsLocalDocumentKey(absl::string_view path) const;
  202. const model::DatabaseId& database_id() const {
  203. return database_id_;
  204. }
  205. private:
  206. friend class SerializerTest;
  207. model::MutableDocument DecodeFoundDocument(
  208. util::ReadContext* context,
  209. google_firestore_v1_BatchGetDocumentsResponse& response) const;
  210. model::MutableDocument DecodeMissingDocument(
  211. util::ReadContext* context,
  212. const google_firestore_v1_BatchGetDocumentsResponse& response) const;
  213. pb_bytes_array_t* EncodeQueryPath(const model::ResourcePath& path) const;
  214. model::ResourcePath DecodeQueryPath(util::ReadContext* context,
  215. absl::string_view name) const;
  216. /**
  217. * Decodes a fully qualified resource name into a resource path and validates
  218. * that there is a project and database encoded in the path. There are no
  219. * guarantees that a local path is also encoded in this resource name.
  220. */
  221. model::ResourcePath DecodeResourceName(util::ReadContext* context,
  222. absl::string_view encoded) const;
  223. void ValidateDocumentKeyPath(util::ReadContext* context,
  224. const model::ResourcePath& resource_name) const;
  225. model::DocumentKey DecodeKey(util::ReadContext* context,
  226. const model::ResourcePath& resource_name) const;
  227. std::string EncodeLabel(local::QueryPurpose purpose) const;
  228. google_firestore_v1_StructuredQuery_Filter EncodeFilters(
  229. const std::vector<core::Filter>& filter_list) const;
  230. google_firestore_v1_StructuredQuery_Filter EncodeFilter(
  231. const core::Filter& filter) const;
  232. google_firestore_v1_StructuredQuery_Filter EncodeUnaryOrFieldFilter(
  233. const core::FieldFilter& filter) const;
  234. google_firestore_v1_StructuredQuery_Filter EncodeCompositeFilter(
  235. const core::CompositeFilter& filter) const;
  236. util::StatusOr<core::Filter> DecodeFilter(
  237. util::ReadContext* context,
  238. google_firestore_v1_StructuredQuery_Filter& proto) const;
  239. core::Filter DecodeFieldFilter(
  240. util::ReadContext* context,
  241. google_firestore_v1_StructuredQuery_FieldFilter& field_filter) const;
  242. core::Filter DecodeUnaryFilter(
  243. util::ReadContext* context,
  244. const google_firestore_v1_StructuredQuery_UnaryFilter& unary) const;
  245. core::Filter DecodeCompositeFilter(
  246. util::ReadContext* context,
  247. const google_firestore_v1_StructuredQuery_CompositeFilter& composite)
  248. const;
  249. google_firestore_v1_StructuredQuery_FieldFilter_Operator
  250. EncodeFieldFilterOperator(core::FieldFilter::Operator op) const;
  251. google_firestore_v1_StructuredQuery_CompositeFilter_Operator
  252. EncodeCompositeFilterOperator(core::CompositeFilter::Operator op) const;
  253. core::FieldFilter::Operator DecodeFieldFilterOperator(
  254. util::ReadContext* context,
  255. google_firestore_v1_StructuredQuery_FieldFilter_Operator op) const;
  256. core::CompositeFilter::Operator DecodeCompositeFilterOperator(
  257. util::ReadContext* context,
  258. google_firestore_v1_StructuredQuery_CompositeFilter_Operator op) const;
  259. google_firestore_v1_StructuredQuery_Order* EncodeOrderBys(
  260. const std::vector<core::OrderBy>& orders) const;
  261. std::vector<core::OrderBy> DecodeOrderBys(
  262. util::ReadContext* context,
  263. google_firestore_v1_StructuredQuery_Order* order_bys,
  264. pb_size_t size) const;
  265. core::OrderBy DecodeOrderBy(
  266. util::ReadContext* context,
  267. const google_firestore_v1_StructuredQuery_Order& order_by) const;
  268. google_firestore_v1_Cursor EncodeCursor(
  269. const nanopb::SharedMessage<_google_firestore_v1_ArrayValue>& bound,
  270. bool before) const;
  271. nanopb::SharedMessage<_google_firestore_v1_ArrayValue> DecodeCursorValue(
  272. google_firestore_v1_Cursor& cursor) const;
  273. std::unique_ptr<remote::WatchChange> DecodeTargetChange(
  274. util::ReadContext* context,
  275. const google_firestore_v1_TargetChange& change) const;
  276. static remote::WatchTargetChangeState DecodeTargetChangeState(
  277. util::ReadContext* context,
  278. const google_firestore_v1_TargetChange_TargetChangeType state);
  279. std::unique_ptr<remote::WatchChange> DecodeDocumentChange(
  280. util::ReadContext* context,
  281. google_firestore_v1_DocumentChange& change) const;
  282. std::unique_ptr<remote::WatchChange> DecodeDocumentDelete(
  283. util::ReadContext* context,
  284. const google_firestore_v1_DocumentDelete& change) const;
  285. std::unique_ptr<remote::WatchChange> DecodeDocumentRemove(
  286. util::ReadContext* context,
  287. const google_firestore_v1_DocumentRemove& change) const;
  288. std::unique_ptr<remote::WatchChange> DecodeExistenceFilterWatchChange(
  289. util::ReadContext* context,
  290. const google_firestore_v1_ExistenceFilter& filter) const;
  291. model::DatabaseId database_id_;
  292. // TODO(varconst): Android caches the result of calling `EncodeDatabaseName`
  293. // as well, consider implementing that.
  294. };
  295. } // namespace remote
  296. } // namespace firestore
  297. } // namespace firebase
  298. #endif // FIRESTORE_CORE_SRC_REMOTE_SERIALIZER_H_