Skip to content

Commit

Permalink
Update FieldValue of type Reference (firebase#775)
Browse files Browse the repository at this point in the history
* update FieldValue of type Reference

* address change

* fix bad path string literal in test

* use ReferenceValue and qualified name
  • Loading branch information
zxu123 authored Feb 12, 2018
1 parent 4afcfb1 commit adf9fb3
Show file tree
Hide file tree
Showing 3 changed files with 104 additions and 5 deletions.
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

0 comments on commit adf9fb3

Please sign in to comment.