Kaynağa Gözat

Replace OrderByList by std::vector<OrderBy> (#10402)

* Replace OrderByList by std::vector<OrderBy>

* Remove unordered_set

* Revert "Remove unordered_set"

This reverts commit f9df4691ef62897e48ec6ce80761396e7bdc12ca.
cherylEnkidu 3 yıl önce
ebeveyn
işleme
da7f1dd986

+ 0 - 14
Firestore/Example/Firestore.xcodeproj/project.pbxproj

@@ -64,7 +64,6 @@
 		095A878BB33211AB52BFAD9F /* leveldb_document_overlay_cache_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = AE89CFF09C6804573841397F /* leveldb_document_overlay_cache_test.cc */; };
 		0963F6D7B0F9AE1E24B82866 /* path_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 403DBF6EFB541DFD01582AA3 /* path_test.cc */; };
 		096BA3A3703AC1491F281618 /* index.pb.cc in Sources */ = {isa = PBXBuildFile; fileRef = 395E8B07639E69290A929695 /* index.pb.cc */; };
-		098191405BA24F9A7E4F80C6 /* append_only_list_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 5477CDE922EE71C8000FCC1E /* append_only_list_test.cc */; };
 		0A4E1B5E3E853763AE6ED7AE /* grpc_stream_tester.cc in Sources */ = {isa = PBXBuildFile; fileRef = 87553338E42B8ECA05BA987E /* grpc_stream_tester.cc */; };
 		0A52B47C43B7602EE64F53A7 /* cc_compilation_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 1B342370EAE3AA02393E33EB /* cc_compilation_test.cc */; };
 		0A6FBE65A7FE048BAD562A15 /* FSTGoogleTestTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 54764FAE1FAA21B90085E60A /* FSTGoogleTestTests.mm */; };
@@ -459,8 +458,6 @@
 		54740A571FC914BA00713A1A /* secure_random_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 54740A531FC913E500713A1A /* secure_random_test.cc */; };
 		54740A581FC914F000713A1A /* autoid_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 54740A521FC913E500713A1A /* autoid_test.cc */; };
 		54764FAF1FAA21B90085E60A /* FSTGoogleTestTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 54764FAE1FAA21B90085E60A /* FSTGoogleTestTests.mm */; };
-		5477CDEA22EE71C8000FCC1E /* append_only_list_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 5477CDE922EE71C8000FCC1E /* append_only_list_test.cc */; };
-		5477CDEB22EE71C8000FCC1E /* append_only_list_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 5477CDE922EE71C8000FCC1E /* append_only_list_test.cc */; };
 		547E9A4222F9EA7300A275E0 /* document_set_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 547E9A4122F9EA7300A275E0 /* document_set_test.cc */; };
 		547E9A4322F9EA7300A275E0 /* document_set_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 547E9A4122F9EA7300A275E0 /* document_set_test.cc */; };
 		547E9A4422F9EA7300A275E0 /* document_set_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 547E9A4122F9EA7300A275E0 /* document_set_test.cc */; };
@@ -560,7 +557,6 @@
 		55E84644D385A70E607A0F91 /* leveldb_local_store_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 5FF903AEFA7A3284660FA4C5 /* leveldb_local_store_test.cc */; };
 		568EC1C0F68A7B95E57C8C6C /* leveldb_key_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 54995F6E205B6E12004EFFA0 /* leveldb_key_test.cc */; };
 		56D85436D3C864B804851B15 /* string_format_apple_test.mm in Sources */ = {isa = PBXBuildFile; fileRef = 9CFD366B783AE27B9E79EE7A /* string_format_apple_test.mm */; };
-		57BDB8DBEDEC4C61DB497CB4 /* append_only_list_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 5477CDE922EE71C8000FCC1E /* append_only_list_test.cc */; };
 		583DF65751B7BBD0A222CAB4 /* byte_stream_cpp_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 01D10113ECC5B446DB35E96D /* byte_stream_cpp_test.cc */; };
 		58693C153EC597BC25EE9648 /* firebase_auth_credentials_provider_test.mm in Sources */ = {isa = PBXBuildFile; fileRef = F869D85E900E5AF6CD02E2FC /* firebase_auth_credentials_provider_test.mm */; };
 		58B84B550725D9812729C7F7 /* FIRTransactionOptionsTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = CF39ECA1293D21A0A2AB2626 /* FIRTransactionOptionsTests.mm */; };
@@ -998,7 +994,6 @@
 		AF4CD9DB5A7D4516FC54892B /* leveldb_lru_garbage_collector_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = B629525F7A1AAC1AB765C74F /* leveldb_lru_garbage_collector_test.cc */; };
 		AF6D6C47F9A25C65BFDCBBA0 /* field_path_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = B686F2AD2023DDB20028D6BE /* field_path_test.cc */; };
 		AF81B6A91987826426F18647 /* remote_store_spec_test.json in Resources */ = {isa = PBXBuildFile; fileRef = 3B843E4A1F3930A400548890 /* remote_store_spec_test.json */; };
-		AFAC87E03815769ABB11746F /* append_only_list_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 5477CDE922EE71C8000FCC1E /* append_only_list_test.cc */; };
 		AFB0ACCF130713DF6495E110 /* writer_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = BC3C788D290A935C353CEAA1 /* writer_test.cc */; };
 		AFB2455806D7C4100C16713B /* object_value_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 214877F52A705012D6720CA0 /* object_value_test.cc */; };
 		AFE84E7B0C356CD2A113E56E /* status_testing.cc in Sources */ = {isa = PBXBuildFile; fileRef = 3CAA33F964042646FDDAF9F9 /* status_testing.cc */; };
@@ -1007,7 +1002,6 @@
 		B0D10C3451EDFB016A6EAF03 /* writer_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = BC3C788D290A935C353CEAA1 /* writer_test.cc */; };
 		B15D17049414E2F5AE72C9C6 /* memory_local_store_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = F6CA0C5638AB6627CB5B4CF4 /* memory_local_store_test.cc */; };
 		B192F30DECA8C28007F9B1D0 /* array_sorted_map_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 54EB764C202277B30088B8F3 /* array_sorted_map_test.cc */; };
-		B1A4D8A731EC0A0B16CC411A /* append_only_list_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 5477CDE922EE71C8000FCC1E /* append_only_list_test.cc */; };
 		B220E091D8F4E6DE1EA44F57 /* executor_libdispatch_test.mm in Sources */ = {isa = PBXBuildFile; fileRef = B6FB4689208F9B9100554BA2 /* executor_libdispatch_test.mm */; };
 		B235E260EA0DCB7BAC04F69B /* field_path_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = B686F2AD2023DDB20028D6BE /* field_path_test.cc */; };
 		B28ACC69EB1F232AE612E77B /* async_testing.cc in Sources */ = {isa = PBXBuildFile; fileRef = 872C92ABD71B12784A1C5520 /* async_testing.cc */; };
@@ -1522,7 +1516,6 @@
 		54740A521FC913E500713A1A /* autoid_test.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = autoid_test.cc; sourceTree = "<group>"; };
 		54740A531FC913E500713A1A /* secure_random_test.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = secure_random_test.cc; sourceTree = "<group>"; };
 		54764FAE1FAA21B90085E60A /* FSTGoogleTestTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = FSTGoogleTestTests.mm; sourceTree = "<group>"; };
-		5477CDE922EE71C8000FCC1E /* append_only_list_test.cc */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = append_only_list_test.cc; sourceTree = "<group>"; };
 		547E9A4122F9EA7300A275E0 /* document_set_test.cc */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = document_set_test.cc; sourceTree = "<group>"; };
 		548DB928200D59F600E00ABC /* comparison_test.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = comparison_test.cc; sourceTree = "<group>"; };
 		5491BC711FB44593008B3588 /* FSTIntegrationTestCase.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = FSTIntegrationTestCase.mm; sourceTree = "<group>"; };
@@ -2224,7 +2217,6 @@
 		54EB764B202277970088B8F3 /* immutable */ = {
 			isa = PBXGroup;
 			children = (
-				5477CDE922EE71C8000FCC1E /* append_only_list_test.cc */,
 				54EB764C202277B30088B8F3 /* array_sorted_map_test.cc */,
 				549CCA4E20A36DBB00BCEB75 /* sorted_map_test.cc */,
 				549CCA4C20A36DBB00BCEB75 /* sorted_set_test.cc */,
@@ -3639,7 +3631,6 @@
 				C8BA36C8B5E26C173F91E677 /* aggregation_result.pb.cc in Sources */,
 				45939AFF906155EA27D281AB /* annotations.pb.cc in Sources */,
 				FF3405218188DFCE586FB26B /* app_testing.mm in Sources */,
-				57BDB8DBEDEC4C61DB497CB4 /* append_only_list_test.cc in Sources */,
 				B192F30DECA8C28007F9B1D0 /* array_sorted_map_test.cc in Sources */,
 				4F857404731D45F02C5EE4C3 /* async_queue_libdispatch_test.mm in Sources */,
 				83A9CD3B6E791A860CE81FA1 /* async_queue_std_test.cc in Sources */,
@@ -3847,7 +3838,6 @@
 				156429A2993B86A905A42D96 /* aggregation_result.pb.cc in Sources */,
 				1C19D796DB6715368407387A /* annotations.pb.cc in Sources */,
 				6EEA00A737690EF82A3C91C6 /* app_testing.mm in Sources */,
-				AFAC87E03815769ABB11746F /* append_only_list_test.cc in Sources */,
 				1291D9F5300AFACD1FBD262D /* array_sorted_map_test.cc in Sources */,
 				4AD9809C9CE9FA09AC40992F /* async_queue_libdispatch_test.mm in Sources */,
 				38208AC761FF994BA69822BE /* async_queue_std_test.cc in Sources */,
@@ -4071,7 +4061,6 @@
 				0EC3921AE220410F7394729B /* aggregation_result.pb.cc in Sources */,
 				276A563D546698B6AAC20164 /* annotations.pb.cc in Sources */,
 				7B8D7BAC1A075DB773230505 /* app_testing.mm in Sources */,
-				098191405BA24F9A7E4F80C6 /* append_only_list_test.cc in Sources */,
 				DC1C711290E12F8EF3601151 /* array_sorted_map_test.cc in Sources */,
 				9B2CD4CBB1DFE8BC3C81A335 /* async_queue_libdispatch_test.mm in Sources */,
 				342724CA250A65E23CB133AC /* async_queue_std_test.cc in Sources */,
@@ -4295,7 +4284,6 @@
 				DF983A9C1FBF758AF3AF110D /* aggregation_result.pb.cc in Sources */,
 				EA46611779C3EEF12822508C /* annotations.pb.cc in Sources */,
 				8F4F40E9BC7ED588F67734D5 /* app_testing.mm in Sources */,
-				B1A4D8A731EC0A0B16CC411A /* append_only_list_test.cc in Sources */,
 				A6E236CE8B3A47BE32254436 /* array_sorted_map_test.cc in Sources */,
 				1CB8AEFBF3E9565FF9955B50 /* async_queue_libdispatch_test.mm in Sources */,
 				AB2BAB0BD77FF05CC26FCF75 /* async_queue_std_test.cc in Sources */,
@@ -4513,7 +4501,6 @@
 				B81B6F327B5E3FE820DC3FB3 /* aggregation_result.pb.cc in Sources */,
 				618BBEAF20B89AAC00B5BCE7 /* annotations.pb.cc in Sources */,
 				5467FB08203E6A44009C9584 /* app_testing.mm in Sources */,
-				5477CDEA22EE71C8000FCC1E /* append_only_list_test.cc in Sources */,
 				54EB764D202277B30088B8F3 /* array_sorted_map_test.cc in Sources */,
 				B6FB4684208EA0EC00554BA2 /* async_queue_libdispatch_test.mm in Sources */,
 				B6FB4685208EA0F000554BA2 /* async_queue_std_test.cc in Sources */,
@@ -4756,7 +4743,6 @@
 				1A3D8028303B45FCBB21CAD3 /* aggregation_result.pb.cc in Sources */,
 				02EB33CC2590E1484D462912 /* annotations.pb.cc in Sources */,
 				EBFC611B1BF195D0EC710AF4 /* app_testing.mm in Sources */,
-				5477CDEB22EE71C8000FCC1E /* append_only_list_test.cc in Sources */,
 				FCA48FB54FC50BFDFDA672CD /* array_sorted_map_test.cc in Sources */,
 				45A5504D33D39C6F80302450 /* async_queue_libdispatch_test.mm in Sources */,
 				6F914209F46E6552B5A79570 /* async_queue_std_test.cc in Sources */,

+ 2 - 3
Firestore/Source/API/FIRQuery.mm

@@ -81,7 +81,6 @@ using firebase::firestore::core::Filter;
 using firebase::firestore::core::CompositeFilter;
 using firebase::firestore::core::ListenOptions;
 using firebase::firestore::core::OrderBy;
-using firebase::firestore::core::OrderByList;
 using firebase::firestore::core::QueryListener;
 using firebase::firestore::core::ViewSnapshot;
 using firebase::firestore::google_firestore_v1_ArrayValue;
@@ -574,7 +573,7 @@ int32_t SaturatedLimitValue(NSInteger limit) {
   }
   const Document &document = *snapshot.internalDocument;
   const DatabaseId &databaseID = self.firestore.databaseID;
-  const OrderByList &order_bys = self.query.order_bys();
+  const std::vector<OrderBy> &order_bys = self.query.order_bys();
 
   SharedMessage<google_firestore_v1_ArrayValue> components{{}};
   components->values_count = CheckedSize(order_bys.size());
@@ -615,7 +614,7 @@ int32_t SaturatedLimitValue(NSInteger limit) {
 /** Converts a list of field values to an Bound. */
 - (Bound)boundFromFieldValues:(NSArray<id> *)fieldValues isInclusive:(BOOL)isInclusive {
   // Use explicit sort order because it has to match the query the user made
-  const OrderByList &explicitSortOrders = self.query.explicit_order_bys();
+  const std::vector<OrderBy> &explicitSortOrders = self.query.explicit_order_bys();
   if (fieldValues.count > explicitSortOrders.size()) {
     ThrowInvalidArgument("Invalid query. You are trying to start or end a query using more values "
                          "than were specified in the order by.");

+ 3 - 4
Firestore/core/src/bundle/bundle_serializer.cc

@@ -53,7 +53,6 @@ using core::FieldFilter;
 using core::Filter;
 using core::LimitType;
 using core::OrderBy;
-using core::OrderByList;
 using core::Target;
 using model::DeepClone;
 using model::Document;
@@ -242,8 +241,8 @@ Filter DecodeUnaryFilter(JsonReader& reader, const json& filter) {
   return InvalidFilter();
 }
 
-OrderByList DecodeOrderBy(JsonReader& reader, const json& query) {
-  OrderByList result;
+std::vector<OrderBy> DecodeOrderBy(JsonReader& reader, const json& query) {
+  std::vector<OrderBy> result;
   std::vector<json> default_order_by;
   for (const auto& order_by :
        reader.OptionalArray("orderBy", query, default_order_by)) {
@@ -261,7 +260,7 @@ OrderByList DecodeOrderBy(JsonReader& reader, const json& query) {
                               ? Direction::Ascending
                               : Direction::Descending;
 
-    result = result.push_back(OrderBy(std::move(path), direction));
+    result.emplace_back(std::move(path), direction);
   }
 
   return result;

+ 4 - 4
Firestore/core/src/core/bound.cc

@@ -19,7 +19,6 @@
 #include <ostream>
 
 #include "Firestore/core/src/core/order_by.h"
-#include "Firestore/core/src/immutable/append_only_list.h"
 #include "Firestore/core/src/model/document.h"
 #include "Firestore/core/src/model/document_key.h"
 #include "Firestore/core/src/model/value_util.h"
@@ -45,7 +44,7 @@ Bound Bound::FromValue(SharedMessage<google_firestore_v1_ArrayValue> position,
   return Bound(std::move(position), inclusive);
 }
 
-bool Bound::SortsBeforeDocument(const OrderByList& order_by,
+bool Bound::SortsBeforeDocument(const std::vector<OrderBy>& order_by,
                                 const model::Document& document) const {
   auto comparison = CompareToDocument(order_by, document);
   return inclusive_ ? (comparison == ComparisonResult::Ascending ||
@@ -53,7 +52,7 @@ bool Bound::SortsBeforeDocument(const OrderByList& order_by,
                     : (comparison == ComparisonResult::Ascending);
 }
 
-bool Bound::SortsAfterDocument(const OrderByList& order_by,
+bool Bound::SortsAfterDocument(const std::vector<OrderBy>& order_by,
                                const model::Document& document) const {
   auto comparison = CompareToDocument(order_by, document);
   return inclusive_ ? (comparison == ComparisonResult::Descending ||
@@ -62,7 +61,8 @@ bool Bound::SortsAfterDocument(const OrderByList& order_by,
 }
 
 ComparisonResult Bound::CompareToDocument(
-    const OrderByList& order_by, const model::Document& document) const {
+    const std::vector<OrderBy>& order_by,
+    const model::Document& document) const {
   HARD_ASSERT(position_->values_count <= order_by.size(),
               "Bound has more components than the provided order by.");
 

+ 5 - 3
Firestore/core/src/core/bound.h

@@ -21,6 +21,7 @@
 #include <memory>
 #include <string>
 #include <utility>
+#include <vector>
 
 #include "Firestore/Protos/nanopb/google/firestore/v1/document.nanopb.h"
 #include "Firestore/core/src/core/core_fwd.h"
@@ -75,14 +76,14 @@ class Bound {
    * Returns true if the given document comes before this bound using the
    * provided sort order.
    */
-  bool SortsBeforeDocument(const OrderByList& order_by,
+  bool SortsBeforeDocument(const std::vector<OrderBy>& order_by,
                            const model::Document& document) const;
 
   /**
    * Returns true if the given document comes after this bound using the
    * provided sort order.
    */
-  bool SortsAfterDocument(const OrderByList& order_by,
+  bool SortsAfterDocument(const std::vector<OrderBy>& order_by,
                           const model::Document& document) const;
 
   std::string PositionString() const;
@@ -98,7 +99,8 @@ class Bound {
   }
 
   util::ComparisonResult CompareToDocument(
-      const OrderByList& order_by, const model::Document& document) const;
+      const std::vector<OrderBy>& order_by,
+      const model::Document& document) const;
 
   nanopb::SharedMessage<google_firestore_v1_ArrayValue> position_;
   bool inclusive_;

+ 0 - 2
Firestore/core/src/core/core_fwd.h

@@ -72,8 +72,6 @@ class EventListener;
 
 using CollectionGroupId = std::shared_ptr<const std::string>;
 
-using OrderByList = immutable::AppendOnlyList<OrderBy>;
-
 using TransactionResultCallback = util::StatusCallback;
 
 using TransactionUpdateCallback = std::function<void(

+ 0 - 3
Firestore/core/src/core/order_by.h

@@ -89,9 +89,6 @@ class OrderBy {
   Direction direction_;
 };
 
-/** A list of OrderBys, as used in Queries and elsewhere. */
-using OrderByList = immutable::AppendOnlyList<OrderBy>;
-
 std::ostream& operator<<(std::ostream& os, const OrderBy& order);
 
 bool operator==(const OrderBy& lhs, const OrderBy& rhs);

+ 16 - 17
Firestore/core/src/core/query.cc

@@ -89,7 +89,7 @@ absl::optional<Operator> Query::FindOpInsideFilters(
   return absl::nullopt;
 }
 
-const OrderByList& Query::order_bys() const {
+const std::vector<OrderBy>& Query::order_bys() const {
   if (memoized_order_bys_.empty()) {
     const FieldPath* inequality_field = InequalityFilterField();
     const FieldPath* first_order_by_field = FirstOrderByField();
@@ -114,7 +114,7 @@ const OrderByList& Query::order_bys() const {
           first_order_by_field->CanonicalString(),
           inequality_field->CanonicalString());
 
-      OrderByList result = explicit_order_bys_;
+      std::vector<OrderBy> result = explicit_order_bys_;
 
       bool found_explicit_key_order = false;
       for (const OrderBy& order_by : explicit_order_bys_) {
@@ -130,7 +130,7 @@ const OrderByList& Query::order_bys() const {
         Direction last_direction = explicit_order_bys_.empty()
                                        ? Direction::Ascending
                                        : explicit_order_bys_.back().direction();
-        result = result.emplace_back(FieldPath::KeyFieldPath(), last_direction);
+        result.emplace_back(FieldPath::KeyFieldPath(), last_direction);
       }
 
       memoized_order_bys_ = std::move(result);
@@ -194,10 +194,11 @@ Query Query::AddingOrderBy(OrderBy order_by) const {
                 "First OrderBy must match inequality field.");
   }
 
-  return {path_,     collection_group_,
-          filters_,  explicit_order_bys_.push_back(std::move(order_by)),
-          limit_,    limit_type_,
-          start_at_, end_at_};
+  std::vector<OrderBy> order_bys_copy(explicit_order_bys_);
+  order_bys_copy.push_back(std::move(order_by));
+
+  return {path_,  collection_group_, filters_,  std::move(order_bys_copy),
+          limit_, limit_type_,       start_at_, end_at_};
 }
 
 Query Query::WithLimitToFirst(int32_t limit) const {
@@ -251,10 +252,9 @@ bool Query::MatchesPathAndCollectionGroup(const Document& doc) const {
 }
 
 bool Query::MatchesFilters(const Document& doc) const {
-  for (const auto& filter : filters_) {
-    if (!filter.Matches(doc)) return false;
-  }
-  return true;
+  return std::all_of(
+      filters_.cbegin(), filters_.cend(),
+      [&doc](const Filter& filter) { return filter.Matches(doc); });
 }
 
 bool Query::MatchesOrderBy(const Document& doc) const {
@@ -277,18 +277,17 @@ bool Query::MatchesOrderBy(const Document& doc) const {
 }
 
 bool Query::MatchesBounds(const Document& doc) const {
-  const OrderByList& ordering = order_bys();
-  if (start_at_ && !start_at_->SortsBeforeDocument(ordering, doc)) {
+  if (start_at_ && !start_at_->SortsBeforeDocument(order_bys(), doc)) {
     return false;
   }
-  if (end_at_ && !end_at_->SortsAfterDocument(ordering, doc)) {
+  if (end_at_ && !end_at_->SortsAfterDocument(order_bys(), doc)) {
     return false;
   }
   return true;
 }
 
 model::DocumentComparator Query::Comparator() const {
-  OrderByList ordering = order_bys();
+  std::vector<OrderBy> ordering = order_bys();
 
   bool has_key_ordering = false;
   for (const OrderBy& order_by : ordering) {
@@ -332,12 +331,12 @@ const Target& Query::ToTarget() const& {
   if (memoized_target == nullptr) {
     if (limit_type_ == LimitType::Last) {
       // Flip the orderBy directions since we want the last results
-      OrderByList new_order_bys;
+      std::vector<OrderBy> new_order_bys;
       for (const auto& order_by : order_bys()) {
         Direction dir = order_by.direction() == Direction::Descending
                             ? Direction::Ascending
                             : Direction::Descending;
-        new_order_bys = new_order_bys.push_back(OrderBy(order_by.field(), dir));
+        new_order_bys.emplace_back(order_by.field(), dir);
       }
 
       // We need to swap the cursors to match the now-flipped query ordering.

+ 5 - 6
Firestore/core/src/core/query.h

@@ -28,7 +28,6 @@
 #include "Firestore/core/src/core/filter.h"
 #include "Firestore/core/src/core/order_by.h"
 #include "Firestore/core/src/core/target.h"
-#include "Firestore/core/src/immutable/append_only_list.h"
 #include "Firestore/core/src/model/model_fwd.h"
 #include "Firestore/core/src/model/resource_path.h"
 
@@ -64,7 +63,7 @@ class Query {
   Query(model::ResourcePath path,
         CollectionGroupId collection_group,
         std::vector<Filter> filters,
-        OrderByList explicit_order_bys,
+        std::vector<OrderBy> explicit_order_bys,
         int32_t limit,
         LimitType limit_type,
         absl::optional<Bound> start_at,
@@ -132,7 +131,7 @@ class Query {
    * Note that the actual query performed might add additional sort orders to
    * match the behavior of the backend.
    */
-  const OrderByList& explicit_order_bys() const {
+  const std::vector<OrderBy>& explicit_order_bys() const {
     return explicit_order_bys_;
   }
 
@@ -142,7 +141,7 @@ class Query {
    * This might include additional sort orders added implicitly to match the
    * backend behavior.
    */
-  const OrderByList& order_bys() const;
+  const std::vector<OrderBy>& order_bys() const;
 
   /** Returns the first field in an order-by constraint, or nullptr if none. */
   const model::FieldPath* FirstOrderByField() const;
@@ -268,10 +267,10 @@ class Query {
 
   // A list of fields given to sort by. This does not include the implicit key
   // sort at the end.
-  OrderByList explicit_order_bys_;
+  std::vector<OrderBy> explicit_order_bys_;
 
   // The memoized list of sort orders.
-  mutable OrderByList memoized_order_bys_;
+  mutable std::vector<OrderBy> memoized_order_bys_;
 
   int32_t limit_ = Target::kNoLimit;
   LimitType limit_type_ = LimitType::None;

+ 3 - 4
Firestore/core/src/core/target.h

@@ -28,7 +28,6 @@
 #include "Firestore/core/src/core/field_filter.h"
 #include "Firestore/core/src/core/filter.h"
 #include "Firestore/core/src/core/order_by.h"
-#include "Firestore/core/src/immutable/append_only_list.h"
 #include "Firestore/core/src/model/field_index.h"
 #include "Firestore/core/src/model/resource_path.h"
 #include "Firestore/core/src/remote/serializer.h"
@@ -91,7 +90,7 @@ class Target {
   }
 
   /** Returns the list of ordering constraints by the target. */
-  const OrderByList& order_bys() const {
+  const std::vector<OrderBy>& order_bys() const {
     return order_bys_;
   }
 
@@ -179,7 +178,7 @@ class Target {
   Target(model::ResourcePath path,
          CollectionGroupId collection_group,
          std::vector<Filter> filters,
-         OrderByList order_bys,
+         std::vector<OrderBy> order_bys,
          int32_t limit,
          absl::optional<Bound> start_at,
          absl::optional<Bound> end_at)
@@ -222,7 +221,7 @@ class Target {
   model::ResourcePath path_;
   std::shared_ptr<const std::string> collection_group_;
   std::vector<Filter> filters_;
-  OrderByList order_bys_;
+  std::vector<OrderBy> order_bys_;
   int32_t limit_ = kNoLimit;
   absl::optional<Bound> start_at_;
   absl::optional<Bound> end_at_;

+ 0 - 253
Firestore/core/src/immutable/append_only_list.h

@@ -1,253 +0,0 @@
-/*
- * Copyright 2019 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_IMMUTABLE_APPEND_ONLY_LIST_H_
-#define FIRESTORE_CORE_SRC_IMMUTABLE_APPEND_ONLY_LIST_H_
-
-#include <algorithm>
-#include <iterator>
-#include <memory>
-#include <utility>
-#include <vector>
-
-#include "absl/algorithm/container.h"
-#include "absl/base/attributes.h"
-
-namespace firebase {
-namespace firestore {
-namespace immutable {
-
-/**
- * An immutable list, optimized for appending.
- *
- * Each `push_back` creates a new instance and does not modify any that come
- * before. If `push_back` is called on the last such instance, it will share
- * the backing vector with the prior instance (though the prior instance will
- * not perceive any change).
- *
- * This "chaining" behavior is what makes AppendOnlyList efficient, but it only
- * applies when applied to the last link in the chain. When applied any instance
- * that is not at the end, most operations will copy instead of chaining.
- *
- * Iterators over an AppendOnlyList are never invalidated.
- */
-template <typename T>
-class AppendOnlyList {
- public:
-  using iterator = const T*;
-  using const_iterator = const T*;
-  using value_type = T;
-
-  AppendOnlyList() = default;
-
-  AppendOnlyList(std::initializer_list<T> initializer_list)
-      : contents_(std::make_shared<std::vector<T>>(initializer_list)),
-        size_(initializer_list.size()) {
-  }
-
-  /**
-   * Returns a new AppendOnlyList that has reserved the given capacity in its
-   * backing vector, without actually lengthening the chain.
-   *
-   * This has a similar effect to std::vector::reserve, except that *this is
-   * not actually modified. Successive `push_back` operations until `size()`
-   * is equal to `capacity` are guaranteed to be O(1).
-   *
-   * Note that if this instance is not the end of the chain, then this forces
-   * a copy.
-   */
-  ABSL_MUST_USE_RESULT AppendOnlyList reserve(size_t capacity) const {
-    if (capacity <= size_) {
-      return *this;
-    }
-
-    // Create a the underlying vector with capacity reserved, but return the
-    // result with the current size. Reserving does not actually append anything
-    // to the underlying vector so size() shouldn't change.
-    std::shared_ptr<std::vector<T>> new_contents = PrepareForAppend(capacity);
-    return AppendOnlyList(std::move(new_contents), size_);
-  }
-
-  /**
-   * Creates a new AppendOnlyList with the given value appended to the end.
-   *
-   * Each `push_back` creates a new instance and appears not to modify any that
-   * come. If `push_back` is called on the last instance in a chain, it will
-   * share the backing vector with the prior instance.
-   *
-   * If `push_back` is called when this instance isn't the last instance in the
-   * chain, it will make a copy of all preceding elements in the chain and
-   * return a new chain suitable for further chained `push_back` operations.
-   */
-  ABSL_MUST_USE_RESULT AppendOnlyList push_back(const T& value) const {
-    size_t new_size = size_ + 1;
-    std::shared_ptr<std::vector<T>> new_contents = PrepareForAppend(new_size);
-
-    new_contents->push_back(value);
-    return AppendOnlyList(std::move(new_contents), new_size);
-  }
-
-  /**
-   * Creates a new AppendOnlyList with the given value appended to the end.
-   *
-   * @see `push_back(const T&)` for detailed discussion.
-   */
-  ABSL_MUST_USE_RESULT AppendOnlyList push_back(T&& value) const {
-    size_t new_size = size_ + 1;
-    std::shared_ptr<std::vector<T>> new_contents = PrepareForAppend(new_size);
-
-    new_contents->push_back(std::move(value));
-    return AppendOnlyList(std::move(new_contents), new_size);
-  }
-
-  /**
-   * Creates a new AppendOnlyList constructing a new value appended to the end.
-   *
-   * @see `push_back(const T&)` for detailed discussion.
-   */
-  template <typename... Args>
-  ABSL_MUST_USE_RESULT AppendOnlyList emplace_back(Args&&... args) const {
-    size_t new_size = size_ + 1;
-    std::shared_ptr<std::vector<T>> new_contents = PrepareForAppend(new_size);
-
-    new_contents->emplace_back(std::forward<Args>(args)...);
-    return AppendOnlyList(std::move(new_contents), new_size);
-  }
-
-  /**
-   * Creates a new AppendOnlyList with the final link in the chain removed.
-   *
-   * Note that the element isn't actually removed from the backing vector and
-   * it still constitutes the end of the chain. This means that any `push_back`
-   * on the resulting AppendOnlyList will result in a full copy.
-   *
-   * Calling pop_back() on an empty AppendOnlyList returns an empty
-   * AppendOnlyList.
-   */
-  ABSL_MUST_USE_RESULT AppendOnlyList pop_back() const {
-    if (size_ <= 1) {
-      return AppendOnlyList(nullptr, 0);
-    }
-
-    return AppendOnlyList(contents_, size_ - 1);
-  }
-
-  size_t size() const {
-    return size_;
-  }
-
-  size_t capacity() const {
-    return contents_ ? contents_->capacity() : 0;
-  }
-
-  bool empty() const {
-    return size_ == 0;
-  }
-
-  /**
-   * Returns an iterator to the beginning of the list. Iterators are never
-   * invalidated (so long as the container itself is valid).
-   */
-  const_iterator begin() const {
-    if (size_ == 0) {
-      return nullptr;
-    } else {
-      return contents_->data();
-    }
-  }
-
-  /**
-   * Returns an iterator that points to one past the end of the list. Iterators
-   * are never invalidated (so long as the container itself is valid).
-   */
-  const_iterator end() const {
-    if (size_ == 0) {
-      return nullptr;
-    } else {
-      return contents_->data() + size_;
-    }
-  }
-
-  /**
-   * Returns the first element of the list. Only valid when the list is not
-   * empty.
-   */
-  const T& front() const {
-    return *begin();
-  }
-
-  /**
-   * Returns the last element of the list. Only valid when the list is not
-   * empty.
-   */
-  const T& back() const {
-    return *(end() - 1);
-  }
-
-  const T& operator[](size_t pos) const {
-    return (*contents_)[pos];
-  }
-
-  friend bool operator==(const AppendOnlyList& lhs, const AppendOnlyList& rhs) {
-    return absl::c_equal(lhs, rhs);
-  }
-
-  friend bool operator!=(const AppendOnlyList& lhs, const AppendOnlyList& rhs) {
-    return !(lhs == rhs);
-  }
-
- private:
-  AppendOnlyList(std::shared_ptr<std::vector<T>> contents, size_t size)
-      : contents_(std::move(contents)), size_(size) {
-  }
-
-  std::shared_ptr<std::vector<T>> PrepareForAppend(size_t new_size) const {
-    if (contents_ && size_ == contents_->size() &&
-        new_size <= contents_->capacity()) {
-      // If there's an existing vector, this instance points to the end, and
-      // can already accommodate what's required, there's nothing to do.
-      return contents_;
-    }
-
-    size_t min_capacity = new_size;
-    if (contents_) {
-      // if contents_->capacity() * 2 overflows, min_capacity will be larger.
-      min_capacity = std::max(min_capacity, contents_->capacity() * 2);
-    }
-
-    // min_capacity will be larger than the existing contents of this list so
-    // reserve that capacity copying in the current values. Copying from this
-    // and then reserving would cause two allocations, the first for exactly
-    // the current size and then another for min_capacity.
-    auto new_contents = std::make_shared<std::vector<T>>();
-    new_contents->reserve(min_capacity);
-    new_contents->insert(new_contents->begin(), begin(), end());
-    return new_contents;
-  }
-
-  // A shared vector. Sequential push_back operations will share the vector. May
-  // be nullptr when size_ == 0, but is not required to be null.
-  std::shared_ptr<std::vector<T>> contents_;
-
-  // size_ is not shared.
-  size_t size_ = 0;
-};
-
-}  // namespace immutable
-}  // namespace firestore
-}  // namespace firebase
-
-#endif  // FIRESTORE_CORE_SRC_IMMUTABLE_APPEND_ONLY_LIST_H_

+ 1 - 1
Firestore/core/src/model/target_index_matcher.h

@@ -93,7 +93,7 @@ class TargetIndexMatcher {
 
   absl::optional<core::FieldFilter> inequality_filter_;
   std::vector<core::FieldFilter> equality_filters_;
-  core::OrderByList order_bys_;
+  std::vector<core::OrderBy> order_bys_;
 };
 
 }  // namespace model

+ 6 - 7
Firestore/core/src/remote/serializer.cc

@@ -67,7 +67,6 @@ using core::Direction;
 using core::FieldFilter;
 using core::Filter;
 using core::OrderBy;
-using core::OrderByList;
 using core::Query;
 using core::Target;
 using local::QueryPurpose;
@@ -761,7 +760,7 @@ Target Serializer::DecodeStructuredQuery(
     filter_by = DecodeFilters(context, query.where);
   }
 
-  OrderByList order_by;
+  std::vector<OrderBy> order_by;
   if (query.order_by_count > 0) {
     order_by = DecodeOrderBys(context, query.order_by, query.order_by_count);
   }
@@ -1095,7 +1094,7 @@ CompositeFilter::Operator Serializer::DecodeCompositeFilterOperator(
 }
 
 google_firestore_v1_StructuredQuery_Order* Serializer::EncodeOrderBys(
-    const OrderByList& orders) const {
+    const std::vector<OrderBy>& orders) const {
   auto* result = MakeArray<google_firestore_v1_StructuredQuery_Order>(
       CheckedSize(orders.size()));
 
@@ -1115,15 +1114,15 @@ google_firestore_v1_StructuredQuery_Order* Serializer::EncodeOrderBys(
   return result;
 }
 
-OrderByList Serializer::DecodeOrderBys(
+std::vector<OrderBy> Serializer::DecodeOrderBys(
     ReadContext* context,
     google_firestore_v1_StructuredQuery_Order* order_bys,
     pb_size_t size) const {
-  OrderByList result;
-  result = result.reserve(size);
+  std::vector<OrderBy> result;
+  result.reserve(size);
 
   for (pb_size_t i = 0; i != size; ++i) {
-    result = result.push_back(DecodeOrderBy(context, order_bys[i]));
+    result.push_back(DecodeOrderBy(context, order_bys[i]));
   }
 
   return result;

+ 3 - 2
Firestore/core/src/remote/serializer.h

@@ -32,6 +32,7 @@
 #include "Firestore/core/src/core/core_fwd.h"
 #include "Firestore/core/src/core/field_filter.h"
 #include "Firestore/core/src/core/filter.h"
+#include "Firestore/core/src/core/order_by.h"
 #include "Firestore/core/src/model/database_id.h"
 #include "Firestore/core/src/model/model_fwd.h"
 #include "Firestore/core/src/model/resource_path.h"
@@ -305,8 +306,8 @@ class Serializer {
       google_firestore_v1_StructuredQuery_CompositeFilter_Operator op) const;
 
   google_firestore_v1_StructuredQuery_Order* EncodeOrderBys(
-      const core::OrderByList& orders) const;
-  core::OrderByList DecodeOrderBys(
+      const std::vector<core::OrderBy>& orders) const;
+  std::vector<core::OrderBy> DecodeOrderBys(
       util::ReadContext* context,
       google_firestore_v1_StructuredQuery_Order* order_bys,
       pb_size_t size) const;

+ 81 - 68
Firestore/core/test/unit/core/query_test.cc

@@ -19,8 +19,8 @@
 #include <cmath>
 
 #include "Firestore/core/src/core/bound.h"
-#include "Firestore/core/src/core/field_filter.h"
 #include "Firestore/core/src/core/filter.h"
+#include "Firestore/core/src/core/order_by.h"
 #include "Firestore/core/src/model/document_set.h"
 #include "Firestore/core/src/model/field_path.h"
 #include "Firestore/core/src/model/mutable_document.h"
@@ -50,7 +50,6 @@ using testutil::DbId;
 using testutil::Doc;
 using testutil::Field;
 using testutil::Map;
-using testutil::OrderBy;
 using testutil::OrFilters;
 using testutil::Ref;
 using testutil::Value;
@@ -75,9 +74,9 @@ TEST(QueryTest, Constructor) {
 }
 
 TEST(QueryTest, OrderBy) {
-  auto query =
-      testutil::Query("rooms/Firestore/messages")
-          .AddingOrderBy(OrderBy(Field("length"), Direction::Descending));
+  auto query = testutil::Query("rooms/Firestore/messages")
+                   .AddingOrderBy(testutil::OrderBy(Field("length"),
+                                                    Direction::Descending));
 
   ASSERT_EQ(2, query.order_bys().size());
   EXPECT_EQ("length", query.order_bys()[0].field().CanonicalString());
@@ -480,8 +479,8 @@ TEST(QueryTest, DoesNotMatchComplexObjectsForFilters) {
 }
 
 TEST(QueryTest, DoesntRemoveComplexObjectsWithOrderBy) {
-  auto query1 =
-      testutil::Query("collection").AddingOrderBy(OrderBy("sort", "asc"));
+  auto query1 = testutil::Query("collection")
+                    .AddingOrderBy(testutil::OrderBy("sort", "asc"));
 
   auto doc1 = Doc("collection/1", 0, Map("sort", 2));
   auto doc2 = Doc("collection/2", 0, Map("sort", Array()));
@@ -569,7 +568,8 @@ testing::AssertionResult CorrectComparisons(
 }
 
 TEST(QueryTest, SortsDocumentsInTheCorrectOrder) {
-  auto query = testutil::Query("collection").AddingOrderBy(OrderBy("sort"));
+  auto query =
+      testutil::Query("collection").AddingOrderBy(testutil::OrderBy("sort"));
 
   // clang-format off
   std::vector<MutableDocument> docs = {
@@ -595,8 +595,8 @@ TEST(QueryTest, SortsDocumentsInTheCorrectOrder) {
 
 TEST(QueryTest, SortsDocumentsUsingMultipleFields) {
   auto query = testutil::Query("collection")
-                   .AddingOrderBy(OrderBy("sort1"))
-                   .AddingOrderBy(OrderBy("sort2"));
+                   .AddingOrderBy(testutil::OrderBy("sort1"))
+                   .AddingOrderBy(testutil::OrderBy("sort2"));
 
   // clang-format off
   std::vector<MutableDocument> docs = {
@@ -618,8 +618,8 @@ TEST(QueryTest, SortsDocumentsUsingMultipleFields) {
 
 TEST(QueryTest, SortsDocumentsWithDescendingToo) {
   auto query = testutil::Query("collection")
-                   .AddingOrderBy(OrderBy("sort1", "desc"))
-                   .AddingOrderBy(OrderBy("sort2", "desc"));
+                   .AddingOrderBy(testutil::OrderBy("sort1", "desc"))
+                   .AddingOrderBy(testutil::OrderBy("sort2", "desc"));
 
   // clang-format off
   std::vector<MutableDocument> docs = {
@@ -654,24 +654,24 @@ TEST(QueryTest, Equality) {
   auto q32 = testutil::Query("foo/bar");
 
   auto q41 = testutil::Query("foo")
-                 .AddingOrderBy(OrderBy("foo", "asc"))
-                 .AddingOrderBy(OrderBy("bar", "asc"));
+                 .AddingOrderBy(testutil::OrderBy("foo", "asc"))
+                 .AddingOrderBy(testutil::OrderBy("bar", "asc"));
   auto q42 = testutil::Query("foo")
-                 .AddingOrderBy(OrderBy("foo", "asc"))
-                 .AddingOrderBy(OrderBy("bar", "asc"));
+                 .AddingOrderBy(testutil::OrderBy("foo", "asc"))
+                 .AddingOrderBy(testutil::OrderBy("bar", "asc"));
   auto q43Diff = testutil::Query("foo")
-                     .AddingOrderBy(OrderBy("bar", "asc"))
-                     .AddingOrderBy(OrderBy("foo", "asc"));
+                     .AddingOrderBy(testutil::OrderBy("bar", "asc"))
+                     .AddingOrderBy(testutil::OrderBy("foo", "asc"));
 
   auto q51 = testutil::Query("foo")
-                 .AddingOrderBy(OrderBy("foo", "asc"))
+                 .AddingOrderBy(testutil::OrderBy("foo", "asc"))
                  .AddingFilter(testutil::Filter("foo", ">", 2));
   auto q52 = testutil::Query("foo")
                  .AddingFilter(testutil::Filter("foo", ">", 2))
-                 .AddingOrderBy(OrderBy("foo", "asc"));
+                 .AddingOrderBy(testutil::OrderBy("foo", "asc"));
   auto q53Diff = testutil::Query("foo")
                      .AddingFilter(testutil::Filter("bar", ">", 2))
-                     .AddingOrderBy(OrderBy("bar", "asc"));
+                     .AddingOrderBy(testutil::OrderBy("bar", "asc"));
 
   auto q61 = testutil::Query("foo").WithLimitToFirst(10);
 
@@ -718,24 +718,24 @@ TEST(QueryTest, UniqueIds) {
   auto q32 = testutil::Query("foo/bar");
 
   auto q41 = testutil::Query("foo")
-                 .AddingOrderBy(OrderBy("foo", "asc"))
-                 .AddingOrderBy(OrderBy("bar", "asc"));
+                 .AddingOrderBy(testutil::OrderBy("foo", "asc"))
+                 .AddingOrderBy(testutil::OrderBy("bar", "asc"));
   auto q42 = testutil::Query("foo")
-                 .AddingOrderBy(OrderBy("foo", "asc"))
-                 .AddingOrderBy(OrderBy("bar", "asc"));
+                 .AddingOrderBy(testutil::OrderBy("foo", "asc"))
+                 .AddingOrderBy(testutil::OrderBy("bar", "asc"));
   auto q43Diff = testutil::Query("foo")
-                     .AddingOrderBy(OrderBy("bar", "asc"))
-                     .AddingOrderBy(OrderBy("foo", "asc"));
+                     .AddingOrderBy(testutil::OrderBy("bar", "asc"))
+                     .AddingOrderBy(testutil::OrderBy("foo", "asc"));
 
   auto q51 = testutil::Query("foo")
-                 .AddingOrderBy(OrderBy("foo", "asc"))
+                 .AddingOrderBy(testutil::OrderBy("foo", "asc"))
                  .AddingFilter(testutil::Filter("foo", ">", 2));
   auto q52 = testutil::Query("foo")
                  .AddingFilter(testutil::Filter("foo", ">", 2))
-                 .AddingOrderBy(OrderBy("foo", "asc"));
+                 .AddingOrderBy(testutil::OrderBy("foo", "asc"));
   auto q53Diff = testutil::Query("foo")
                      .AddingFilter(testutil::Filter("bar", ">", 2))
-                     .AddingOrderBy(OrderBy("bar", "asc"));
+                     .AddingOrderBy(testutil::OrderBy("bar", "asc"));
 
   auto q61 = testutil::Query("foo").WithLimitToFirst(10);
 
@@ -771,55 +771,67 @@ TEST(QueryTest, ImplicitOrderBy) {
   auto base_query = testutil::Query("foo");
   // Default is ascending
   ASSERT_EQ(base_query.order_bys(),
-            OrderByList{OrderBy(FieldPath::kDocumentKeyPath, "asc")});
+            std::vector<core::OrderBy>{
+                testutil::OrderBy(FieldPath::kDocumentKeyPath, "asc")});
 
   // Explicit key ordering is respected
   ASSERT_EQ(
-      base_query.AddingOrderBy(OrderBy(FieldPath::kDocumentKeyPath, "asc"))
+      base_query
+          .AddingOrderBy(testutil::OrderBy(FieldPath::kDocumentKeyPath, "asc"))
           .order_bys(),
-      OrderByList{OrderBy(FieldPath::kDocumentKeyPath, "asc")});
+      std::vector<OrderBy>{
+          testutil::OrderBy(FieldPath::kDocumentKeyPath, "asc")});
   ASSERT_EQ(
-      base_query.AddingOrderBy(OrderBy(FieldPath::kDocumentKeyPath, "desc"))
+      base_query
+          .AddingOrderBy(testutil::OrderBy(FieldPath::kDocumentKeyPath, "desc"))
           .order_bys(),
-      OrderByList{OrderBy(FieldPath::kDocumentKeyPath, "desc")});
+      std::vector<OrderBy>{
+          testutil::OrderBy(FieldPath::kDocumentKeyPath, "desc")});
 
-  ASSERT_EQ(base_query.AddingOrderBy(OrderBy("foo", "asc"))
-                .AddingOrderBy(OrderBy(FieldPath::kDocumentKeyPath, "asc"))
-                .order_bys(),
-            (OrderByList{OrderBy("foo", "asc"),
-                         OrderBy(FieldPath::kDocumentKeyPath, "asc")}));
+  ASSERT_EQ(
+      base_query.AddingOrderBy(testutil::OrderBy("foo", "asc"))
+          .AddingOrderBy(testutil::OrderBy(FieldPath::kDocumentKeyPath, "asc"))
+          .order_bys(),
+      (std::vector<OrderBy>{
+          testutil::OrderBy("foo", "asc"),
+          testutil::OrderBy(FieldPath::kDocumentKeyPath, "asc")}));
 
-  ASSERT_EQ(base_query.AddingOrderBy(OrderBy("foo", "asc"))
-                .AddingOrderBy(OrderBy(FieldPath::kDocumentKeyPath, "desc"))
-                .order_bys(),
-            (OrderByList{OrderBy("foo", "asc"),
-                         OrderBy(FieldPath::kDocumentKeyPath, "desc")}));
+  ASSERT_EQ(
+      base_query.AddingOrderBy(testutil::OrderBy("foo", "asc"))
+          .AddingOrderBy(testutil::OrderBy(FieldPath::kDocumentKeyPath, "desc"))
+          .order_bys(),
+      (std::vector<OrderBy>{
+          testutil::OrderBy("foo", "asc"),
+          testutil::OrderBy(FieldPath::kDocumentKeyPath, "desc")}));
 
   // Inequality filters add order bys
   ASSERT_EQ(
       base_query.AddingFilter(testutil::Filter("foo", "<", 5)).order_bys(),
-      (OrderByList{OrderBy("foo", "asc"),
-                   OrderBy(FieldPath::kDocumentKeyPath, "asc")}));
+      (std::vector<OrderBy>{
+          testutil::OrderBy("foo", "asc"),
+          testutil::OrderBy(FieldPath::kDocumentKeyPath, "asc")}));
 
   // Descending order by applies to implicit key ordering
-  ASSERT_EQ(base_query.AddingOrderBy(OrderBy("foo", "desc")).order_bys(),
-            (OrderByList{OrderBy("foo", "desc"),
-                         OrderBy(FieldPath::kDocumentKeyPath, "desc")}));
-  ASSERT_EQ(base_query.AddingOrderBy(OrderBy("foo", "asc"))
-                .AddingOrderBy(OrderBy("bar", "desc"))
+  ASSERT_EQ(
+      base_query.AddingOrderBy(testutil::OrderBy("foo", "desc")).order_bys(),
+      (std::vector<OrderBy>{
+          testutil::OrderBy("foo", "desc"),
+          testutil::OrderBy(FieldPath::kDocumentKeyPath, "desc")}));
+  ASSERT_EQ(base_query.AddingOrderBy(testutil::OrderBy("foo", "asc"))
+                .AddingOrderBy(testutil::OrderBy("bar", "desc"))
                 .order_bys(),
-            (OrderByList{
-                OrderBy("foo", "asc"),
-                OrderBy("bar", "desc"),
-                OrderBy(FieldPath::kDocumentKeyPath, "desc"),
+            (std::vector<OrderBy>{
+                testutil::OrderBy("foo", "asc"),
+                testutil::OrderBy("bar", "desc"),
+                testutil::OrderBy(FieldPath::kDocumentKeyPath, "desc"),
             }));
-  ASSERT_EQ(base_query.AddingOrderBy(OrderBy("foo", "desc"))
-                .AddingOrderBy(OrderBy("bar", "asc"))
+  ASSERT_EQ(base_query.AddingOrderBy(testutil::OrderBy("foo", "desc"))
+                .AddingOrderBy(testutil::OrderBy("bar", "asc"))
                 .order_bys(),
-            (OrderByList{
-                OrderBy("foo", "desc"),
-                OrderBy("bar", "asc"),
-                OrderBy(FieldPath::kDocumentKeyPath, "asc"),
+            (std::vector<OrderBy>{
+                testutil::OrderBy("foo", "desc"),
+                testutil::OrderBy("bar", "asc"),
+                testutil::OrderBy(FieldPath::kDocumentKeyPath, "asc"),
             }));
 }
 
@@ -859,11 +871,12 @@ TEST(QueryTest, CanonicalIDs) {
   EXPECT_THAT(filters,
               HasCanonicalId("coll|f:anot-in[1,2,3]|ob:aasc__name__asc"));
 
-  auto order_bys = testutil::Query("coll").AddingOrderBy(OrderBy("up", "asc"));
+  auto order_bys =
+      testutil::Query("coll").AddingOrderBy(testutil::OrderBy("up", "asc"));
   EXPECT_THAT(order_bys, HasCanonicalId("coll|f:|ob:upasc__name__asc"));
 
   // __name__'s order matches the trailing component
-  order_bys = order_bys.AddingOrderBy(OrderBy("down", "desc"));
+  order_bys = order_bys.AddingOrderBy(testutil::OrderBy("down", "desc"));
   EXPECT_THAT(order_bys,
               HasCanonicalId("coll|f:|ob:upascdowndesc__name__desc"));
 
@@ -871,8 +884,8 @@ TEST(QueryTest, CanonicalIDs) {
   EXPECT_THAT(limit, HasCanonicalId("coll|f:|ob:__name__asc|l:25|lt:f"));
 
   auto bounds = testutil::Query("airports")
-                    .AddingOrderBy(OrderBy("name", "asc"))
-                    .AddingOrderBy(OrderBy("score", "desc"))
+                    .AddingOrderBy(testutil::OrderBy("name", "asc"))
+                    .AddingOrderBy(testutil::OrderBy("score", "desc"))
                     .StartingAt(Bound::FromValue(Array("OAK", 1000),
                                                  /* inclusive= */ true))
                     .EndingAt(Bound::FromValue(Array("SFO", 2000),
@@ -885,10 +898,10 @@ TEST(QueryTest, MatchesAllDocuments) {
   auto base_query = testutil::Query("coll");
   EXPECT_TRUE(base_query.MatchesAllDocuments());
 
-  auto query = base_query.AddingOrderBy(OrderBy("__name__"));
+  auto query = base_query.AddingOrderBy(testutil::OrderBy("__name__"));
   EXPECT_TRUE(query.MatchesAllDocuments());
 
-  query = base_query.AddingOrderBy(OrderBy("foo"));
+  query = base_query.AddingOrderBy(testutil::OrderBy("foo"));
   EXPECT_FALSE(query.MatchesAllDocuments());
 
   query = base_query.AddingFilter(testutil::Filter("foo", "==", "bar"));

+ 0 - 148
Firestore/core/test/unit/immutable/append_only_list_test.cc

@@ -1,148 +0,0 @@
-/*
- * Copyright 2019 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/immutable/append_only_list.h"
-
-#include "Firestore/core/test/unit/immutable/testing.h"
-#include "gtest/gtest.h"
-
-namespace firebase {
-namespace firestore {
-namespace immutable {
-
-using IntList = AppendOnlyList<int>;
-
-TEST(AppendOnlyListTest, DefaultConstructs) {
-  IntList list;
-  EXPECT_TRUE(list.empty());
-  EXPECT_EQ(0, list.size());
-  EXPECT_EQ(list.begin(), list.end());
-}
-
-TEST(AppendOnlyListTest, AppendDoesNotModifyOriginal) {
-  IntList empty;
-
-  // Appending does not modify the original list
-  IntList not_empty = empty.push_back(1);
-  EXPECT_EQ(0, empty.size());
-  EXPECT_EQ(1, not_empty.size());
-}
-
-TEST(AppendOnlyListTest, AppendToEndShares) {
-  IntList initial{0, 1};
-  initial = initial.push_back(2);
-
-  // Doubling behavior should leave unused capacity
-  ASSERT_LT(initial.size(), initial.capacity());
-
-  IntList actual = initial.push_back(3);
-
-  ASSERT_NE(nullptr, actual.begin());
-  EXPECT_EQ(initial.begin(), actual.begin());
-
-  EXPECT_EQ(Sequence(4), Collect(actual));
-}
-
-TEST(AppendOnlyListTest, PopBack) {
-  IntList original{0, 1, 2};
-  EXPECT_EQ(3, original.size());
-
-  IntList smaller = original.pop_back();
-  EXPECT_EQ(2, smaller.size());
-  EXPECT_EQ(Sequence(2), Collect(smaller));
-  EXPECT_EQ(original.begin(), smaller.begin());
-
-  IntList even_smaller = smaller.pop_back();
-  EXPECT_EQ(1, even_smaller.size());
-  EXPECT_EQ(Sequence(1), Collect(even_smaller));
-  EXPECT_EQ(original.begin(), even_smaller.begin());
-
-  IntList empty = even_smaller.pop_back();
-  EXPECT_EQ(0, empty.size());
-  EXPECT_EQ(nullptr, empty.begin());
-
-  IntList empty2 = empty.pop_back();
-  EXPECT_EQ(0, empty2.size());
-  EXPECT_EQ(nullptr, empty2.begin());
-}
-
-TEST(AppendOnlyListTest, AppendToMiddleCopies) {
-  // Set up original to have extra capacity so that we can append without
-  // copying the backing vector.
-  IntList original{0, 1};
-  original = original.push_back(2);
-
-  IntList smaller = original.pop_back();
-
-  IntList original2 = original.push_back(3);
-  IntList smaller2 = smaller.push_back(3);
-
-  EXPECT_EQ((IntList{0, 1, 2, 3}), original2);
-  EXPECT_EQ((IntList{0, 1, 3}), smaller2);
-
-  EXPECT_EQ(original.begin(), original2.begin());
-
-  // Popping from original will make smaller share. Appending to smaller will
-  // force it to copy.
-  EXPECT_EQ(original.begin(), smaller.begin());
-  EXPECT_NE(smaller.begin(), smaller2.begin());
-}
-
-TEST(AppendOnlyListTest, Emplaces) {
-  using PairList = AppendOnlyList<std::pair<int, int>>;
-  PairList empty;
-
-  PairList appended = empty.emplace_back(1, 2);
-  EXPECT_EQ(std::make_pair(1, 2), appended.front());
-
-  PairList appended2 = empty.emplace_back(3, 4);
-  EXPECT_EQ(std::make_pair(3, 4), appended2.back());
-}
-
-TEST(AppendOnlyListTest, AvoidsIteratorInvalidation) {
-  const size_t iterations = 10;
-  std::vector<IntList> lists;
-  std::vector<IntList::const_iterator> iterators;
-
-  lists.emplace_back();
-  iterators.push_back(lists.back().begin());
-
-  // At each iteration, push_back onto the list
-  for (size_t i = 0; i < iterations; i++) {
-    lists.push_back(lists.back().push_back(0));
-    iterators.push_back(lists.back().begin());
-  }
-
-  for (size_t i = 0; i < iterations; i++) {
-    ASSERT_EQ(iterators[i], lists[i].begin()) << "iteration " << i;
-  }
-}
-
-TEST(AppendOnlyListTest, ReservePreventsReallocation) {
-  IntList empty;
-  IntList one = empty.push_back(1);
-  IntList two = one.push_back(2);
-  ASSERT_NE(one.begin(), two.begin());
-
-  IntList reserved = empty.reserve(2);
-  IntList reserved_one = reserved.push_back(1);
-  IntList reserved_two = reserved_one.push_back(2);
-  ASSERT_EQ(reserved_one.begin(), reserved_two.begin());
-}
-
-}  // namespace immutable
-}  // namespace firestore
-}  // namespace firebase

+ 1 - 0
Firestore/core/test/unit/local/target_cache_test.cc

@@ -18,6 +18,7 @@
 
 #include <set>
 #include <string>
+#include <unordered_set>
 #include <utility>
 
 #include "Firestore/core/src/core/field_filter.h"