/* * 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_FIELD_VALUE_H_ #define FIRESTORE_CORE_SRC_FIREBASE_FIRESTORE_MODEL_FIELD_VALUE_H_ #include #include #include #include #include #include "Firestore/core/include/firebase/firestore/geo_point.h" #include "Firestore/core/src/firebase/firestore/model/database_id.h" #include "Firestore/core/src/firebase/firestore/model/document_key.h" #include "Firestore/core/src/firebase/firestore/model/timestamp.h" #include "Firestore/core/src/firebase/firestore/util/firebase_assert.h" namespace firebase { namespace firestore { namespace model { struct ServerTimestamp { Timestamp local_write_time; Timestamp previous_value; // TODO(zxu123): adopt absl::optional once abseil is ported. bool has_previous_value_; }; struct ReferenceValue { DocumentKey reference; // Does not own the DatabaseId instance. const DatabaseId* database_id; }; /** * tagged-union class representing an immutable data value as stored in * Firestore. FieldValue represents all the different kinds of values * that can be stored in fields in a document. */ class FieldValue { public: /** * All the different kinds of values that can be stored in fields in * a document. The types of the same comparison order should be defined * together as a group. The order of each group is defined by the Firestore * backend and is available at: * https://firebase.google.com/docs/firestore/manage-data/data-types */ enum class Type { Null, // Null Boolean, // Boolean Integer, // Number type starts here Double, Timestamp, // Timestamp type starts here ServerTimestamp, String, // String Blob, // Blob Reference, // Reference GeoPoint, // GeoPoint Array, // Array Object, // Object // New enum should not always been added at the tail. Add it to the correct // position instead, see the doc comment above. }; FieldValue() { } // Do not inline these ctor/dtor below, which contain call to non-trivial // operator=. FieldValue(const FieldValue& value); FieldValue(FieldValue&& value); ~FieldValue(); FieldValue& operator=(const FieldValue& value); FieldValue& operator=(FieldValue&& value); /** Returns the true type for this value. */ Type type() const { return tag_; } bool boolean_value() const { FIREBASE_ASSERT(tag_ == Type::Boolean); return boolean_value_; } int64_t integer_value() const { FIREBASE_ASSERT(tag_ == Type::Integer); return integer_value_; } const std::string& string_value() const { FIREBASE_ASSERT(tag_ == Type::String); return string_value_; } const std::map& object_value() const { FIREBASE_ASSERT(tag_ == Type::Object); return object_value_; } /** factory methods. */ static const FieldValue& NullValue(); static const FieldValue& TrueValue(); static const FieldValue& FalseValue(); static const FieldValue& BooleanValue(bool value); static const FieldValue& NanValue(); static FieldValue IntegerValue(int64_t value); static FieldValue DoubleValue(double value); static FieldValue TimestampValue(const Timestamp& value); static FieldValue ServerTimestampValue(const Timestamp& local_write_time, const Timestamp& previous_value); static FieldValue ServerTimestampValue(const Timestamp& local_write_time); static FieldValue StringValue(const char* value); static FieldValue StringValue(const std::string& value); static FieldValue StringValue(std::string&& value); static FieldValue BlobValue(const uint8_t* source, size_t size); static FieldValue ReferenceValue(const DocumentKey& value, const DatabaseId* database_id); static FieldValue ReferenceValue(DocumentKey&& value, const DatabaseId* database_id); static FieldValue GeoPointValue(const GeoPoint& value); static FieldValue ArrayValue(const std::vector& value); static FieldValue ArrayValue(std::vector&& value); static FieldValue ObjectValue(const std::map& value); static FieldValue ObjectValue(std::map&& value); friend bool operator<(const FieldValue& lhs, const FieldValue& rhs); private: explicit FieldValue(bool value) : tag_(Type::Boolean), boolean_value_(value) { } /** * Switch to the specified type, if different from the current type. */ void SwitchTo(const Type type); Type tag_ = Type::Null; union { // There is no null type as tag_ alone is enough for Null FieldValue. bool boolean_value_; int64_t integer_value_; double double_value_; Timestamp timestamp_value_; ServerTimestamp server_timestamp_value_; std::string string_value_; std::vector blob_value_; // Qualified name to avoid conflict with the member function of same name. firebase::firestore::model::ReferenceValue reference_value_; GeoPoint geo_point_value_; std::vector array_value_; std::map object_value_; }; }; /** Compares against another FieldValue. */ bool operator<(const FieldValue& lhs, const FieldValue& rhs); inline bool operator>(const FieldValue& lhs, const FieldValue& rhs) { return rhs < lhs; } inline bool operator>=(const FieldValue& lhs, const FieldValue& rhs) { return !(lhs < rhs); } inline bool operator<=(const FieldValue& lhs, const FieldValue& rhs) { return !(lhs > rhs); } inline bool operator!=(const FieldValue& lhs, const FieldValue& rhs) { return lhs < rhs || lhs > rhs; } inline bool operator==(const FieldValue& lhs, const FieldValue& rhs) { return !(lhs != rhs); } } // namespace model } // namespace firestore } // namespace firebase #endif // FIRESTORE_CORE_SRC_FIREBASE_FIRESTORE_MODEL_FIELD_VALUE_H_