aboutsummaryrefslogtreecommitdiffhomepage
path: root/Firestore/core/src/firebase/firestore/model
diff options
context:
space:
mode:
authorGravatar zxu <zxu@google.com>2018-04-12 21:32:19 -0400
committerGravatar GitHub <noreply@github.com>2018-04-12 21:32:19 -0400
commit2ceea9b66eb8ea516702e1ef409e801fec068682 (patch)
tree31de20fc11306df23b41f373c3768c03f2185359 /Firestore/core/src/firebase/firestore/model
parentac969c721a129e888177756fa2a6ae52af0dd04a (diff)
Port `Precondition` to C++ (#1040)
* port FieldMask to C++ * address changes * address changes * fix test * address change * Port transform operations (FSTTransformOperation, FSTServerTimestampTransform) to C++ * address changes * address changes * address changes * implement `FieldTransform` in C++ * port `FieldTransform` * make `fieldTransforms` shared inside `context` * Implement Precondition in C++ w/o test yet * add unit test for `Precondition` * port `Precondition` * address changes * address changes * fix bugs for integration test * address changes * fix lint * address changes * address changes
Diffstat (limited to 'Firestore/core/src/firebase/firestore/model')
-rw-r--r--Firestore/core/src/firebase/firestore/model/CMakeLists.txt2
-rw-r--r--Firestore/core/src/firebase/firestore/model/precondition.cc67
-rw-r--r--Firestore/core/src/firebase/firestore/model/precondition.h160
-rw-r--r--Firestore/core/src/firebase/firestore/model/snapshot_version.h23
4 files changed, 252 insertions, 0 deletions
diff --git a/Firestore/core/src/firebase/firestore/model/CMakeLists.txt b/Firestore/core/src/firebase/firestore/model/CMakeLists.txt
index de783ad..02affdb 100644
--- a/Firestore/core/src/firebase/firestore/model/CMakeLists.txt
+++ b/Firestore/core/src/firebase/firestore/model/CMakeLists.txt
@@ -32,6 +32,8 @@ cc_library(
maybe_document.h
no_document.cc
no_document.h
+ precondition.cc
+ precondition.h
resource_path.cc
resource_path.h
snapshot_version.cc
diff --git a/Firestore/core/src/firebase/firestore/model/precondition.cc b/Firestore/core/src/firebase/firestore/model/precondition.cc
new file mode 100644
index 0000000..423d5a2
--- /dev/null
+++ b/Firestore/core/src/firebase/firestore/model/precondition.cc
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2018 Google
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "Firestore/core/src/firebase/firestore/model/precondition.h"
+
+#include "Firestore/core/src/firebase/firestore/model/maybe_document.h"
+#include "Firestore/core/src/firebase/firestore/model/snapshot_version.h"
+#include "Firestore/core/src/firebase/firestore/util/firebase_assert.h"
+
+namespace firebase {
+namespace firestore {
+namespace model {
+
+Precondition::Precondition(Type type, SnapshotVersion update_time, bool exists)
+ : type_(type), update_time_(std::move(update_time)), exists_(exists) {
+}
+
+/* static */
+Precondition Precondition::Exists(bool exists) {
+ return Precondition{Type::Exists, SnapshotVersion::None(), exists};
+}
+
+/* static */
+Precondition Precondition::UpdateTime(SnapshotVersion update_time) {
+ // update_time could be SnapshotVersion::None() in particular for locally
+ // deleted documents.
+ return Precondition{Type::UpdateTime, std::move(update_time), false};
+}
+
+/* static */
+Precondition Precondition::None() {
+ return Precondition{Type::None, SnapshotVersion::None(), false};
+}
+
+bool Precondition::IsValidFor(const MaybeDocument& maybe_doc) const {
+ switch (type_) {
+ case Type::UpdateTime:
+ return maybe_doc.type() == MaybeDocument::Type::Document &&
+ maybe_doc.version() == update_time_;
+ case Type::Exists:
+ if (exists_) {
+ return maybe_doc.type() == MaybeDocument::Type::Document;
+ } else {
+ return maybe_doc.type() == MaybeDocument::Type::NoDocument;
+ }
+ case Type::None:
+ return true;
+ }
+ FIREBASE_UNREACHABLE();
+}
+
+} // namespace model
+} // namespace firestore
+} // namespace firebase
diff --git a/Firestore/core/src/firebase/firestore/model/precondition.h b/Firestore/core/src/firebase/firestore/model/precondition.h
new file mode 100644
index 0000000..4ab03c2
--- /dev/null
+++ b/Firestore/core/src/firebase/firestore/model/precondition.h
@@ -0,0 +1,160 @@
+/*
+ * Copyright 2018 Google
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef FIRESTORE_CORE_SRC_FIREBASE_FIRESTORE_MODEL_PRECONDITION_H_
+#define FIRESTORE_CORE_SRC_FIREBASE_FIRESTORE_MODEL_PRECONDITION_H_
+
+#include <utility>
+
+#if defined(__OBJC__)
+#import "FIRTimestamp.h"
+#import "Firestore/Source/Core/FSTSnapshotVersion.h"
+#import "Firestore/Source/Model/FSTDocument.h"
+#include "Firestore/core/include/firebase/firestore/timestamp.h"
+#endif // defined(__OBJC__)
+
+#include "Firestore/core/src/firebase/firestore/model/maybe_document.h"
+#include "Firestore/core/src/firebase/firestore/model/snapshot_version.h"
+#include "Firestore/core/src/firebase/firestore/util/firebase_assert.h"
+
+namespace firebase {
+namespace firestore {
+namespace model {
+
+/**
+ * Encodes a precondition for a mutation. This follows the model that the
+ * backend accepts with the special case of an explicit "empty" precondition
+ * (meaning no precondition).
+ */
+class Precondition {
+ public:
+ enum class Type {
+ None,
+ Exists,
+ UpdateTime,
+ };
+
+ /** Creates a new Precondition with an exists flag. */
+ static Precondition Exists(bool exists);
+
+ /** Creates a new Precondition based on a time the document exists at. */
+ static Precondition UpdateTime(SnapshotVersion update_time);
+
+ /** Returns a precondition representing no precondition. */
+ static Precondition None();
+
+ /**
+ * Returns true if the precondition is valid for the given document (and the
+ * document is available).
+ */
+ bool IsValidFor(const MaybeDocument& maybe_doc) const;
+
+ /** Returns whether this Precondition represents no precondition. */
+ bool IsNone() const {
+ return type_ == Type::None;
+ }
+
+ Type type() const {
+ return type_;
+ }
+
+ const SnapshotVersion& update_time() const {
+ return update_time_;
+ }
+
+ bool operator==(const Precondition& other) const {
+ return type_ == other.type_ && update_time_ == other.update_time_ &&
+ exists_ == other.exists_;
+ }
+
+#if defined(__OBJC__)
+ // Objective-C requires a default constructor.
+ Precondition()
+ : type_(Type::None),
+ update_time_(SnapshotVersion::None()),
+ exists_(false) {
+ }
+
+ // MaybeDocument is not fully ported yet. So we suppose this addition helper.
+ bool IsValidFor(FSTMaybeDocument* maybe_doc) const {
+ switch (type_) {
+ case Type::UpdateTime:
+ return [maybe_doc isKindOfClass:[FSTDocument class]] &&
+ firebase::firestore::model::SnapshotVersion(maybe_doc.version) ==
+ update_time_;
+ case Type::Exists:
+ if (exists_) {
+ return [maybe_doc isKindOfClass:[FSTDocument class]];
+ } else {
+ return maybe_doc == nil ||
+ [maybe_doc isKindOfClass:[FSTDeletedDocument class]];
+ }
+ case Type::None:
+ return true;
+ }
+ FIREBASE_UNREACHABLE();
+ }
+
+ // For Objective-C++ hash; to be removed after migration.
+ // Do NOT use in C++ code.
+ NSUInteger Hash() const {
+ NSUInteger hash = std::hash<Timestamp>()(update_time_.timestamp());
+ hash = hash * 31 + exists_;
+ hash = hash * 31 + static_cast<NSUInteger>(type_);
+ return hash;
+ }
+
+ NSString* description() const {
+ switch (type_) {
+ case Type::None:
+ return @"<Precondition <none>>";
+ case Type::Exists:
+ if (exists_) {
+ return @"<Precondition exists=yes>";
+ } else {
+ return @"<Precondition exists=no>";
+ }
+ case Type::UpdateTime:
+ return [NSString
+ stringWithFormat:@"<Precondition update_time=%s>",
+ update_time_.timestamp().ToString().c_str()];
+ }
+ // We only raise dev assertion here. This function is mainly used in
+ // logging.
+ FIREBASE_DEV_ASSERT_MESSAGE(false, "precondition invalid");
+ return @"<Precondition invalid>";
+ }
+#endif // defined(__OBJC__)
+
+ private:
+ Precondition(Type type, SnapshotVersion update_time, bool exists);
+
+ // The actual time of this precondition.
+ Type type_ = Type::None;
+
+ // For UpdateTime type, preconditions a mutation based on the last updateTime.
+ SnapshotVersion update_time_;
+
+ // For Exists type, preconditions a mutation based on whether the document
+ // exists.
+ bool exists_;
+};
+
+} // namespace model
+} // namespace firestore
+} // namespace firebase
+
+#endif // FIRESTORE_CORE_SRC_FIREBASE_FIRESTORE_MODEL_PRECONDITION_H_
diff --git a/Firestore/core/src/firebase/firestore/model/snapshot_version.h b/Firestore/core/src/firebase/firestore/model/snapshot_version.h
index 56e8c50..1fbba1c 100644
--- a/Firestore/core/src/firebase/firestore/model/snapshot_version.h
+++ b/Firestore/core/src/firebase/firestore/model/snapshot_version.h
@@ -19,6 +19,11 @@
#include "Firestore/core/include/firebase/firestore/timestamp.h"
+#if defined(__OBJC__)
+#import "FIRTimestamp.h"
+#import "Firestore/Source/Core/FSTSnapshotVersion.h"
+#endif // defined(__OBJC__)
+
namespace firebase {
namespace firestore {
namespace model {
@@ -38,6 +43,24 @@ class SnapshotVersion {
/** Creates a new version that is smaller than all other versions. */
static const SnapshotVersion& None();
+#if defined(__OBJC__)
+ SnapshotVersion(FSTSnapshotVersion* version) // NOLINT(runtime/explicit)
+ : timestamp_{version.timestamp.seconds, version.timestamp.nanoseconds} {
+ }
+
+ operator FSTSnapshotVersion*() const {
+ if (timestamp_ == Timestamp{}) {
+ return [FSTSnapshotVersion noVersion];
+ } else {
+ return [FSTSnapshotVersion
+ versionWithTimestamp:[FIRTimestamp
+ timestampWithSeconds:timestamp_.seconds()
+ nanoseconds:timestamp_
+ .nanoseconds()]];
+ }
+ }
+#endif // defined(__OBJC__)
+
private:
Timestamp timestamp_;
};