From 2ceea9b66eb8ea516702e1ef409e801fec068682 Mon Sep 17 00:00:00 2001 From: zxu Date: Thu, 12 Apr 2018 21:32:19 -0400 Subject: 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 --- .../src/firebase/firestore/model/precondition.h | 160 +++++++++++++++++++++ 1 file changed, 160 insertions(+) create mode 100644 Firestore/core/src/firebase/firestore/model/precondition.h (limited to 'Firestore/core/src/firebase/firestore/model/precondition.h') 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 + +#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()(update_time_.timestamp()); + hash = hash * 31 + exists_; + hash = hash * 31 + static_cast(type_); + return hash; + } + + NSString* description() const { + switch (type_) { + case Type::None: + return @">"; + case Type::Exists: + if (exists_) { + return @""; + } else { + return @""; + } + case Type::UpdateTime: + return [NSString + stringWithFormat:@"", + 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 @""; + } +#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_ -- cgit v1.2.3