Skip to content

Commit d723fc4

Browse files
author
Hui-Wu
authored
FieldValue and DocumentReference codable support. (#3231)
* working serverTimestamp * working FieldValue. Still need: document ref and ability to Eq of FieldValue * DocumentReference implemented and testing works * clean up header search path * improving FieldValue enum comments * run through formatting * addressing comments * formatted with swiftformat 0.35.7 * add missing bool->BOOL change * undo unintended swift version change * remove unwanted proj file change
1 parent cd7456f commit d723fc4

File tree

12 files changed

+286
-45
lines changed

12 files changed

+286
-45
lines changed

Firestore/Example/Firestore.xcodeproj/project.pbxproj

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,11 +60,14 @@
6060
113190791F42202FDE1ABC14 /* FIRQuerySnapshotTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5492E04F202154AA00B64F25 /* FIRQuerySnapshotTests.mm */; };
6161
11F8EE69182C9699E90A9E3D /* database_info_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = AB38D92E20235D22000A432D /* database_info_test.cc */; };
6262
12158DFCEE09D24B7988A340 /* maybe_document.pb.cc in Sources */ = {isa = PBXBuildFile; fileRef = 618BBE7E20B89AAC00B5BCE7 /* maybe_document.pb.cc */; };
63+
1235769322B7E99F007DDFA9 /* EncodableFieldValueTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1235769122B7E915007DDFA9 /* EncodableFieldValueTests.swift */; };
6364
1235769522B86E65007DDFA9 /* FirestoreEncoderTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1235769422B86E65007DDFA9 /* FirestoreEncoderTests.swift */; };
6465
127CC0D222B3ADDC00A3E42A /* CodableTimestampTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B65C996438B84DBC7616640 /* CodableTimestampTests.swift */; };
6566
1291D9F5300AFACD1FBD262D /* array_sorted_map_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 54EB764C202277B30088B8F3 /* array_sorted_map_test.cc */; };
6667
12BB9ED1CA98AA52B92F497B /* log_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 54C2294E1FECABAE007D065B /* log_test.cc */; };
6768
12DB753599571E24DCED0C2C /* FIRValidationTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5492E06D202154D600B64F25 /* FIRValidationTests.mm */; };
69+
12E62D5722BBC41A0074F412 /* FSTAPIHelpers.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5492E04E202154AA00B64F25 /* FSTAPIHelpers.mm */; };
70+
12E62D5822BBC6EF0074F412 /* FSTHelpers.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5492E03A2021401F00B64F25 /* FSTHelpers.mm */; };
6871
132E3483789344640A52F223 /* reference_set_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 132E32997D781B896672D30A /* reference_set_test.cc */; };
6972
132E3E53179DE287D875F3F2 /* FSTLevelDBTransactionTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 132E36BB104830BD806351AC /* FSTLevelDBTransactionTests.mm */; };
7073
132E3EE56C143B2C9ACB6187 /* FSTLevelDBBenchmarkTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 132E3BB3D5C42282B4ACFB20 /* FSTLevelDBBenchmarkTests.mm */; };
@@ -753,6 +756,7 @@
753756
0473AFFF5567E667A125347B /* ordered_code_benchmark.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; path = ordered_code_benchmark.cc; sourceTree = "<group>"; };
754757
0EE5300F8233D14025EF0456 /* string_apple_test.mm */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.objcpp; path = string_apple_test.mm; sourceTree = "<group>"; };
755758
11984BA0A99D7A7ABA5B0D90 /* Pods-Firestore_Example_iOS-Firestore_SwiftTests_iOS.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Firestore_Example_iOS-Firestore_SwiftTests_iOS.release.xcconfig"; path = "Pods/Target Support Files/Pods-Firestore_Example_iOS-Firestore_SwiftTests_iOS/Pods-Firestore_Example_iOS-Firestore_SwiftTests_iOS.release.xcconfig"; sourceTree = "<group>"; };
759+
1235769122B7E915007DDFA9 /* EncodableFieldValueTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EncodableFieldValueTests.swift; sourceTree = "<group>"; };
756760
1235769422B86E65007DDFA9 /* FirestoreEncoderTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FirestoreEncoderTests.swift; sourceTree = "<group>"; };
757761
1277F98C20D2DF0867496976 /* Pods-Firestore_IntegrationTests_iOS.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Firestore_IntegrationTests_iOS.debug.xcconfig"; path = "Pods/Target Support Files/Pods-Firestore_IntegrationTests_iOS/Pods-Firestore_IntegrationTests_iOS.debug.xcconfig"; sourceTree = "<group>"; };
758762
12F4357299652983A615F886 /* LICENSE */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; name = LICENSE; path = ../LICENSE; sourceTree = "<group>"; };
@@ -1354,6 +1358,7 @@
13541358
children = (
13551359
5495EB022040E90200EBA509 /* CodableGeoPointTests.swift */,
13561360
7B65C996438B84DBC7616640 /* CodableTimestampTests.swift */,
1361+
1235769122B7E915007DDFA9 /* EncodableFieldValueTests.swift */,
13571362
1235769422B86E65007DDFA9 /* FirestoreEncoderTests.swift */,
13581363
);
13591364
path = Codable;
@@ -3394,6 +3399,9 @@
33943399
544A20EE20F6C10C004E52CD /* BasicCompileTests.swift in Sources */,
33953400
5495EB032040E90200EBA509 /* CodableGeoPointTests.swift in Sources */,
33963401
127CC0D222B3ADDC00A3E42A /* CodableTimestampTests.swift in Sources */,
3402+
1235769322B7E99F007DDFA9 /* EncodableFieldValueTests.swift in Sources */,
3403+
12E62D5722BBC41A0074F412 /* FSTAPIHelpers.mm in Sources */,
3404+
12E62D5822BBC6EF0074F412 /* FSTHelpers.mm in Sources */,
33973405
1235769522B86E65007DDFA9 /* FirestoreEncoderTests.swift in Sources */,
33983406
);
33993407
runOnlyForDeploymentPostprocessing = 0;
@@ -4381,13 +4389,19 @@
43814389
ENABLE_STRICT_OBJC_MSGSEND = YES;
43824390
GCC_C_LANGUAGE_STANDARD = c99;
43834391
GCC_NO_COMMON_BLOCKS = YES;
4392+
HEADER_SEARCH_PATHS = (
4393+
"$(inherited)",
4394+
"\"${PODS_ROOT}/../../..\"",
4395+
"\"${PODS_ROOT}/../../../Firestore/third_party/abseil-cpp\"",
4396+
);
43844397
INFOPLIST_FILE = ../Swift/Tests/Info.plist;
43854398
IPHONEOS_DEPLOYMENT_TARGET = 11.2;
43864399
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
43874400
MTL_ENABLE_DEBUG_INFO = YES;
43884401
PRODUCT_BUNDLE_IDENTIFIER = "com.google.Firestore-SwiftTests-iOS";
43894402
PRODUCT_NAME = "$(TARGET_NAME)";
43904403
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
4404+
SWIFT_OBJC_BRIDGING_HEADER = ../Swift/Tests/BridgingHeader.h;
43914405
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
43924406
SWIFT_VERSION = 4.0;
43934407
TARGETED_DEVICE_FAMILY = "1,2";
@@ -4420,12 +4434,18 @@
44204434
ENABLE_STRICT_OBJC_MSGSEND = YES;
44214435
GCC_C_LANGUAGE_STANDARD = c99;
44224436
GCC_NO_COMMON_BLOCKS = YES;
4437+
HEADER_SEARCH_PATHS = (
4438+
"$(inherited)",
4439+
"\"${PODS_ROOT}/../../..\"",
4440+
"\"${PODS_ROOT}/../../../Firestore/third_party/abseil-cpp\"",
4441+
);
44234442
INFOPLIST_FILE = ../Swift/Tests/Info.plist;
44244443
IPHONEOS_DEPLOYMENT_TARGET = 11.2;
44254444
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
44264445
MTL_ENABLE_DEBUG_INFO = NO;
44274446
PRODUCT_BUNDLE_IDENTIFIER = "com.google.Firestore-SwiftTests-iOS";
44284447
PRODUCT_NAME = "$(TARGET_NAME)";
4448+
SWIFT_OBJC_BRIDGING_HEADER = ../Swift/Tests/BridgingHeader.h;
44294449
SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
44304450
SWIFT_VERSION = 4.0;
44314451
TARGETED_DEVICE_FAMILY = "1,2";
@@ -4694,6 +4714,7 @@
46944714
baseConfigurationReference = 3C81DE3772628FE297055662 /* Pods-Firestore_Example_iOS.debug.xcconfig */;
46954715
buildSettings = {
46964716
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
4717+
CLANG_ENABLE_MODULES = YES;
46974718
GCC_PRECOMPILE_PREFIX_HEADER = YES;
46984719
GCC_PREFIX_HEADER = "";
46994720
HEADER_SEARCH_PATHS = (
@@ -4709,6 +4730,8 @@
47094730
);
47104731
PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.demo.${PRODUCT_NAME:rfc1034identifier}";
47114732
PRODUCT_NAME = "$(TARGET_NAME)";
4733+
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
4734+
SWIFT_VERSION = 4.0;
47124735
WRAPPER_EXTENSION = app;
47134736
};
47144737
name = Debug;
@@ -4718,6 +4741,7 @@
47184741
baseConfigurationReference = 3F0992A4B83C60841C52E960 /* Pods-Firestore_Example_iOS.release.xcconfig */;
47194742
buildSettings = {
47204743
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
4744+
CLANG_ENABLE_MODULES = YES;
47214745
GCC_PRECOMPILE_PREFIX_HEADER = YES;
47224746
GCC_PREFIX_HEADER = "";
47234747
HEADER_SEARCH_PATHS = (
@@ -4726,13 +4750,15 @@
47264750
"\"${PODS_ROOT}/leveldb-library/include\"",
47274751
);
47284752
INFOPLIST_FILE = "App/iOS/Firestore-Info.plist";
4753+
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
47294754
MODULE_NAME = ExampleApp;
47304755
OTHER_LDFLAGS = (
47314756
"$(inherited)",
47324757
"-all_load",
47334758
);
47344759
PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.demo.${PRODUCT_NAME:rfc1034identifier}";
47354760
PRODUCT_NAME = "$(TARGET_NAME)";
4761+
SWIFT_VERSION = 4.0;
47364762
WRAPPER_EXTENSION = app;
47374763
};
47384764
name = Release;

Firestore/Example/Tests/API/FIRQueryTests.mm

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#import "Firestore/Source/Core/FSTQuery.h"
2424

2525
#import "Firestore/Example/Tests/API/FSTAPIHelpers.h"
26+
#import "Firestore/Example/Tests/Util/FSTHelpers.h"
2627

2728
namespace api = firebase::firestore::api;
2829

Firestore/Example/Tests/API/FSTAPIHelpers.h

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -13,19 +13,17 @@
1313
* See the License for the specific language governing permissions and
1414
* limitations under the License.
1515
*/
16-
1716
#import <Foundation/Foundation.h>
1817

19-
#import "Firestore/Example/Tests/Util/FSTHelpers.h"
20-
21-
#include "absl/strings/string_view.h"
22-
2318
@class FIRCollectionReference;
2419
@class FIRDocumentReference;
2520
@class FIRDocumentSnapshot;
2621
@class FIRFirestore;
2722
@class FIRQuerySnapshot;
2823

24+
/** Allow tests to just use an int literal for versions. */
25+
typedef int64_t FSTTestSnapshotVersion;
26+
2927
NS_ASSUME_NONNULL_BEGIN
3028

3129
#if __cplusplus
@@ -36,17 +34,17 @@ extern "C" {
3634
FIRFirestore *FSTTestFirestore();
3735

3836
/** A convenience method for creating a doc snapshot for tests. */
39-
FIRDocumentSnapshot *FSTTestDocSnapshot(const absl::string_view path,
37+
FIRDocumentSnapshot *FSTTestDocSnapshot(const char *path,
4038
FSTTestSnapshotVersion version,
4139
NSDictionary<NSString *, id> *_Nullable data,
4240
BOOL hasMutations,
4341
BOOL fromCache);
4442

4543
/** A convenience method for creating a collection reference from a path string. */
46-
FIRCollectionReference *FSTTestCollectionRef(const absl::string_view path);
44+
FIRCollectionReference *FSTTestCollectionRef(const char *path);
4745

4846
/** A convenience method for creating a document reference from a path string. */
49-
FIRDocumentReference *FSTTestDocRef(const absl::string_view path);
47+
FIRDocumentReference *FSTTestDocRef(const char *path);
5048

5149
/**
5250
* A convenience method for creating a particular query snapshot for tests.
@@ -63,11 +61,11 @@ FIRDocumentReference *FSTTestDocRef(const absl::string_view path);
6361
* @returns A query snapshot that consists of both sets of documents.
6462
*/
6563
FIRQuerySnapshot *FSTTestQuerySnapshot(
66-
const absl::string_view path,
64+
const char *path,
6765
NSDictionary<NSString *, NSDictionary<NSString *, id> *> *oldDocs,
6866
NSDictionary<NSString *, NSDictionary<NSString *, id> *> *docsToAdd,
69-
bool hasPendingWrites,
70-
bool fromCache);
67+
BOOL hasPendingWrites,
68+
BOOL fromCache);
7169

7270
#if __cplusplus
7371
} // extern "C"

Firestore/Example/Tests/API/FSTAPIHelpers.mm

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
#include <utility>
2525
#include <vector>
2626

27+
#import "Firestore/Example/Tests/Util/FSTHelpers.h"
2728
#import "Firestore/Source/API/FIRCollectionReference+Internal.h"
2829
#import "Firestore/Source/API/FIRDocumentReference+Internal.h"
2930
#import "Firestore/Source/API/FIRDocumentSnapshot+Internal.h"
@@ -69,7 +70,7 @@
6970
return sharedInstance;
7071
}
7172

72-
FIRDocumentSnapshot *FSTTestDocSnapshot(const absl::string_view path,
73+
FIRDocumentSnapshot *FSTTestDocSnapshot(const char *path,
7374
FSTTestSnapshotVersion version,
7475
NSDictionary<NSString *, id> *_Nullable data,
7576
BOOL hasMutations,
@@ -85,23 +86,23 @@
8586
hasPendingWrites:hasMutations];
8687
}
8788

88-
FIRCollectionReference *FSTTestCollectionRef(const absl::string_view path) {
89+
FIRCollectionReference *FSTTestCollectionRef(const char *path) {
8990
return [[FIRCollectionReference alloc] initWithPath:testutil::Resource(path)
9091
firestore:FSTTestFirestore().wrapped];
9192
}
9293

93-
FIRDocumentReference *FSTTestDocRef(const absl::string_view path) {
94+
FIRDocumentReference *FSTTestDocRef(const char *path) {
9495
return [[FIRDocumentReference alloc] initWithPath:testutil::Resource(path)
9596
firestore:FSTTestFirestore().wrapped];
9697
}
9798

9899
/** A convenience method for creating a query snapshots for tests. */
99100
FIRQuerySnapshot *FSTTestQuerySnapshot(
100-
const absl::string_view path,
101+
const char *path,
101102
NSDictionary<NSString *, NSDictionary<NSString *, id> *> *oldDocs,
102103
NSDictionary<NSString *, NSDictionary<NSString *, id> *> *docsToAdd,
103-
bool hasPendingWrites,
104-
bool fromCache) {
104+
BOOL hasPendingWrites,
105+
BOOL fromCache) {
105106
SnapshotMetadata metadata(hasPendingWrites, fromCache);
106107
DocumentSet oldDocuments = FSTTestDocSet(DocumentComparator::ByKey(), @[]);
107108
DocumentKeySet mutatedKeys;
@@ -132,7 +133,7 @@
132133
oldDocuments,
133134
std::move(documentChanges),
134135
mutatedKeys,
135-
fromCache,
136+
static_cast<bool>(fromCache),
136137
/*sync_state_changed=*/true,
137138
/*excludes_metadata_changes=*/false};
138139
return [[FIRQuerySnapshot alloc] initWithFirestore:FSTTestFirestore().wrapped

Firestore/Swift/Source/Codable/CodablePassThroughTypes.swift

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,5 +20,7 @@ import FirebaseFirestore
2020
internal func isFirestorePassthroughType<T: Any>(_ value: T) -> Bool {
2121
return
2222
T.self == GeoPoint.self ||
23-
T.self == Timestamp.self
23+
T.self == Timestamp.self ||
24+
T.self == FieldValue.self ||
25+
T.self == DocumentReference.self
2426
}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
/*
2+
* Copyright 2019 Google
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
import FirebaseFirestore
18+
19+
/** Mark DocumentReference to conform to Codable. */
20+
21+
/**
22+
* A protocol describing the encodable properties of a DocumentReference.
23+
*
24+
* Note: this protocol exists as a workaround for the Swift compiler: if the DocumentReference class
25+
* was extended directly to conform to Codable, the methods implementing the protocol would be need
26+
* to be marked required but that can't be done in an extension. Declaring the extension on the
27+
* protocol sidesteps this issue.
28+
*/
29+
private protocol CodableDocumentReference: Codable {}
30+
31+
/**
32+
* DocumentReference's codable implmentation will just throw for most
33+
* encoder/decoder however. It is only meant to be encoded by FirestoreEncoder/FirestoreDecoder.
34+
*/
35+
extension CodableDocumentReference {
36+
public init(from decoder: Decoder) throws {
37+
throw FirestoreDecodingError.decodingIsNotSupported
38+
}
39+
40+
public func encode(to encoder: Encoder) throws {
41+
throw FirestoreEncodingError.encodingIsNotSupported
42+
}
43+
}
44+
45+
extension DocumentReference: CodableDocumentReference {}
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
/*
2+
* Copyright 2019 Google
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
import FirebaseFirestore
18+
19+
/** Extends FieldValue to conform to Encodable. */
20+
extension FieldValue: Encodable {
21+
/// Encoding a FieldValue will throw by default unless the encoder implementation
22+
/// explicitly handles it, which is what FirestoreEncoder does.
23+
public func encode(to encoder: Encoder) throws {
24+
throw FirestoreEncodingError.encodingIsNotSupported
25+
}
26+
}
27+
28+
/** Swift enums providing alternatives to direct usages of FieldValue. */
29+
30+
/// Wraps around Timestamp and FieldValue.serverTimestamp to support modeling
31+
/// timestamps in custom classes.
32+
///
33+
/// Example:
34+
/// struct CustomModel {
35+
/// var ts: ServerTimestamp
36+
/// }
37+
/// Then `CustomModel(ts: .pending)` will tell server to fill `ts` with current
38+
/// timestamp.
39+
public enum ServerTimestamp: Codable, Equatable {
40+
/// When being read (decoded) from Firestore, NSNull values will be mapped to `pending`.
41+
/// When being written (encoded) to Firestore, `pending` means requesting server to
42+
/// set timestamp on the field (essentially setting value
43+
/// to FieldValue.serverTimestamp()).
44+
case pending
45+
46+
/// When being read (decoded) from Firestore, non-nil Timestamp will be mapped to
47+
/// `resolved`.
48+
/// When being written (encoded) to Firestore, `resolved(stamp)` will set the field
49+
/// value to `stamp`.
50+
case resolved(Timestamp)
51+
52+
public init(from decoder: Decoder) throws {
53+
let container = try decoder.singleValueContainer()
54+
if container.decodeNil() {
55+
self = .pending
56+
} else {
57+
let value = try container.decode(Timestamp.self)
58+
self = .resolved(value)
59+
}
60+
}
61+
62+
public func encode(to encoder: Encoder) throws {
63+
var container = encoder.singleValueContainer()
64+
switch self {
65+
case .pending:
66+
try container.encode(FieldValue.serverTimestamp())
67+
case let .resolved(value: value):
68+
try container.encode(value)
69+
}
70+
}
71+
}

Firestore/Swift/Source/Codable/third_party/FirestoreDecoder.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1033,7 +1033,7 @@ extension _FirestoreDecoder {
10331033
}
10341034
}
10351035

1036-
// Decoding an embeded container, this requires expanding the storage stack and
1036+
// Decoding an embedded container, this requires expanding the storage stack and
10371037
// then restore after decoding.
10381038
storage.push(container: value)
10391039
let decoded = try T(from: self)

Firestore/Swift/Source/Codable/third_party/FirestoreEncoder.swift

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,10 @@ extension Firestore {
3535
/// - Returns: A Map keyed by String representing a document Firestore
3636
/// API can work with.
3737
public func encode<T: Encodable>(_ value: T) throws -> [String: Any] {
38+
// DocumentReference and FieldValue cannot be encoded directly.
39+
guard T.self != DocumentReference.self && T.self != FieldValue.self else {
40+
throw FirestoreEncodingError.encodingIsNotSupported
41+
}
3842
guard let topLevel = try _FirestoreEncoder().box_(value) else {
3943
throw EncodingError.invalidValue(value,
4044
EncodingError.Context(codingPath: [],
@@ -495,7 +499,7 @@ extension _FirestoreEncoder: SingleValueEncodingContainer {
495499
}
496500

497501
/// Special subclass of `_FirestoreEncoder` used by `superEncoder`.
498-
/// It inherits the codingPath from the referencing `_FirestoreEncoder` but uses it's own
502+
/// It inherits the codingPath from the referencing `_FirestoreEncoder` but uses its own
499503
/// storage. The encoded result will be written back to the referencing encoder's storage
500504
/// when it is `deinit`-ed.
501505
private class _FirestoreReferencingEncoder: _FirestoreEncoder {

0 commit comments

Comments
 (0)