Skip to content

Update FieldValue of type Reference #775

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Feb 12, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 41 additions & 0 deletions Firestore/core/src/firebase/firestore/model/field_value.cc
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,9 @@ FieldValue& FieldValue::operator=(const FieldValue& value) {
std::swap(blob_value_, tmp);
break;
}
case Type::Reference:
reference_value_ = value.reference_value_;
break;
case Type::GeoPoint:
geo_point_value_ = value.geo_point_value_;
break;
Expand Down Expand Up @@ -131,6 +134,11 @@ FieldValue& FieldValue::operator=(FieldValue&& value) {
SwitchTo(Type::Blob);
std::swap(blob_value_, value.blob_value_);
return *this;
case Type::Reference:
SwitchTo(Type::Reference);
std::swap(reference_value_.reference, value.reference_value_.reference);
reference_value_.database_id = value.reference_value_.database_id;
return *this;
case Type::Array:
SwitchTo(Type::Array);
std::swap(array_value_, value.array_value_);
Expand Down Expand Up @@ -233,6 +241,26 @@ FieldValue FieldValue::BlobValue(const uint8_t* source, size_t size) {
return result;
}

// Does NOT pass ownership of database_id.
FieldValue FieldValue::ReferenceValue(const DocumentKey& value,
const DatabaseId* database_id) {
FieldValue result;
result.SwitchTo(Type::Reference);
result.reference_value_.reference = value;
result.reference_value_.database_id = database_id;
return result;
}

// Does NOT pass ownership of database_id.
FieldValue FieldValue::ReferenceValue(DocumentKey&& value,
const DatabaseId* database_id) {
FieldValue result;
result.SwitchTo(Type::Reference);
std::swap(result.reference_value_.reference, value);
result.reference_value_.database_id = database_id;
return result;
}

FieldValue FieldValue::GeoPointValue(const GeoPoint& value) {
FieldValue result;
result.SwitchTo(Type::GeoPoint);
Expand Down Expand Up @@ -309,6 +337,12 @@ bool operator<(const FieldValue& lhs, const FieldValue& rhs) {
return lhs.string_value_.compare(rhs.string_value_) < 0;
case Type::Blob:
return lhs.blob_value_ < rhs.blob_value_;
case Type::Reference:
return *lhs.reference_value_.database_id <
*rhs.reference_value_.database_id ||
(*lhs.reference_value_.database_id ==
*rhs.reference_value_.database_id &&
lhs.reference_value_.reference < rhs.reference_value_.reference);
case Type::GeoPoint:
return lhs.geo_point_value_ < rhs.geo_point_value_;
case Type::Array:
Expand Down Expand Up @@ -343,6 +377,9 @@ void FieldValue::SwitchTo(const Type type) {
case Type::Blob:
blob_value_.~vector();
break;
case Type::Reference:
reference_value_.~ReferenceValue();
break;
case Type::GeoPoint:
geo_point_value_.~GeoPoint();
break;
Expand Down Expand Up @@ -370,6 +407,10 @@ void FieldValue::SwitchTo(const Type type) {
// Do not even bother to allocate a new array of size 0.
new (&blob_value_) std::vector<uint8_t>();
break;
case Type::Reference:
// Qualified name to avoid conflict with the member function of same name.
new (&reference_value_) firebase::firestore::model::ReferenceValue();
break;
case Type::GeoPoint:
new (&geo_point_value_) GeoPoint();
break;
Expand Down
15 changes: 14 additions & 1 deletion Firestore/core/src/firebase/firestore/model/field_value.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@
#include <vector>

#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"

namespace firebase {
Expand All @@ -38,6 +40,12 @@ struct ServerTimestamp {
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
Expand Down Expand Up @@ -103,7 +111,10 @@ class FieldValue {
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();
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<FieldValue>& value);
static FieldValue ArrayValue(std::vector<FieldValue>&& value);
Expand Down Expand Up @@ -133,6 +144,8 @@ class FieldValue {
ServerTimestamp server_timestamp_value_;
std::string string_value_;
std::vector<uint8_t> 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<FieldValue> array_value_;
std::map<const std::string, const FieldValue> object_value_;
Expand Down
53 changes: 49 additions & 4 deletions Firestore/core/test/firebase/firestore/model/field_value_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,20 @@ TEST(FieldValue, BlobType) {
EXPECT_FALSE(a < a);
}

TEST(FieldValue, ReferenceType) {
const DatabaseId id("project", "database");
const FieldValue a =
FieldValue::ReferenceValue(DocumentKey::FromPathString("root/abc"), &id);
DocumentKey key = DocumentKey::FromPathString("root/def");
const FieldValue b = FieldValue::ReferenceValue(key, &id);
const FieldValue c = FieldValue::ReferenceValue(std::move(key), &id);
EXPECT_EQ(Type::Reference, a.type());
EXPECT_EQ(Type::Reference, b.type());
EXPECT_EQ(Type::Reference, c.type());
EXPECT_TRUE(a < b);
EXPECT_FALSE(a < a);
}

TEST(FieldValue, GeoPointType) {
const FieldValue a = FieldValue::GeoPointValue({1, 2});
const FieldValue b = FieldValue::GeoPointValue({3, 4});
Expand Down Expand Up @@ -280,6 +294,23 @@ TEST(FieldValue, Copy) {
clone = null_value;
EXPECT_EQ(FieldValue::NullValue(), clone);

const DatabaseId database_id("project", "database");
const FieldValue reference_value = FieldValue::ReferenceValue(
DocumentKey::FromPathString("root/abc"), &database_id);
clone = reference_value;
EXPECT_EQ(FieldValue::ReferenceValue(DocumentKey::FromPathString("root/abc"),
&database_id),
clone);
EXPECT_EQ(FieldValue::ReferenceValue(DocumentKey::FromPathString("root/abc"),
&database_id),
reference_value);
clone = clone;
EXPECT_EQ(FieldValue::ReferenceValue(DocumentKey::FromPathString("root/abc"),
&database_id),
clone);
clone = null_value;
EXPECT_EQ(FieldValue::NullValue(), clone);

const FieldValue geo_point_value = FieldValue::GeoPointValue({1, 2});
clone = geo_point_value;
EXPECT_EQ(FieldValue::GeoPointValue({1, 2}), clone);
Expand Down Expand Up @@ -361,7 +392,7 @@ TEST(FieldValue, Move) {
clone = FieldValue::NullValue();
EXPECT_EQ(FieldValue::NullValue(), clone);

const FieldValue timestamp_value = FieldValue::TimestampValue({100, 200});
FieldValue timestamp_value = FieldValue::TimestampValue({100, 200});
clone = std::move(timestamp_value);
EXPECT_EQ(FieldValue::TimestampValue({100, 200}), clone);
clone = FieldValue::NullValue();
Expand All @@ -373,13 +404,23 @@ TEST(FieldValue, Move) {
clone = FieldValue::NullValue();
EXPECT_EQ(FieldValue::NullValue(), clone);

const FieldValue blob_value = FieldValue::BlobValue(Bytes("abc"), 4);
FieldValue blob_value = FieldValue::BlobValue(Bytes("abc"), 4);
clone = std::move(blob_value);
EXPECT_EQ(FieldValue::BlobValue(Bytes("abc"), 4), clone);
clone = FieldValue::NullValue();
EXPECT_EQ(FieldValue::NullValue(), clone);

const FieldValue geo_point_value = FieldValue::GeoPointValue({1, 2});
const DatabaseId database_id("project", "database");
FieldValue reference_value = FieldValue::ReferenceValue(
DocumentKey::FromPathString("root/abc"), &database_id);
clone = std::move(reference_value);
EXPECT_EQ(FieldValue::ReferenceValue(DocumentKey::FromPathString("root/abc"),
&database_id),
clone);
clone = null_value;
EXPECT_EQ(FieldValue::NullValue(), clone);

FieldValue geo_point_value = FieldValue::GeoPointValue({1, 2});
clone = std::move(geo_point_value);
EXPECT_EQ(FieldValue::GeoPointValue({1, 2}), clone);
clone = null_value;
Expand Down Expand Up @@ -415,6 +456,9 @@ TEST(FieldValue, CompareMixedType) {
const FieldValue timestamp_value = FieldValue::TimestampValue({100, 200});
const FieldValue string_value = FieldValue::StringValue("abc");
const FieldValue blob_value = FieldValue::BlobValue(Bytes("abc"), 4);
const DatabaseId database_id("project", "database");
const FieldValue reference_value = FieldValue::ReferenceValue(
DocumentKey::FromPathString("root/abc"), &database_id);
const FieldValue geo_point_value = FieldValue::GeoPointValue({1, 2});
const FieldValue array_value =
FieldValue::ArrayValue(std::vector<FieldValue>());
Expand All @@ -425,7 +469,8 @@ TEST(FieldValue, CompareMixedType) {
EXPECT_TRUE(number_value < timestamp_value);
EXPECT_TRUE(timestamp_value < string_value);
EXPECT_TRUE(string_value < blob_value);
EXPECT_TRUE(blob_value < geo_point_value);
EXPECT_TRUE(blob_value < reference_value);
EXPECT_TRUE(reference_value < geo_point_value);
EXPECT_TRUE(geo_point_value < array_value);
EXPECT_TRUE(array_value < object_value);
}
Expand Down