修改pods
This commit is contained in:
@@ -24,7 +24,7 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
/** @typedef FIRTokenCallback
|
||||
@brief The type of block which gets called when a token is ready.
|
||||
*/
|
||||
typedef void (^FIRTokenCallback)(NSString *_Nullable token, NSError *_Nullable error)
|
||||
typedef void (^FIRTokenCallback)(NSString *_Nullable_result token, NSError *_Nullable error)
|
||||
NS_SWIFT_UNAVAILABLE("Use Swift's closure syntax instead.");
|
||||
|
||||
/// Common methods for Auth interoperability.
|
||||
@@ -34,7 +34,7 @@ NS_SWIFT_NAME(AuthInterop)
|
||||
/// Retrieves the Firebase authentication token, possibly refreshing it if it has expired.
|
||||
- (void)getTokenForcingRefresh:(BOOL)forceRefresh
|
||||
withCallback:
|
||||
(void (^)(NSString *_Nullable token, NSError *_Nullable error))callback
|
||||
(void (^)(NSString *_Nullable_result token, NSError *_Nullable error))callback
|
||||
NS_SWIFT_NAME(getToken(forcingRefresh:completion:));
|
||||
|
||||
/// Get the current Auth user's UID. Returns nil if there is no user signed in.
|
||||
@@ -14,6 +14,9 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef FIREBASECORE_FIRAPPINTERNAL_H
|
||||
#define FIREBASECORE_FIRAPPINTERNAL_H
|
||||
|
||||
#import <FirebaseCore/FIRApp.h>
|
||||
|
||||
@class FIRComponentContainer;
|
||||
@@ -40,8 +43,26 @@ extern NSString *const kFIRAppNameKey;
|
||||
extern NSString *const kFIRGoogleAppIDKey;
|
||||
extern NSString *const kFirebaseCoreErrorDomain;
|
||||
|
||||
/** The `UserDefaults` suite name for `FirebaseCore`, for those storage locations that use it. */
|
||||
extern NSString *const kFirebaseCoreDefaultsSuiteName;
|
||||
/**
|
||||
* Keys for the strings in the plist file.
|
||||
*/
|
||||
extern NSString *const kFIRAPIKey;
|
||||
extern NSString *const kFIRTrackingID;
|
||||
extern NSString *const kFIRGoogleAppID;
|
||||
extern NSString *const kFIRClientID;
|
||||
extern NSString *const kFIRGCMSenderID;
|
||||
extern NSString *const kFIRAndroidClientID;
|
||||
extern NSString *const kFIRDatabaseURL;
|
||||
extern NSString *const kFIRStorageBucket;
|
||||
extern NSString *const kFIRBundleID;
|
||||
extern NSString *const kFIRProjectID;
|
||||
|
||||
/**
|
||||
* Keys for the plist file name
|
||||
*/
|
||||
extern NSString *const kServiceInfoFileName;
|
||||
|
||||
extern NSString *const kServiceInfoFileType;
|
||||
|
||||
/**
|
||||
* The format string for the `UserDefaults` key used for storing the data collection enabled flag.
|
||||
@@ -157,3 +178,5 @@ extern NSString *const FIRAuthStateDidChangeInternalNotificationUIDKey;
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
#endif // FIREBASECORE_FIRAPPINTERNAL_H
|
||||
|
||||
@@ -14,6 +14,9 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef FIREBASECORE_FIRCOMPONENT_H
|
||||
#define FIREBASECORE_FIRCOMPONENT_H
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
@class FIRApp;
|
||||
@@ -32,8 +35,6 @@ typedef _Nullable id (^FIRComponentCreationBlock)(FIRComponentContainer *contain
|
||||
BOOL *isCacheable)
|
||||
NS_SWIFT_NAME(ComponentCreationBlock);
|
||||
|
||||
@class FIRDependency;
|
||||
|
||||
/// Describes the timing of instantiation. Note: new components should default to lazy unless there
|
||||
/// is a strong reason to be eager.
|
||||
typedef NS_ENUM(NSInteger, FIRInstantiationTiming) {
|
||||
@@ -52,9 +53,6 @@ NS_SWIFT_NAME(Component)
|
||||
/// The timing of instantiation.
|
||||
@property(nonatomic, readonly) FIRInstantiationTiming instantiationTiming;
|
||||
|
||||
/// An array of dependencies for the component.
|
||||
@property(nonatomic, copy, readonly) NSArray<FIRDependency *> *dependencies;
|
||||
|
||||
/// A block to instantiate an instance of the component with the appropriate dependencies.
|
||||
@property(nonatomic, copy, readonly) FIRComponentCreationBlock creationBlock;
|
||||
|
||||
@@ -72,14 +70,12 @@ NS_SWIFT_NAME(init(_:creationBlock:));
|
||||
/// @param protocol - The protocol describing functionality provided by the component.
|
||||
/// @param instantiationTiming - When the component should be initialized. Use .lazy unless there's
|
||||
/// a good reason to be instantiated earlier.
|
||||
/// @param dependencies - Any dependencies the `implementingClass` has, optional or required.
|
||||
/// @param creationBlock - A block to instantiate the component with a container, and if
|
||||
/// @return A component that can be registered with the component container.
|
||||
+ (instancetype)componentWithProtocol:(Protocol *)protocol
|
||||
instantiationTiming:(FIRInstantiationTiming)instantiationTiming
|
||||
dependencies:(NSArray<FIRDependency *> *)dependencies
|
||||
creationBlock:(FIRComponentCreationBlock)creationBlock
|
||||
NS_SWIFT_NAME(init(_:instantiationTiming:dependencies:creationBlock:));
|
||||
NS_SWIFT_NAME(init(_:instantiationTiming:creationBlock:));
|
||||
|
||||
// clang-format on
|
||||
|
||||
@@ -89,3 +85,5 @@ NS_SWIFT_NAME(init(_:instantiationTiming:dependencies:creationBlock:));
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
#endif // FIREBASECORE_FIRCOMPONENT_H
|
||||
|
||||
@@ -13,6 +13,10 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef FIREBASECORE_FIRCOMPONENTCONTAINER_H
|
||||
#define FIREBASECORE_FIRCOMPONENTCONTAINER_H
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
@@ -43,3 +47,5 @@ NS_SWIFT_NAME(FirebaseComponentContainer)
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
#endif // FIREBASECORE_FIRCOMPONENTCONTAINER_H
|
||||
|
||||
@@ -14,6 +14,9 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef FIREBASECORE_FIRCOMPONENTTYPE_H
|
||||
#define FIREBASECORE_FIRCOMPONENTTYPE_H
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
@class FIRComponentContainer;
|
||||
@@ -33,3 +36,5 @@ NS_SWIFT_NAME(ComponentType)
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
#endif // FIREBASECORE_FIRCOMPONENTTYPE_H
|
||||
|
||||
@@ -1,45 +0,0 @@
|
||||
/*
|
||||
* Copyright 2018 Google
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/// A dependency on a specific protocol's functionality.
|
||||
NS_SWIFT_NAME(Dependency)
|
||||
@interface FIRDependency : NSObject
|
||||
|
||||
/// The protocol describing functionality being depended on.
|
||||
@property(nonatomic, strong, readonly) Protocol *protocol;
|
||||
|
||||
/// A flag to specify if the dependency is required or not.
|
||||
@property(nonatomic, readonly) BOOL isRequired;
|
||||
|
||||
/// Initializes a dependency that is required. Calls `init(protocol:isRequired:)` with true for
|
||||
/// the required parameter.
|
||||
/// Creates a required dependency on the specified protocol's functionality.
|
||||
+ (instancetype)dependencyWithProtocol:(Protocol *)protocol;
|
||||
|
||||
/// Creates a dependency on the specified protocol's functionality and specify if it's required for
|
||||
/// the class's functionality.
|
||||
+ (instancetype)dependencyWithProtocol:(Protocol *)protocol isRequired:(BOOL)required;
|
||||
|
||||
/// Use `init(withProtocol:isRequired:)` instead.
|
||||
- (instancetype)init NS_UNAVAILABLE;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
@@ -12,6 +12,9 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef FIREBASECORE_FIRHEARTBEATLOGGER_H
|
||||
#define FIREBASECORE_FIRHEARTBEATLOGGER_H
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
@@ -30,19 +33,24 @@ typedef NS_ENUM(NSInteger, FIRDailyHeartbeatCode) {
|
||||
FIRDailyHeartbeatCodeSome = 2,
|
||||
};
|
||||
|
||||
NS_SWIFT_SENDABLE
|
||||
@protocol FIRHeartbeatLoggerProtocol <NSObject>
|
||||
|
||||
/// Asynchronously logs a heartbeat.
|
||||
- (void)log;
|
||||
|
||||
#ifndef FIREBASE_BUILD_CMAKE
|
||||
/// Flushes heartbeats from storage into a structured payload of heartbeats.
|
||||
- (FIRHeartbeatsPayload *)flushHeartbeatsIntoPayload;
|
||||
#endif // FIREBASE_BUILD_CMAKE
|
||||
|
||||
/// Gets the heartbeat code for today.
|
||||
- (FIRDailyHeartbeatCode)heartbeatCodeForToday;
|
||||
|
||||
#ifndef FIREBASE_BUILD_CMAKE
|
||||
/// Returns the header value for the heartbeat logger via the given completion handler..
|
||||
- (void)asyncHeaderValueWithCompletionHandler:(void (^)(NSString *_Nullable))completionHandler
|
||||
API_AVAILABLE(ios(13.0), macosx(10.15), macCatalyst(13.0), tvos(13.0), watchos(6.0));
|
||||
|
||||
/// Return the header value for the heartbeat logger.
|
||||
- (NSString *_Nullable)headerValue;
|
||||
#endif // FIREBASE_BUILD_CMAKE
|
||||
|
||||
@end
|
||||
|
||||
#ifndef FIREBASE_BUILD_CMAKE
|
||||
@@ -68,13 +76,23 @@ NSString *_Nullable FIRHeaderValueFromHeartbeatsPayload(FIRHeartbeatsPayload *he
|
||||
- (void)log;
|
||||
|
||||
#ifndef FIREBASE_BUILD_CMAKE
|
||||
/// Flushes heartbeats from storage into a structured payload of heartbeats.
|
||||
/// Synchronously flushes heartbeats from storage into a structured payload of heartbeats.
|
||||
///
|
||||
/// This API is for clients using platform logging V2.
|
||||
///
|
||||
/// @note This API is thread-safe.
|
||||
/// @return A payload of heartbeats.
|
||||
- (FIRHeartbeatsPayload *)flushHeartbeatsIntoPayload;
|
||||
|
||||
/// Asynchronously flushes heartbeats from storage into a structured payload of heartbeats.
|
||||
///
|
||||
/// This API is for clients using platform logging V2.
|
||||
///
|
||||
/// @note This API is thread-safe.
|
||||
/// @param completionHandler A completion handler to process the flushed payload of heartbeats.
|
||||
- (void)flushHeartbeatsIntoPayloadWithCompletionHandler:
|
||||
(void (^)(FIRHeartbeatsPayload *))completionHandler
|
||||
API_AVAILABLE(ios(13.0), macosx(10.15), macCatalyst(13.0), tvos(13.0), watchos(6.0));
|
||||
#endif // FIREBASE_BUILD_CMAKE
|
||||
|
||||
/// Gets today's corresponding heartbeat code.
|
||||
@@ -88,3 +106,5 @@ NSString *_Nullable FIRHeaderValueFromHeartbeatsPayload(FIRHeartbeatsPayload *he
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
#endif // FIREBASECORE_FIRHEARTBEATLOGGER_H
|
||||
|
||||
@@ -14,6 +14,9 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef FIREBASECORE_FIRLIBRARY_H
|
||||
#define FIREBASECORE_FIRLIBRARY_H
|
||||
|
||||
#ifndef FIRLibrary_h
|
||||
#define FIRLibrary_h
|
||||
|
||||
@@ -32,13 +35,10 @@ NS_SWIFT_NAME(Library)
|
||||
/// FirebaseApp and participate in dependency resolution and injection.
|
||||
+ (NSArray<FIRComponent *> *)componentsToRegister;
|
||||
|
||||
@optional
|
||||
/// Implement this method if the library needs notifications for lifecycle events. This method is
|
||||
/// called when the developer calls `FirebaseApp.configure()`.
|
||||
+ (void)configureWithApp:(FIRApp *)app;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
#endif /* FIRLibrary_h */
|
||||
|
||||
#endif // FIREBASECORE_FIRLIBRARY_H
|
||||
|
||||
@@ -14,9 +14,12 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef FIREBASECORE_FIRLOGGER_H
|
||||
#define FIREBASECORE_FIRLOGGER_H
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#import <FirebaseCore/FIRLoggerLevel.h>
|
||||
typedef NS_ENUM(NSInteger, FIRLoggerLevel);
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@@ -25,10 +28,10 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
*/
|
||||
typedef NSString *const FIRLoggerService;
|
||||
|
||||
extern FIRLoggerService kFIRLoggerAnalytics;
|
||||
extern FIRLoggerService kFIRLoggerCrash;
|
||||
extern FIRLoggerService kFIRLoggerCore;
|
||||
extern FIRLoggerService kFIRLoggerRemoteConfig;
|
||||
extern NSString *const kFIRLoggerAnalytics;
|
||||
extern NSString *const kFIRLoggerCrash;
|
||||
extern NSString *const kFIRLoggerCore;
|
||||
extern NSString *const kFIRLoggerRemoteConfig;
|
||||
|
||||
/**
|
||||
* The key used to store the logger's error count.
|
||||
@@ -64,6 +67,11 @@ FIRLoggerLevel FIRGetLoggerLevel(void);
|
||||
*/
|
||||
void FIRSetLoggerLevel(FIRLoggerLevel loggerLevel);
|
||||
|
||||
void FIRSetLoggerLevelNotice(void);
|
||||
void FIRSetLoggerLevelWarning(void);
|
||||
void FIRSetLoggerLevelError(void);
|
||||
void FIRSetLoggerLevelDebug(void);
|
||||
|
||||
/**
|
||||
* Checks if the specified logger level is loggable given the current settings.
|
||||
* (required) log level (one of the FirebaseLoggerLevel enum values).
|
||||
@@ -71,6 +79,11 @@ void FIRSetLoggerLevel(FIRLoggerLevel loggerLevel);
|
||||
*/
|
||||
BOOL FIRIsLoggableLevel(FIRLoggerLevel loggerLevel, BOOL analyticsComponent);
|
||||
|
||||
BOOL FIRIsLoggableLevelNotice(void);
|
||||
BOOL FIRIsLoggableLevelWarning(void);
|
||||
BOOL FIRIsLoggableLevelError(void);
|
||||
BOOL FIRIsLoggableLevelDebug(void);
|
||||
|
||||
/**
|
||||
* Logs a message to the Xcode console and the device log. If running from AppStore, will
|
||||
* not log any messages with a level higher than FirebaseLoggerLevelNotice to avoid log spamming.
|
||||
@@ -85,7 +98,7 @@ BOOL FIRIsLoggableLevel(FIRLoggerLevel loggerLevel, BOOL analyticsComponent);
|
||||
* string.
|
||||
*/
|
||||
extern void FIRLogBasic(FIRLoggerLevel level,
|
||||
FIRLoggerService service,
|
||||
NSString *category,
|
||||
NSString *messageCode,
|
||||
NSString *message,
|
||||
// On 64-bit simulators, va_list is not a pointer, so cannot be marked nullable
|
||||
@@ -110,43 +123,51 @@ extern void FIRLogBasic(FIRLoggerLevel level,
|
||||
* Example usage:
|
||||
* FirebaseLogError(kFirebaseLoggerCore, @"I-COR000001", @"Configuration of %@ failed.", app.name);
|
||||
*/
|
||||
extern void FIRLogError(FIRLoggerService service, NSString *messageCode, NSString *message, ...)
|
||||
extern void FIRLogError(NSString *category, NSString *messageCode, NSString *message, ...)
|
||||
NS_FORMAT_FUNCTION(3, 4);
|
||||
extern void FIRLogWarning(FIRLoggerService service, NSString *messageCode, NSString *message, ...)
|
||||
extern void FIRLogWarning(NSString *category, NSString *messageCode, NSString *message, ...)
|
||||
NS_FORMAT_FUNCTION(3, 4);
|
||||
extern void FIRLogNotice(FIRLoggerService service, NSString *messageCode, NSString *message, ...)
|
||||
extern void FIRLogNotice(NSString *category, NSString *messageCode, NSString *message, ...)
|
||||
NS_FORMAT_FUNCTION(3, 4);
|
||||
extern void FIRLogInfo(FIRLoggerService service, NSString *messageCode, NSString *message, ...)
|
||||
extern void FIRLogInfo(NSString *category, NSString *messageCode, NSString *message, ...)
|
||||
NS_FORMAT_FUNCTION(3, 4);
|
||||
extern void FIRLogDebug(FIRLoggerService service, NSString *messageCode, NSString *message, ...)
|
||||
extern void FIRLogDebug(NSString *category, NSString *messageCode, NSString *message, ...)
|
||||
NS_FORMAT_FUNCTION(3, 4);
|
||||
|
||||
// TODO: Come up with a better logging scheme for Swift.
|
||||
/**
|
||||
* Logs a debug message to the Xcode console and the device log. If running from AppStore, will
|
||||
* not log any messages with a level higher than FirebaseLoggerLevelNotice to avoid log spamming.
|
||||
* This function is intended to be used by Swift clients that do not support variadic parameters.
|
||||
* This function is similar to the one above, except it takes a `va_list` instead of the listed
|
||||
* variables.
|
||||
*
|
||||
* @param service The service name of type `FirebaseLoggerService`.
|
||||
* @param messageCode The mesage code. starting with "I-" which means iOS, followed by a capitalized
|
||||
* three-character service identifier and a six digit integer message ID that is unique within the
|
||||
* service. An example of the message code is @"I-COR000001".
|
||||
* @param message The message string.
|
||||
*/
|
||||
extern void FIRLogDebugSwift(FIRLoggerService service, NSString *messageCode, NSString *message);
|
||||
|
||||
/**
|
||||
* Logs a warning message to the Xcode console and the device log. If running from AppStore, will
|
||||
* not log any messages with a level higher than FirebaseLoggerLevelNotice to avoid log spamming.
|
||||
* This function is intended to be used by Swift clients that do not support variadic parameters.
|
||||
* The following functions accept the following parameters in order: (required) service
|
||||
* name of type FirebaseLoggerService.
|
||||
*
|
||||
* @param service The service name of type `FirebaseLoggerService`.
|
||||
* @param messageCode The mesage code. starting with "I-" which means iOS, followed by a capitalized
|
||||
* three-character service identifier and a six digit integer message ID that is unique within the
|
||||
* service. An example of the message code is @"I-COR000001".
|
||||
* @param message The message string.
|
||||
* (required) message code starting from "I-" which means iOS,
|
||||
* followed by a capitalized three-character service identifier and a six digit integer message
|
||||
* ID that is unique within the service. An example of the message code is @"I-COR000001".
|
||||
* See go/firebase-log-proposal for details.
|
||||
* (required) message string which can be a format string.
|
||||
* (optional) A va_list
|
||||
*/
|
||||
extern void FIRLogWarningSwift(FIRLoggerService service, NSString *messageCode, NSString *message);
|
||||
extern void FIRLogBasicError(NSString *category,
|
||||
NSString *messageCode,
|
||||
NSString *message,
|
||||
va_list args_ptr);
|
||||
extern void FIRLogBasicWarning(NSString *category,
|
||||
NSString *messageCode,
|
||||
NSString *message,
|
||||
va_list args_ptr);
|
||||
extern void FIRLogBasicNotice(NSString *category,
|
||||
NSString *messageCode,
|
||||
NSString *message,
|
||||
va_list args_ptr);
|
||||
extern void FIRLogBasicInfo(NSString *category,
|
||||
NSString *messageCode,
|
||||
NSString *message,
|
||||
va_list args_ptr);
|
||||
extern void FIRLogBasicDebug(NSString *category,
|
||||
NSString *messageCode,
|
||||
NSString *message,
|
||||
va_list args_ptr);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
@@ -155,35 +176,17 @@ extern void FIRLogWarningSwift(FIRLoggerService service, NSString *messageCode,
|
||||
NS_SWIFT_NAME(FirebaseLogger)
|
||||
@interface FIRLoggerWrapper : NSObject
|
||||
|
||||
/// Logs a given message at a given log level. This API is effectively a wrapper for the
|
||||
/// `FIRLogBasic` C API.
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - level: The log level to use (defined by `FirebaseLoggerLevel` enum values).
|
||||
/// - service: The service name of type `FirebaseLoggerService`.
|
||||
/// - code: The mesage code. Starting with "I-" which means iOS, followed by a capitalized
|
||||
/// three-character service identifier and a six digit integer message ID that is unique within
|
||||
/// the service. An example of the message code is @"I-COR000001".
|
||||
/// - message: Formatted string to be used as the log's message.
|
||||
/// - args: Arguments list obtained from calling `va_start`, used when message is a format string.
|
||||
+ (void)logWithLevel:(FIRLoggerLevel)level
|
||||
withService:(FIRLoggerService)service
|
||||
withCode:(NSString *)messageCode
|
||||
withMessage:(NSString *)message
|
||||
withArgs:(va_list)args;
|
||||
|
||||
/// Logs a given message at a given log level.
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - level: The log level to use (defined by `FirebaseLoggerLevel` enum values).
|
||||
/// - service: The service name of type `FirebaseLoggerService`.
|
||||
/// - code: The mesage code. Starting with "I-" which means iOS, followed by a capitalized
|
||||
/// - category: The service name of type `FirebaseLoggerService`.
|
||||
/// - code: The message code. Starting with "I-" which means iOS, followed by a capitalized
|
||||
/// three-character service identifier and a six digit integer message ID that is unique within
|
||||
/// the service. An example of the message code is @"I-COR000001".
|
||||
/// - message: Formatted string to be used as the log's message.
|
||||
/// - args: Arguments list obtained from calling `va_start`, used when message is a format string.
|
||||
+ (void)logWithLevel:(FIRLoggerLevel)level
|
||||
service:(FIRLoggerService)service
|
||||
service:(NSString *)category
|
||||
code:(NSString *)code
|
||||
message:(NSString *)message
|
||||
__attribute__((__swift_name__("log(level:service:code:message:)")));
|
||||
@@ -191,3 +194,5 @@ NS_SWIFT_NAME(FirebaseLogger)
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
#endif // FIREBASECORE_FIRLOGGER_H
|
||||
|
||||
@@ -12,14 +12,17 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef FIREBASECORE_FIREBASECOREINTERNAL_H
|
||||
#define FIREBASECORE_FIREBASECOREINTERNAL_H
|
||||
|
||||
@import FirebaseCore;
|
||||
|
||||
#import "FIRAppInternal.h"
|
||||
#import "FIRComponent.h"
|
||||
#import "FIRComponentContainer.h"
|
||||
#import "FIRComponentType.h"
|
||||
#import "FIRDependency.h"
|
||||
#import "FIRHeartbeatLogger.h"
|
||||
#import "FIRLibrary.h"
|
||||
#import "FIRLogger.h"
|
||||
#import "FIROptionsInternal.h"
|
||||
|
||||
#endif // FIREBASECORE_FIREBASECOREINTERNAL_H
|
||||
|
||||
@@ -16,27 +16,6 @@
|
||||
|
||||
#import <FirebaseCore/FIROptions.h>
|
||||
|
||||
/**
|
||||
* Keys for the strings in the plist file.
|
||||
*/
|
||||
extern NSString *const kFIRAPIKey;
|
||||
extern NSString *const kFIRTrackingID;
|
||||
extern NSString *const kFIRGoogleAppID;
|
||||
extern NSString *const kFIRClientID;
|
||||
extern NSString *const kFIRGCMSenderID;
|
||||
extern NSString *const kFIRAndroidClientID;
|
||||
extern NSString *const kFIRDatabaseURL;
|
||||
extern NSString *const kFIRStorageBucket;
|
||||
extern NSString *const kFIRBundleID;
|
||||
extern NSString *const kFIRProjectID;
|
||||
|
||||
/**
|
||||
* Keys for the plist file name
|
||||
*/
|
||||
extern NSString *const kServiceInfoFileName;
|
||||
|
||||
extern NSString *const kServiceInfoFileType;
|
||||
|
||||
/**
|
||||
* This header file exposes the initialization of FirebaseOptions to internal use.
|
||||
*/
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2023 Google LLC
|
||||
* Copyright 2024 Google LLC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2023 Google LLC
|
||||
* Copyright 2024 Google LLC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2023 Google LLC
|
||||
* Copyright 2024 Google LLC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2023 Google LLC
|
||||
* Copyright 2024 Google LLC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2023 Google LLC
|
||||
* Copyright 2024 Google LLC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2023 Google LLC
|
||||
* Copyright 2024 Google LLC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2023 Google LLC
|
||||
* Copyright 2024 Google LLC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2023 Google LLC
|
||||
* Copyright 2024 Google LLC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2023 Google LLC
|
||||
* Copyright 2024 Google LLC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2023 Google LLC
|
||||
* Copyright 2024 Google LLC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2023 Google LLC
|
||||
* Copyright 2024 Google LLC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2023 Google LLC
|
||||
* Copyright 2024 Google LLC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2023 Google LLC
|
||||
* Copyright 2024 Google LLC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2023 Google LLC
|
||||
* Copyright 2024 Google LLC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2023 Google LLC
|
||||
* Copyright 2024 Google LLC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2023 Google LLC
|
||||
* Copyright 2024 Google LLC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2023 Google LLC
|
||||
* Copyright 2024 Google LLC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2023 Google LLC
|
||||
* Copyright 2024 Google LLC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2023 Google LLC
|
||||
* Copyright 2024 Google LLC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2023 Google LLC
|
||||
* Copyright 2024 Google LLC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2023 Google LLC
|
||||
* Copyright 2024 Google LLC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2023 Google LLC
|
||||
* Copyright 2024 Google LLC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2023 Google LLC
|
||||
* Copyright 2024 Google LLC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2023 Google LLC
|
||||
* Copyright 2024 Google LLC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2023 Google LLC
|
||||
* Copyright 2024 Google LLC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2023 Google LLC
|
||||
* Copyright 2024 Google LLC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2023 Google LLC
|
||||
* Copyright 2024 Google LLC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2023 Google LLC
|
||||
* Copyright 2024 Google LLC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2023 Google LLC
|
||||
* Copyright 2024 Google LLC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2023 Google LLC
|
||||
* Copyright 2024 Google LLC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2023 Google LLC
|
||||
* Copyright 2024 Google LLC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2023 Google LLC
|
||||
* Copyright 2024 Google LLC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2023 Google LLC
|
||||
* Copyright 2024 Google LLC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2023 Google LLC
|
||||
* Copyright 2024 Google LLC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2023 Google LLC
|
||||
* Copyright 2024 Google LLC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2023 Google LLC
|
||||
* Copyright 2024 Google LLC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2023 Google LLC
|
||||
* Copyright 2024 Google LLC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2023 Google LLC
|
||||
* Copyright 2024 Google LLC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2023 Google LLC
|
||||
* Copyright 2024 Google LLC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2023 Google LLC
|
||||
* Copyright 2024 Google LLC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2023 Google LLC
|
||||
* Copyright 2024 Google LLC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2023 Google LLC
|
||||
* Copyright 2024 Google LLC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2023 Google LLC
|
||||
* Copyright 2024 Google LLC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2023 Google LLC
|
||||
* Copyright 2024 Google LLC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
@@ -14,11 +14,13 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#import "FIRDocumentSnapshot+Internal.h"
|
||||
#import <FirebaseCore/FIRTimestamp.h>
|
||||
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#import "FIRDocumentSnapshot+Internal.h"
|
||||
|
||||
#include "Firestore/core/src/util/warnings.h"
|
||||
|
||||
#import "Firestore/Source/API/FIRDocumentReference+Internal.h"
|
||||
@@ -26,7 +28,6 @@
|
||||
#import "Firestore/Source/API/FIRFirestore+Internal.h"
|
||||
#import "Firestore/Source/API/FIRGeoPoint+Internal.h"
|
||||
#import "Firestore/Source/API/FIRSnapshotMetadata+Internal.h"
|
||||
#import "Firestore/Source/API/FIRTimestamp+Internal.h"
|
||||
#import "Firestore/Source/API/FSTUserDataWriter.h"
|
||||
#import "Firestore/Source/API/converters.h"
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
|
||||
#import "Firestore/Source/API/FIRFieldValue+Internal.h"
|
||||
#import "Firestore/Source/Public/FirebaseFirestore/FIRVectorValue.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@@ -176,6 +177,10 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
return [[FSTNumericIncrementFieldValue alloc] initWithOperand:@(l)];
|
||||
}
|
||||
|
||||
+ (nonnull FIRVectorValue *)vectorWithArray:(nonnull NSArray<NSNumber *> *)array {
|
||||
return [[FIRVectorValue alloc] initWithArray:array];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
@@ -1,152 +0,0 @@
|
||||
/*
|
||||
* Copyright 2017 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.
|
||||
*/
|
||||
|
||||
#import "Firestore/Source/API/FIRTimestamp+Internal.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
static const int kNanosPerSecond = 1000000000;
|
||||
|
||||
@implementation FIRTimestamp (Internal)
|
||||
|
||||
#pragma mark - Internal public methods
|
||||
|
||||
- (NSString *)ISO8601String {
|
||||
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
|
||||
formatter.dateFormat = @"yyyy-MM-dd'T'HH:mm:ss";
|
||||
formatter.timeZone = [NSTimeZone timeZoneWithName:@"UTC"];
|
||||
NSDate *secondsDate = [NSDate dateWithTimeIntervalSince1970:self.seconds];
|
||||
NSString *secondsString = [formatter stringFromDate:secondsDate];
|
||||
if (secondsString.length != 19) {
|
||||
[NSException raise:@"Invalid ISO string" format:@"Invalid ISO string: %@", secondsString];
|
||||
}
|
||||
|
||||
NSString *nanosString = [NSString stringWithFormat:@"%09d", self.nanoseconds];
|
||||
return [NSString stringWithFormat:@"%@.%@Z", secondsString, nanosString];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation FIRTimestamp
|
||||
|
||||
#pragma mark - Constructors
|
||||
|
||||
+ (instancetype)timestampWithDate:(NSDate *)date {
|
||||
double secondsDouble;
|
||||
double fraction = modf(date.timeIntervalSince1970, &secondsDouble);
|
||||
// GCP Timestamps always have non-negative nanos.
|
||||
if (fraction < 0) {
|
||||
fraction += 1.0;
|
||||
secondsDouble -= 1.0;
|
||||
}
|
||||
int64_t seconds = (int64_t)secondsDouble;
|
||||
int32_t nanos = (int32_t)(fraction * kNanosPerSecond);
|
||||
return [[FIRTimestamp alloc] initWithSeconds:seconds nanoseconds:nanos];
|
||||
}
|
||||
|
||||
+ (instancetype)timestampWithSeconds:(int64_t)seconds nanoseconds:(int32_t)nanoseconds {
|
||||
return [[FIRTimestamp alloc] initWithSeconds:seconds nanoseconds:nanoseconds];
|
||||
}
|
||||
|
||||
+ (instancetype)timestamp {
|
||||
return [FIRTimestamp timestampWithDate:[NSDate date]];
|
||||
}
|
||||
|
||||
- (instancetype)initWithSeconds:(int64_t)seconds nanoseconds:(int32_t)nanoseconds {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
if (nanoseconds < 0) {
|
||||
[NSException raise:@"Invalid timestamp"
|
||||
format:@"Timestamp nanoseconds out of range: %d", nanoseconds];
|
||||
}
|
||||
if (nanoseconds >= 1e9) {
|
||||
[NSException raise:@"Invalid timestamp"
|
||||
format:@"Timestamp nanoseconds out of range: %d", nanoseconds];
|
||||
}
|
||||
// Midnight at the beginning of 1/1/1 is the earliest timestamp supported.
|
||||
if (seconds < -62135596800L) {
|
||||
[NSException raise:@"Invalid timestamp"
|
||||
format:@"Timestamp seconds out of range: %lld", seconds];
|
||||
}
|
||||
// This will break in the year 10,000.
|
||||
if (seconds >= 253402300800L) {
|
||||
[NSException raise:@"Invalid timestamp"
|
||||
format:@"Timestamp seconds out of range: %lld", seconds];
|
||||
}
|
||||
|
||||
_seconds = seconds;
|
||||
_nanoseconds = nanoseconds;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
#pragma mark - NSObject methods
|
||||
|
||||
- (BOOL)isEqual:(id)object {
|
||||
if (self == object) {
|
||||
return YES;
|
||||
}
|
||||
if (![object isKindOfClass:[FIRTimestamp class]]) {
|
||||
return NO;
|
||||
}
|
||||
return [self isEqualToTimestamp:(FIRTimestamp *)object];
|
||||
}
|
||||
|
||||
- (NSUInteger)hash {
|
||||
return (NSUInteger)((self.seconds >> 32) ^ self.seconds ^ self.nanoseconds);
|
||||
}
|
||||
|
||||
- (NSString *)description {
|
||||
return [NSString stringWithFormat:@"<FIRTimestamp: seconds=%lld nanoseconds=%d>", self.seconds,
|
||||
self.nanoseconds];
|
||||
}
|
||||
|
||||
/** Implements NSCopying without actually copying because timestamps are immutable. */
|
||||
- (id)copyWithZone:(__unused NSZone *_Nullable)zone {
|
||||
return self;
|
||||
}
|
||||
|
||||
#pragma mark - Public methods
|
||||
|
||||
- (NSDate *)dateValue {
|
||||
NSTimeInterval interval = (NSTimeInterval)self.seconds + ((NSTimeInterval)self.nanoseconds) / 1e9;
|
||||
return [NSDate dateWithTimeIntervalSince1970:interval];
|
||||
}
|
||||
|
||||
- (NSComparisonResult)compare:(FIRTimestamp *)other {
|
||||
if (self.seconds < other.seconds) {
|
||||
return NSOrderedAscending;
|
||||
} else if (self.seconds > other.seconds) {
|
||||
return NSOrderedDescending;
|
||||
}
|
||||
|
||||
if (self.nanoseconds < other.nanoseconds) {
|
||||
return NSOrderedAscending;
|
||||
} else if (self.nanoseconds > other.nanoseconds) {
|
||||
return NSOrderedDescending;
|
||||
}
|
||||
return NSOrderedSame;
|
||||
}
|
||||
|
||||
#pragma mark - Private methods
|
||||
|
||||
- (BOOL)isEqualToTimestamp:(FIRTimestamp *)other {
|
||||
return [self compare:other] == NSOrderedSame;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
48
Pods/FirebaseFirestoreInternal/Firestore/Source/API/FIRVectorValue.m
generated
Normal file
48
Pods/FirebaseFirestoreInternal/Firestore/Source/API/FIRVectorValue.m
generated
Normal file
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright 2024 Google LLC
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#include "Firestore/Source/Public/FirebaseFirestore/FIRVectorValue.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@implementation FIRVectorValue
|
||||
|
||||
- (instancetype)initWithArray:(NSArray<NSNumber *> *)array {
|
||||
if (self = [super init]) {
|
||||
_array = [array valueForKey:@"doubleValue"];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (BOOL)isEqual:(nullable id)object {
|
||||
if (self == object) {
|
||||
return YES;
|
||||
}
|
||||
|
||||
if (![object isKindOfClass:[FIRVectorValue class]]) {
|
||||
return NO;
|
||||
}
|
||||
|
||||
FIRVectorValue *otherVector = ((FIRVectorValue *)object);
|
||||
|
||||
return [self.array isEqualToArray:otherVector.array];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
@@ -22,14 +22,13 @@
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
#import "FirebaseAuth/Interop/FIRAuthInterop.h"
|
||||
#import "FirebaseAuth/Interop/Public/FirebaseAuthInterop/FIRAuthInterop.h"
|
||||
#import "FirebaseCore/Extension/FIRAppInternal.h"
|
||||
#import "FirebaseCore/Extension/FIRComponent.h"
|
||||
#import "FirebaseCore/Extension/FIRComponentContainer.h"
|
||||
#import "FirebaseCore/Extension/FIRComponentType.h"
|
||||
#import "FirebaseCore/Extension/FIRDependency.h"
|
||||
#import "FirebaseCore/Extension/FIRLibrary.h"
|
||||
#import "FirebaseCore/Extension/FIROptionsInternal.h"
|
||||
#import "FirebaseCore/Sources/FIROptionsInternal.h"
|
||||
#import "Firestore/Source/API/FIRFirestore+Internal.h"
|
||||
|
||||
#include "Firestore/core/include/firebase/firestore/firestore_version.h"
|
||||
@@ -160,12 +159,9 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
#pragma mark - Interoperability
|
||||
|
||||
+ (NSArray<FIRComponent *> *)componentsToRegister {
|
||||
FIRDependency *auth = [FIRDependency dependencyWithProtocol:@protocol(FIRAuthInterop)
|
||||
isRequired:NO];
|
||||
FIRComponent *firestoreProvider = [FIRComponent
|
||||
componentWithProtocol:@protocol(FSTFirestoreMultiDBProvider)
|
||||
instantiationTiming:FIRInstantiationTimingLazy
|
||||
dependencies:@[ auth ]
|
||||
creationBlock:^id _Nullable(FIRComponentContainer *container, BOOL *isCacheable) {
|
||||
FSTFirestoreComponent *multiDBComponent =
|
||||
[[FSTFirestoreComponent alloc] initWithApp:container.app];
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#import "Firestore/Source/API/FSTUserDataReader.h"
|
||||
#import <FirebaseCore/FIRTimestamp.h>
|
||||
|
||||
#include <memory>
|
||||
#include <set>
|
||||
@@ -22,8 +22,10 @@
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#import "Firestore/Source/API/FSTUserDataReader.h"
|
||||
|
||||
#import "FIRGeoPoint.h"
|
||||
#import "FIRTimestamp.h"
|
||||
#import "FIRVectorValue.h"
|
||||
|
||||
#import "Firestore/Source/API/FIRDocumentReference+Internal.h"
|
||||
#import "Firestore/Source/API/FIRFieldPath+Internal.h"
|
||||
@@ -340,6 +342,42 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
return std::move(result);
|
||||
}
|
||||
|
||||
- (Message<google_firestore_v1_Value>)parseVectorValue:(FIRVectorValue *)vectorValue
|
||||
context:(ParseContext &&)context {
|
||||
__block Message<google_firestore_v1_Value> result;
|
||||
result->which_value_type = google_firestore_v1_Value_map_value_tag;
|
||||
result->map_value = {};
|
||||
|
||||
result->map_value.fields_count = 2;
|
||||
result->map_value.fields = nanopb::MakeArray<google_firestore_v1_MapValue_FieldsEntry>(2);
|
||||
|
||||
result->map_value.fields[0].key = nanopb::CopyBytesArray(model::kTypeValueFieldKey);
|
||||
result->map_value.fields[0].value = *[self encodeStringValue:MakeString(@"__vector__")].release();
|
||||
|
||||
NSArray<NSNumber *> *vectorArray = vectorValue.array;
|
||||
|
||||
__block Message<google_firestore_v1_Value> arrayMessage;
|
||||
arrayMessage->which_value_type = google_firestore_v1_Value_array_value_tag;
|
||||
arrayMessage->array_value.values_count = CheckedSize([vectorArray count]);
|
||||
arrayMessage->array_value.values =
|
||||
nanopb::MakeArray<google_firestore_v1_Value>(arrayMessage->array_value.values_count);
|
||||
|
||||
[vectorArray enumerateObjectsUsingBlock:^(id entry, NSUInteger idx, BOOL *) {
|
||||
if (![entry isKindOfClass:[NSNumber class]]) {
|
||||
ThrowInvalidArgument("VectorValues must only contain numeric values.",
|
||||
context.FieldDescription());
|
||||
}
|
||||
|
||||
// Vector values must always use Double encoding
|
||||
arrayMessage->array_value.values[idx] = *[self encodeDouble:[entry doubleValue]].release();
|
||||
}];
|
||||
|
||||
result->map_value.fields[1].key = nanopb::CopyBytesArray(model::kVectorValueFieldKey);
|
||||
result->map_value.fields[1].value = *arrayMessage.release();
|
||||
|
||||
return std::move(result);
|
||||
}
|
||||
|
||||
- (Message<google_firestore_v1_Value>)parseArray:(NSArray<id> *)array
|
||||
context:(ParseContext &&)context {
|
||||
__block Message<google_firestore_v1_Value> result;
|
||||
@@ -528,7 +566,9 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
_databaseID.database_id(), context.FieldDescription());
|
||||
}
|
||||
return [self encodeReference:_databaseID key:reference.key];
|
||||
|
||||
} else if ([input isKindOfClass:[FIRVectorValue class]]) {
|
||||
FIRVectorValue *vector = input;
|
||||
return [self parseVectorValue:vector context:std::move(context)];
|
||||
} else {
|
||||
ThrowInvalidArgument("Unsupported type: %s%s", NSStringFromClass([input class]),
|
||||
context.FieldDescription());
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
|
||||
#include "Firestore/Protos/nanopb/google/firestore/v1/document.nanopb.h"
|
||||
#include "Firestore/Source/API/FIRDocumentReference+Internal.h"
|
||||
#include "Firestore/Source/API/FIRFieldValue+Internal.h"
|
||||
#include "Firestore/Source/API/converters.h"
|
||||
#include "Firestore/core/include/firebase/firestore/geo_point.h"
|
||||
#include "Firestore/core/include/firebase/firestore/timestamp.h"
|
||||
@@ -105,6 +106,8 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
case TypeOrder::kGeoPoint:
|
||||
return MakeFIRGeoPoint(
|
||||
GeoPoint(value.geo_point_value.latitude, value.geo_point_value.longitude));
|
||||
case TypeOrder::kVector:
|
||||
return [self convertedVector:value.map_value];
|
||||
case TypeOrder::kMaxValue:
|
||||
// It is not possible for users to construct a kMaxValue manually.
|
||||
break;
|
||||
@@ -123,6 +126,18 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
return result;
|
||||
}
|
||||
|
||||
- (FIRVectorValue *)convertedVector:(const google_firestore_v1_MapValue &)mapValue {
|
||||
for (pb_size_t i = 0; i < mapValue.fields_count; ++i) {
|
||||
absl::string_view key = MakeStringView(mapValue.fields[i].key);
|
||||
const google_firestore_v1_Value &value = mapValue.fields[i].value;
|
||||
if ((0 == key.compare(absl::string_view("value"))) &&
|
||||
value.which_value_type == google_firestore_v1_Value_array_value_tag) {
|
||||
return [FIRFieldValue vectorWithArray:[self convertedArray:value.array_value]];
|
||||
}
|
||||
}
|
||||
return [FIRFieldValue vectorWithArray:@[]];
|
||||
}
|
||||
|
||||
- (NSArray<id> *)convertedArray:(const google_firestore_v1_ArrayValue &)arrayValue {
|
||||
NSMutableArray *result = [NSMutableArray arrayWithCapacity:arrayValue.values_count];
|
||||
for (pb_size_t i = 0; i < arrayValue.values_count; ++i) {
|
||||
|
||||
@@ -14,12 +14,13 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "Firestore/Source/API/converters.h"
|
||||
#import <FirebaseCore/FIRTimestamp.h>
|
||||
|
||||
#include <utility>
|
||||
|
||||
#include "Firestore/Source/API/converters.h"
|
||||
|
||||
#import "FIRGeoPoint.h"
|
||||
#import "FIRTimestamp.h"
|
||||
|
||||
#include "Firestore/Source/API/FIRDocumentReference+Internal.h"
|
||||
#include "Firestore/core/include/firebase/firestore/geo_point.h"
|
||||
|
||||
@@ -23,6 +23,7 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
/**
|
||||
* Represents an aggregation that can be performed by Firestore.
|
||||
*/
|
||||
NS_SWIFT_SENDABLE
|
||||
NS_SWIFT_NAME(AggregateField)
|
||||
@interface FIRAggregateField : NSObject
|
||||
|
||||
|
||||
@@ -26,6 +26,7 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
/**
|
||||
* A query that calculates aggregations over an underlying query.
|
||||
*/
|
||||
NS_SWIFT_SENDABLE
|
||||
NS_SWIFT_NAME(AggregateQuery)
|
||||
@interface FIRAggregateQuery : NSObject
|
||||
|
||||
|
||||
@@ -24,6 +24,7 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
/**
|
||||
* The results of executing an `AggregateQuery`.
|
||||
*/
|
||||
NS_SWIFT_SENDABLE
|
||||
NS_SWIFT_NAME(AggregateQuerySnapshot)
|
||||
@interface FIRAggregateQuerySnapshot : NSObject
|
||||
|
||||
|
||||
@@ -26,6 +26,7 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
* A `CollectionReference` object can be used for adding documents, getting document references,
|
||||
* and querying for documents (using the methods inherited from `Query`).
|
||||
*/
|
||||
NS_SWIFT_SENDABLE
|
||||
NS_SWIFT_NAME(CollectionReference)
|
||||
@interface FIRCollectionReference : FIRQuery
|
||||
|
||||
|
||||
@@ -43,6 +43,7 @@ typedef NS_ENUM(NSInteger, FIRDocumentChangeType)
|
||||
* A `DocumentChange` represents a change to the documents matching a query. It contains the
|
||||
* document affected and the type of change that occurred (added, modified, or removed).
|
||||
*/
|
||||
NS_SWIFT_SENDABLE
|
||||
NS_SWIFT_NAME(DocumentChange)
|
||||
@interface FIRDocumentChange : NSObject
|
||||
|
||||
|
||||
@@ -39,6 +39,7 @@ typedef void (^FIRDocumentSnapshotBlock)(FIRDocumentSnapshot *_Nullable snapshot
|
||||
* may or may not exist. A `DocumentReference` can also be used to create a `CollectionReference` to
|
||||
* a subcollection.
|
||||
*/
|
||||
NS_SWIFT_SENDABLE
|
||||
NS_SWIFT_NAME(DocumentReference)
|
||||
@interface FIRDocumentReference : NSObject
|
||||
|
||||
|
||||
@@ -55,6 +55,7 @@ typedef NS_ENUM(NSInteger, FIRServerTimestampBehavior) {
|
||||
* For a `DocumentSnapshot` that points to a non-existing document, any data access will return
|
||||
* `nil`. You can use the `exists` property to explicitly verify a documents existence.
|
||||
*/
|
||||
NS_SWIFT_SENDABLE
|
||||
NS_SWIFT_NAME(DocumentSnapshot)
|
||||
@interface FIRDocumentSnapshot : NSObject
|
||||
|
||||
|
||||
@@ -23,6 +23,7 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
* (referring to a top level field in the document), or a list of field names (referring to a nested
|
||||
* field in the document).
|
||||
*/
|
||||
NS_SWIFT_SENDABLE
|
||||
NS_SWIFT_NAME(FieldPath)
|
||||
@interface FIRFieldPath : NSObject <NSCopying>
|
||||
|
||||
|
||||
@@ -17,10 +17,12 @@
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
@class FIRVectorValue;
|
||||
|
||||
/**
|
||||
* Sentinel values that can be used when writing document fields with `setData()` or `updateData()`.
|
||||
*/
|
||||
NS_SWIFT_SENDABLE
|
||||
NS_SWIFT_NAME(FieldValue)
|
||||
@interface FIRFieldValue : NSObject
|
||||
|
||||
@@ -90,6 +92,14 @@ NS_SWIFT_NAME(FieldValue)
|
||||
*/
|
||||
+ (instancetype)fieldValueForIntegerIncrement:(int64_t)l NS_SWIFT_NAME(increment(_:));
|
||||
|
||||
/**
|
||||
* Creates a new `VectorValue` constructed with a copy of the given array of NSNumbers.
|
||||
*
|
||||
* @param array Create a `VectorValue` instance with a copy of this array of NSNumbers.
|
||||
* @return A new `VectorValue` constructed with a copy of the given array of NSNumbers.
|
||||
*/
|
||||
+ (FIRVectorValue *)vectorWithArray:(NSArray<NSNumber *> *)array NS_REFINED_FOR_SWIFT;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
@@ -24,6 +24,7 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
* A Filter represents a restriction on one or more field values and can be used to refine
|
||||
* the results of a Query.
|
||||
*/
|
||||
NS_SWIFT_SENDABLE
|
||||
NS_SWIFT_NAME(Filter)
|
||||
@interface FIRFilter : NSObject
|
||||
|
||||
|
||||
@@ -25,6 +25,7 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
* Latitude values are in the range of [-90, 90].
|
||||
* Longitude values are in the range of [-180, 180].
|
||||
*/
|
||||
NS_SWIFT_SENDABLE
|
||||
NS_SWIFT_NAME(GeoPoint)
|
||||
@interface FIRGeoPoint : NSObject <NSCopying>
|
||||
|
||||
|
||||
@@ -36,6 +36,7 @@ typedef NS_ENUM(NSInteger, FIRLoadBundleTaskState) {
|
||||
|
||||
/** Represents a progress update or a final state from loading bundles. */
|
||||
NS_SWIFT_NAME(LoadBundleTaskProgress)
|
||||
NS_SWIFT_SENDABLE
|
||||
@interface FIRLoadBundleTaskProgress : NSObject
|
||||
|
||||
/** How many documents have been loaded. */
|
||||
|
||||
@@ -44,14 +44,14 @@ NS_SWIFT_NAME(PersistentCacheSettings)
|
||||
/**
|
||||
* Creates `PersistentCacheSettings` with default cache size: 100MB.
|
||||
*
|
||||
* The cache size is not a hard limit, but a target for the SDK's gabarge collector to work towards.
|
||||
* The cache size is not a hard limit, but a target for the SDK's garbage collector to work towards.
|
||||
*/
|
||||
- (instancetype)init;
|
||||
|
||||
/**
|
||||
* Creates `PersistentCacheSettings` with a custom cache size in bytes.
|
||||
*
|
||||
* The cache size is not a hard limit, but a target for the SDK's gabarge collector to work towards.
|
||||
* The cache size is not a hard limit, but a target for the SDK's garbage collector to work towards.
|
||||
*/
|
||||
- (instancetype)initWithSizeBytes:(NSNumber *)size;
|
||||
|
||||
@@ -132,7 +132,7 @@ NS_SWIFT_NAME(MemoryCacheSettings)
|
||||
|
||||
/**
|
||||
* Creates an instance of `MemoryCacheSettings` with given `MemoryGarbageCollectorSettings` to
|
||||
* custom the gabarge collector.
|
||||
* custom the garbage collector.
|
||||
*/
|
||||
- (instancetype)initWithGarbageCollectorSettings:
|
||||
(id<FIRMemoryGarbageCollectorSettings, NSObject>)settings;
|
||||
|
||||
@@ -41,6 +41,7 @@ typedef void (^FIRQuerySnapshotBlock)(FIRQuerySnapshot *_Nullable snapshot,
|
||||
* A `Query` refers to a query which you can read or listen to. You can also construct
|
||||
* refined `Query` objects by adding filters and ordering.
|
||||
*/
|
||||
NS_SWIFT_SENDABLE
|
||||
NS_SWIFT_NAME(Query)
|
||||
@interface FIRQuery : NSObject
|
||||
/** :nodoc: */
|
||||
|
||||
@@ -28,6 +28,7 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
* using the `documents` property and its size can be inspected with `isEmpty` and
|
||||
* `count`.
|
||||
*/
|
||||
NS_SWIFT_SENDABLE
|
||||
NS_SWIFT_NAME(QuerySnapshot)
|
||||
@interface FIRQuerySnapshot : NSObject
|
||||
|
||||
|
||||
@@ -44,6 +44,7 @@ typedef NS_ENUM(NSUInteger, FIRListenSource) {
|
||||
* of this class control settings like whether metadata-only changes trigger events and the
|
||||
* preferred data source.
|
||||
*/
|
||||
NS_SWIFT_SENDABLE
|
||||
NS_SWIFT_NAME(SnapshotListenOptions)
|
||||
@interface FIRSnapshotListenOptions : NSObject
|
||||
|
||||
@@ -61,7 +62,7 @@ NS_SWIFT_NAME(SnapshotListenOptions)
|
||||
- (instancetype)init NS_DESIGNATED_INITIALIZER;
|
||||
|
||||
/**
|
||||
* Creates and returns a new `SnapshotListenOptions` object with with all properties of the current
|
||||
* Creates and returns a new `SnapshotListenOptions` object with all properties of the current
|
||||
* `SnapshotListenOptions` object plus the new property specifying whether metadata-only changes
|
||||
* should trigger snapshot events
|
||||
*
|
||||
@@ -70,7 +71,7 @@ NS_SWIFT_NAME(SnapshotListenOptions)
|
||||
- (FIRSnapshotListenOptions *)optionsWithIncludeMetadataChanges:(BOOL)includeMetadataChanges;
|
||||
|
||||
/**
|
||||
* Creates and returns a new `SnapshotListenOptions` object with with all properties of the current
|
||||
* Creates and returns a new `SnapshotListenOptions` object with all properties of the current
|
||||
* `SnapshotListenOptions` object plus the new property specifying the source that the snapshot
|
||||
* listener listens to.
|
||||
*
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/** Metadata about a snapshot, describing the state of the snapshot. */
|
||||
NS_SWIFT_SENDABLE
|
||||
NS_SWIFT_NAME(SnapshotMetadata)
|
||||
@interface FIRSnapshotMetadata : NSObject
|
||||
|
||||
|
||||
@@ -1,89 +0,0 @@
|
||||
/*
|
||||
* Copyright 2018 Google
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/**
|
||||
* A Timestamp represents a point in time independent of any time zone or calendar, represented as
|
||||
* seconds and fractions of seconds at nanosecond resolution in UTC Epoch time. It is encoded using
|
||||
* the Proleptic Gregorian Calendar which extends the Gregorian calendar backwards to year one. It
|
||||
* is encoded assuming all minutes are 60 seconds long, i.e. leap seconds are "smeared" so that no
|
||||
* leap second table is needed for interpretation. Range is from 0001-01-01T00:00:00Z to
|
||||
* 9999-12-31T23:59:59.999999999Z. By restricting to that range, we ensure that we can convert to
|
||||
* and from RFC 3339 date strings.
|
||||
*
|
||||
* @see https://github.com/google/protobuf/blob/main/src/google/protobuf/timestamp.proto for the
|
||||
* reference timestamp definition.
|
||||
*/
|
||||
NS_SWIFT_NAME(Timestamp)
|
||||
@interface FIRTimestamp : NSObject <NSCopying>
|
||||
|
||||
/** :nodoc: */
|
||||
- (instancetype)init NS_UNAVAILABLE;
|
||||
|
||||
/**
|
||||
* Creates a new timestamp.
|
||||
*
|
||||
* @param seconds the number of seconds since epoch.
|
||||
* @param nanoseconds the number of nanoseconds after the seconds.
|
||||
*/
|
||||
- (instancetype)initWithSeconds:(int64_t)seconds
|
||||
nanoseconds:(int32_t)nanoseconds NS_DESIGNATED_INITIALIZER;
|
||||
|
||||
/**
|
||||
* Creates a new timestamp.
|
||||
*
|
||||
* @param seconds the number of seconds since epoch.
|
||||
* @param nanoseconds the number of nanoseconds after the seconds.
|
||||
*/
|
||||
+ (instancetype)timestampWithSeconds:(int64_t)seconds nanoseconds:(int32_t)nanoseconds;
|
||||
|
||||
/** Creates a new timestamp from the given date. */
|
||||
+ (instancetype)timestampWithDate:(NSDate *)date;
|
||||
|
||||
/** Creates a new timestamp with the current date / time. */
|
||||
+ (instancetype)timestamp;
|
||||
|
||||
/** Returns a new `Date` corresponding to this timestamp. This may lose precision. */
|
||||
- (NSDate *)dateValue;
|
||||
|
||||
/**
|
||||
* Returns the result of comparing the receiver with another timestamp.
|
||||
* @param other the other timestamp to compare.
|
||||
* @return `orderedAscending` if `other` is chronologically following self,
|
||||
* `orderedDescending` if `other` is chronologically preceding self,
|
||||
* `orderedSame` otherwise.
|
||||
*/
|
||||
- (NSComparisonResult)compare:(FIRTimestamp *)other;
|
||||
|
||||
/**
|
||||
* Represents seconds of UTC time since Unix epoch 1970-01-01T00:00:00Z.
|
||||
* Must be from 0001-01-01T00:00:00Z to 9999-12-31T23:59:59Z inclusive.
|
||||
*/
|
||||
@property(nonatomic, assign, readonly) int64_t seconds;
|
||||
|
||||
/**
|
||||
* Non-negative fractions of a second at nanosecond resolution. Negative second values with
|
||||
* fractions must still have non-negative nanos values that count forward in time.
|
||||
* Must be from 0 to 999,999,999 inclusive.
|
||||
*/
|
||||
@property(nonatomic, assign, readonly) int32_t nanoseconds;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
42
Pods/FirebaseFirestoreInternal/Firestore/Source/Public/FirebaseFirestore/FIRVectorValue.h
generated
Normal file
42
Pods/FirebaseFirestoreInternal/Firestore/Source/Public/FirebaseFirestore/FIRVectorValue.h
generated
Normal file
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright 2024 Google LLC
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/**
|
||||
* Represents a vector type in Firestore documents.
|
||||
*/
|
||||
NS_SWIFT_SENDABLE
|
||||
NS_SWIFT_NAME(VectorValue)
|
||||
@interface FIRVectorValue : NSObject
|
||||
|
||||
/** Returns a copy of the raw number array that represents the vector. */
|
||||
@property(atomic, readonly) NSArray<NSNumber *> *array NS_REFINED_FOR_SWIFT;
|
||||
|
||||
/** :nodoc: */
|
||||
- (instancetype)init NS_UNAVAILABLE;
|
||||
|
||||
/**
|
||||
* Creates a `VectorValue` constructed with a copy of the given array of NSNumbrers.
|
||||
* @param array An array of NSNumbers that represents a vector.
|
||||
*/
|
||||
- (instancetype)initWithArray:(NSArray<NSNumber *> *)array NS_REFINED_FOR_SWIFT;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
@@ -36,7 +36,6 @@
|
||||
#import "FIRQuerySnapshot.h"
|
||||
#import "FIRSnapshotListenOptions.h"
|
||||
#import "FIRSnapshotMetadata.h"
|
||||
#import "FIRTimestamp.h"
|
||||
#import "FIRTransaction.h"
|
||||
#import "FIRTransactionOptions.h"
|
||||
#import "FIRWriteBatch.h"
|
||||
|
||||
@@ -19,13 +19,11 @@
|
||||
|
||||
#include <cstdint>
|
||||
#include <ctime>
|
||||
|
||||
#include <chrono>
|
||||
#include <iosfwd>
|
||||
#include <string>
|
||||
|
||||
#if !defined(_STLPORT_VERSION)
|
||||
#include <chrono> // NOLINT(build/c++11)
|
||||
#endif // !defined(_STLPORT_VERSION)
|
||||
|
||||
namespace firebase {
|
||||
|
||||
/**
|
||||
@@ -117,7 +115,6 @@ class Timestamp {
|
||||
*/
|
||||
static Timestamp FromTimeT(time_t seconds_since_unix_epoch);
|
||||
|
||||
#if !defined(_STLPORT_VERSION)
|
||||
/**
|
||||
* Converts `std::chrono::time_point` to a `Timestamp`.
|
||||
*
|
||||
@@ -145,7 +142,6 @@ class Timestamp {
|
||||
template <typename Clock = std::chrono::system_clock,
|
||||
typename Duration = std::chrono::microseconds>
|
||||
std::chrono::time_point<Clock, Duration> ToTimePoint() const;
|
||||
#endif // !defined(_STLPORT_VERSION)
|
||||
|
||||
/**
|
||||
* Returns a string representation of this `Timestamp` for logging/debugging
|
||||
@@ -205,8 +201,6 @@ inline bool operator==(const Timestamp& lhs, const Timestamp& rhs) {
|
||||
return !(lhs != rhs);
|
||||
}
|
||||
|
||||
#if !defined(_STLPORT_VERSION)
|
||||
|
||||
// Make sure the header compiles even when included after `<windows.h>` without
|
||||
// `NOMINMAX` defined. `push/pop_macro` pragmas are supported by Visual Studio
|
||||
// as well as Clang and GCC.
|
||||
@@ -239,8 +233,6 @@ std::chrono::time_point<Clock, Duration> Timestamp::ToTimePoint() const {
|
||||
#pragma pop_macro("max")
|
||||
#pragma pop_macro("min")
|
||||
|
||||
#endif // !defined(_STLPORT_VERSION)
|
||||
|
||||
} // namespace firebase
|
||||
|
||||
#endif // FIRESTORE_CORE_INCLUDE_FIREBASE_FIRESTORE_TIMESTAMP_H_
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
#include "Firestore/core/src/api/document_reference.h"
|
||||
|
||||
#include <future> // NOLINT(build/c++11)
|
||||
#include <future>
|
||||
#include <memory>
|
||||
|
||||
#include "Firestore/core/src/api/collection_reference.h"
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
#define FIRESTORE_CORE_SRC_API_FIRESTORE_H_
|
||||
|
||||
#include <memory>
|
||||
#include <mutex> // NOLINT(build/c++11)
|
||||
#include <mutex>
|
||||
#include <string>
|
||||
|
||||
#include "Firestore/core/src/api/api_fwd.h"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2024 Google
|
||||
* Copyright 2024 Google LLC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
#include "Firestore/core/src/api/load_bundle_task.h"
|
||||
|
||||
#include <mutex> // NOLINT(build/c++11)
|
||||
#include <mutex>
|
||||
#include <utility>
|
||||
|
||||
#include "Firestore/core/src/util/autoid.h"
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
#include <cstdint>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <mutex> // NOLINT(build/c++11)
|
||||
#include <mutex>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
#include "Firestore/core/src/api/query_core.h"
|
||||
|
||||
#include <future> // NOLINT(build/c++11)
|
||||
#include <future>
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
@@ -69,15 +69,15 @@ std::unique_ptr<LocalCacheSettings> Settings::CopyCacheSettings(
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
std::unique_ptr<MemoryGargabeCollectorSettings>
|
||||
std::unique_ptr<MemoryGarbageCollectorSettings>
|
||||
MemoryCacheSettings::CopyMemoryGcSettings(
|
||||
const MemoryGargabeCollectorSettings& settings) {
|
||||
const MemoryGarbageCollectorSettings& settings) {
|
||||
if (settings.kind() ==
|
||||
MemoryGargabeCollectorSettings::MemoryGcKind::kEagerGc) {
|
||||
MemoryGarbageCollectorSettings::MemoryGcKind::kEagerGc) {
|
||||
return absl::make_unique<MemoryEagerGcSettings>(
|
||||
static_cast<const MemoryEagerGcSettings&>(settings));
|
||||
} else if (settings.kind() ==
|
||||
MemoryGargabeCollectorSettings::MemoryGcKind::kLruGc) {
|
||||
MemoryGarbageCollectorSettings::MemoryGcKind::kLruGc) {
|
||||
return absl::make_unique<MemoryLruGcSettings>(
|
||||
static_cast<const MemoryLruGcSettings&>(settings));
|
||||
}
|
||||
@@ -107,7 +107,7 @@ MemoryLruGcSettings MemoryLruGcSettings::WithSizeBytes(int64_t size) const {
|
||||
}
|
||||
|
||||
MemoryCacheSettings MemoryCacheSettings::WithMemoryGarbageCollectorSettings(
|
||||
const MemoryGargabeCollectorSettings& settings) {
|
||||
const MemoryGarbageCollectorSettings& settings) {
|
||||
MemoryCacheSettings new_settings(*this);
|
||||
new_settings.settings_ = CopyMemoryGcSettings(settings);
|
||||
return new_settings;
|
||||
@@ -157,18 +157,18 @@ bool operator==(const LocalCacheSettings& lhs, const LocalCacheSettings& rhs) {
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
bool operator==(const MemoryGargabeCollectorSettings& lhs,
|
||||
const MemoryGargabeCollectorSettings& rhs) {
|
||||
bool operator==(const MemoryGarbageCollectorSettings& lhs,
|
||||
const MemoryGarbageCollectorSettings& rhs) {
|
||||
if (lhs.kind() != rhs.kind()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (lhs.kind() == MemoryGargabeCollectorSettings::MemoryGcKind::kEagerGc) {
|
||||
if (lhs.kind() == MemoryGarbageCollectorSettings::MemoryGcKind::kEagerGc) {
|
||||
return static_cast<const MemoryEagerGcSettings&>(lhs) ==
|
||||
static_cast<const MemoryEagerGcSettings&>(rhs);
|
||||
}
|
||||
|
||||
if (lhs.kind() == MemoryGargabeCollectorSettings::MemoryGcKind::kLruGc) {
|
||||
if (lhs.kind() == MemoryGarbageCollectorSettings::MemoryGcKind::kLruGc) {
|
||||
return static_cast<const MemoryLruGcSettings&>(lhs) ==
|
||||
static_cast<const MemoryLruGcSettings&>(rhs);
|
||||
}
|
||||
@@ -268,7 +268,7 @@ int64_t Settings::cache_size_bytes() const {
|
||||
auto* memory_cache_settings =
|
||||
static_cast<MemoryCacheSettings*>(cache_settings_.get());
|
||||
if (memory_cache_settings->gc_settings().kind() ==
|
||||
MemoryGargabeCollectorSettings::MemoryGcKind::kLruGc) {
|
||||
MemoryGarbageCollectorSettings::MemoryGcKind::kLruGc) {
|
||||
return static_cast<const MemoryLruGcSettings&>(
|
||||
memory_cache_settings->gc_settings())
|
||||
.size_bytes();
|
||||
@@ -289,14 +289,14 @@ bool Settings::gc_enabled() const {
|
||||
auto* memory_cache_settings =
|
||||
static_cast<MemoryCacheSettings*>(cache_settings_.get());
|
||||
return memory_cache_settings->gc_settings().kind() ==
|
||||
MemoryGargabeCollectorSettings::MemoryGcKind::kLruGc &&
|
||||
MemoryGarbageCollectorSettings::MemoryGcKind::kLruGc &&
|
||||
static_cast<const MemoryLruGcSettings&>(
|
||||
memory_cache_settings->gc_settings())
|
||||
.size_bytes() != CacheSizeUnlimited;
|
||||
}
|
||||
}
|
||||
|
||||
return persistence_enabled_ && cache_size_bytes_ != CacheSizeUnlimited;
|
||||
return cache_size_bytes_ != CacheSizeUnlimited;
|
||||
}
|
||||
|
||||
const LocalCacheSettings* Settings::local_cache_settings() const {
|
||||
|
||||
@@ -97,7 +97,7 @@ class LocalCacheSettings {
|
||||
friend class Settings;
|
||||
|
||||
public:
|
||||
enum class Kind { kMemory, kPersistent };
|
||||
enum class Kind { kMemory = 1, kPersistent };
|
||||
virtual ~LocalCacheSettings() = default;
|
||||
friend bool operator==(const LocalCacheSettings& lhs,
|
||||
const LocalCacheSettings& rhs);
|
||||
@@ -133,12 +133,13 @@ class PersistentCacheSettings : public LocalCacheSettings {
|
||||
int64_t size_bytes_;
|
||||
};
|
||||
|
||||
class MemoryGargabeCollectorSettings {
|
||||
class MemoryGarbageCollectorSettings {
|
||||
public:
|
||||
enum class MemoryGcKind { kEagerGc, kLruGc };
|
||||
virtual ~MemoryGargabeCollectorSettings() = default;
|
||||
friend bool operator==(const MemoryGargabeCollectorSettings& lhs,
|
||||
const MemoryGargabeCollectorSettings& rhs);
|
||||
enum class MemoryGcKind { kEagerGc = 1, kLruGc };
|
||||
virtual ~MemoryGarbageCollectorSettings() = default;
|
||||
friend bool operator==(const MemoryGarbageCollectorSettings& lhs,
|
||||
const MemoryGarbageCollectorSettings& rhs);
|
||||
|
||||
virtual size_t Hash() const = 0;
|
||||
|
||||
MemoryGcKind kind() const {
|
||||
@@ -146,25 +147,25 @@ class MemoryGargabeCollectorSettings {
|
||||
}
|
||||
|
||||
protected:
|
||||
explicit MemoryGargabeCollectorSettings(MemoryGcKind kind) : kind_(kind) {
|
||||
explicit MemoryGarbageCollectorSettings(MemoryGcKind kind) : kind_(kind) {
|
||||
}
|
||||
MemoryGcKind kind_;
|
||||
};
|
||||
|
||||
class MemoryEagerGcSettings : public MemoryGargabeCollectorSettings {
|
||||
class MemoryEagerGcSettings : public MemoryGarbageCollectorSettings {
|
||||
public:
|
||||
MemoryEagerGcSettings()
|
||||
: MemoryGargabeCollectorSettings(
|
||||
MemoryGargabeCollectorSettings::MemoryGcKind::kEagerGc) {
|
||||
: MemoryGarbageCollectorSettings(
|
||||
MemoryGarbageCollectorSettings::MemoryGcKind::kEagerGc) {
|
||||
}
|
||||
size_t Hash() const override;
|
||||
};
|
||||
|
||||
class MemoryLruGcSettings : public MemoryGargabeCollectorSettings {
|
||||
class MemoryLruGcSettings : public MemoryGarbageCollectorSettings {
|
||||
public:
|
||||
MemoryLruGcSettings()
|
||||
: MemoryGargabeCollectorSettings(
|
||||
MemoryGargabeCollectorSettings::MemoryGcKind::kLruGc),
|
||||
: MemoryGarbageCollectorSettings(
|
||||
MemoryGarbageCollectorSettings::MemoryGcKind::kLruGc),
|
||||
size_bytes_(Settings::DefaultCacheSizeBytes) {
|
||||
}
|
||||
|
||||
@@ -185,7 +186,7 @@ class MemoryCacheSettings : public LocalCacheSettings {
|
||||
public:
|
||||
MemoryCacheSettings()
|
||||
: LocalCacheSettings(LocalCacheSettings::Kind::kMemory),
|
||||
settings_(absl::make_unique<MemoryEagerGcSettings>()) {
|
||||
settings_(absl::make_unique<MemoryLruGcSettings>()) {
|
||||
}
|
||||
MemoryCacheSettings(const MemoryCacheSettings& other);
|
||||
MemoryCacheSettings& operator=(const MemoryCacheSettings& other);
|
||||
@@ -193,17 +194,17 @@ class MemoryCacheSettings : public LocalCacheSettings {
|
||||
size_t Hash() const override;
|
||||
|
||||
MemoryCacheSettings WithMemoryGarbageCollectorSettings(
|
||||
const MemoryGargabeCollectorSettings& settings);
|
||||
const MemoryGarbageCollectorSettings& settings);
|
||||
|
||||
const MemoryGargabeCollectorSettings& gc_settings() const {
|
||||
const MemoryGarbageCollectorSettings& gc_settings() const {
|
||||
return *settings_;
|
||||
}
|
||||
|
||||
private:
|
||||
static std::unique_ptr<MemoryGargabeCollectorSettings> CopyMemoryGcSettings(
|
||||
const MemoryGargabeCollectorSettings& settings);
|
||||
static std::unique_ptr<MemoryGarbageCollectorSettings> CopyMemoryGcSettings(
|
||||
const MemoryGarbageCollectorSettings& settings);
|
||||
|
||||
std::unique_ptr<MemoryGargabeCollectorSettings> settings_;
|
||||
std::unique_ptr<MemoryGarbageCollectorSettings> settings_;
|
||||
};
|
||||
|
||||
bool operator!=(const Settings& lhs, const Settings& rhs);
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
#include "Firestore/core/src/core/composite_filter.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
|
||||
#include "Firestore/core/src/core/field_filter.h"
|
||||
@@ -141,16 +142,14 @@ const FieldFilter* CompositeFilter::Rep::FindFirstMatchingFilter(
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const std::vector<FieldFilter>& CompositeFilter::Rep::GetFlattenedFilters()
|
||||
const {
|
||||
return memoized_flattened_filters_->memoize([&]() {
|
||||
std::vector<FieldFilter> flattened_filters;
|
||||
for (const auto& filter : filters())
|
||||
std::copy(filter.GetFlattenedFilters().begin(),
|
||||
filter.GetFlattenedFilters().end(),
|
||||
std::back_inserter(flattened_filters));
|
||||
return flattened_filters;
|
||||
});
|
||||
std::shared_ptr<std::vector<FieldFilter>>
|
||||
CompositeFilter::Rep::CalculateFlattenedFilters() const {
|
||||
auto flattened_filters = std::make_shared<std::vector<FieldFilter>>();
|
||||
for (const auto& filter : filters())
|
||||
std::copy(filter.GetFlattenedFilters().begin(),
|
||||
filter.GetFlattenedFilters().end(),
|
||||
std::back_inserter(*flattened_filters));
|
||||
return flattened_filters;
|
||||
}
|
||||
|
||||
} // namespace core
|
||||
|
||||
@@ -138,7 +138,8 @@ class CompositeFilter : public Filter {
|
||||
return filters_.empty();
|
||||
}
|
||||
|
||||
const std::vector<FieldFilter>& GetFlattenedFilters() const override;
|
||||
std::shared_ptr<std::vector<FieldFilter>> CalculateFlattenedFilters()
|
||||
const override;
|
||||
|
||||
std::vector<Filter> GetFilters() const override {
|
||||
return filters();
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
#define FIRESTORE_CORE_SRC_CORE_EVENT_LISTENER_H_
|
||||
|
||||
#include <memory>
|
||||
#include <mutex> // NOLINT(build/c++11)
|
||||
#include <mutex>
|
||||
#include <utility>
|
||||
|
||||
#include "Firestore/core/src/util/executor.h"
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
#include "Firestore/core/src/core/field_filter.h"
|
||||
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
|
||||
#include "Firestore/core/src/core/array_contains_any_filter.h"
|
||||
@@ -122,12 +123,12 @@ FieldFilter::FieldFilter(std::shared_ptr<const Filter::Rep> rep)
|
||||
: Filter(std::move(rep)) {
|
||||
}
|
||||
|
||||
const std::vector<FieldFilter>& FieldFilter::Rep::GetFlattenedFilters() const {
|
||||
std::shared_ptr<std::vector<FieldFilter>>
|
||||
FieldFilter::Rep::CalculateFlattenedFilters() const {
|
||||
// This is already a field filter, so we return a vector of size one.
|
||||
return memoized_flattened_filters_->memoize([&]() {
|
||||
return std::vector<FieldFilter>{
|
||||
FieldFilter(std::make_shared<const Rep>(*this))};
|
||||
});
|
||||
auto filters = std::make_shared<std::vector<FieldFilter>>();
|
||||
filters->push_back(FieldFilter(std::make_shared<const Rep>(*this)));
|
||||
return filters;
|
||||
}
|
||||
|
||||
std::vector<Filter> FieldFilter::Rep::GetFilters() const {
|
||||
@@ -156,7 +157,8 @@ bool FieldFilter::Rep::Matches(const model::Document& doc) const {
|
||||
|
||||
// Types do not have to match in NotEqual filters.
|
||||
if (op_ == Operator::NotEqual) {
|
||||
return MatchesComparison(Compare(lhs, *value_rhs_));
|
||||
return lhs.which_value_type != google_firestore_v1_Value_null_value_tag &&
|
||||
MatchesComparison(Compare(lhs, *value_rhs_));
|
||||
}
|
||||
|
||||
// Only compare types with matching backend order (such as double and int).
|
||||
|
||||
@@ -117,8 +117,6 @@ class FieldFilter : public Filter {
|
||||
return false;
|
||||
}
|
||||
|
||||
const std::vector<FieldFilter>& GetFlattenedFilters() const override;
|
||||
|
||||
std::vector<Filter> GetFilters() const override;
|
||||
|
||||
protected:
|
||||
@@ -140,6 +138,9 @@ class FieldFilter : public Filter {
|
||||
|
||||
bool MatchesComparison(util::ComparisonResult comparison) const;
|
||||
|
||||
std::shared_ptr<std::vector<FieldFilter>> CalculateFlattenedFilters()
|
||||
const override;
|
||||
|
||||
private:
|
||||
friend class FieldFilter;
|
||||
|
||||
|
||||
@@ -35,12 +35,6 @@ std::ostream& operator<<(std::ostream& os, const Filter& filter) {
|
||||
return os << filter.ToString();
|
||||
}
|
||||
|
||||
Filter::Rep::Rep()
|
||||
: memoized_flattened_filters_(
|
||||
std::make_shared<
|
||||
util::ThreadSafeMemoizer<std::vector<FieldFilter>>>()) {
|
||||
}
|
||||
|
||||
} // namespace core
|
||||
} // namespace firestore
|
||||
} // namespace firebase
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
#ifndef FIRESTORE_CORE_SRC_CORE_FILTER_H_
|
||||
#define FIRESTORE_CORE_SRC_CORE_FILTER_H_
|
||||
|
||||
#include <functional>
|
||||
#include <iosfwd>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
@@ -114,7 +115,7 @@ class Filter {
|
||||
protected:
|
||||
class Rep {
|
||||
public:
|
||||
Rep();
|
||||
Rep() = default;
|
||||
|
||||
virtual ~Rep() = default;
|
||||
|
||||
@@ -147,20 +148,23 @@ class Filter {
|
||||
|
||||
virtual bool IsEmpty() const = 0;
|
||||
|
||||
virtual const std::vector<FieldFilter>& GetFlattenedFilters() const = 0;
|
||||
virtual const std::vector<FieldFilter>& GetFlattenedFilters() const {
|
||||
const auto func = std::bind(&Rep::CalculateFlattenedFilters, this);
|
||||
return memoized_flattened_filters_.value(func);
|
||||
}
|
||||
|
||||
virtual std::vector<Filter> GetFilters() const = 0;
|
||||
|
||||
protected:
|
||||
virtual std::shared_ptr<std::vector<FieldFilter>>
|
||||
CalculateFlattenedFilters() const = 0;
|
||||
|
||||
private:
|
||||
/**
|
||||
* Memoized list of all field filters that can be found by
|
||||
* traversing the tree of filters contained in this composite filter.
|
||||
*
|
||||
* Use a `std::shared_ptr<ThreadSafeMemoizer>` rather than using
|
||||
* `ThreadSafeMemoizer` directly so that this class is copyable
|
||||
* (`ThreadSafeMemoizer` is not copyable because of its `std::once_flag`
|
||||
* member variable, which is not copyable).
|
||||
*/
|
||||
mutable std::shared_ptr<util::ThreadSafeMemoizer<std::vector<FieldFilter>>>
|
||||
mutable util::ThreadSafeMemoizer<const std::vector<FieldFilter>>
|
||||
memoized_flattened_filters_;
|
||||
};
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
#include "Firestore/core/src/core/firestore_client.h"
|
||||
|
||||
#include <functional>
|
||||
#include <future> // NOLINT(build/c++11)
|
||||
#include <future>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
@@ -62,7 +62,10 @@ bool NotInFilter::Rep::Matches(const Document& doc) const {
|
||||
return false;
|
||||
}
|
||||
absl::optional<google_firestore_v1_Value> maybe_lhs = doc->field(field());
|
||||
return maybe_lhs && !Contains(array_value, *maybe_lhs);
|
||||
return maybe_lhs &&
|
||||
maybe_lhs->which_value_type !=
|
||||
google_firestore_v1_Value_null_value_tag &&
|
||||
!Contains(array_value, *maybe_lhs);
|
||||
}
|
||||
|
||||
} // namespace core
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
#include "Firestore/core/src/core/query.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <memory>
|
||||
#include <ostream>
|
||||
|
||||
#include "Firestore/core/src/core/bound.h"
|
||||
@@ -91,44 +92,42 @@ absl::optional<Operator> Query::FindOpInsideFilters(
|
||||
return absl::nullopt;
|
||||
}
|
||||
|
||||
const std::vector<OrderBy>& Query::normalized_order_bys() const {
|
||||
return memoized_normalized_order_bys_->memoize([&]() {
|
||||
// Any explicit order by fields should be added as is.
|
||||
std::vector<OrderBy> result = explicit_order_bys_;
|
||||
std::set<FieldPath> fieldsNormalized;
|
||||
for (const OrderBy& order_by : explicit_order_bys_) {
|
||||
fieldsNormalized.insert(order_by.field());
|
||||
std::shared_ptr<const std::vector<OrderBy>> Query::CalculateNormalizedOrderBys()
|
||||
const {
|
||||
// Any explicit order by fields should be added as is.
|
||||
auto result = std::make_shared<std::vector<OrderBy>>(explicit_order_bys_);
|
||||
std::set<FieldPath> fieldsNormalized;
|
||||
for (const OrderBy& order_by : explicit_order_bys_) {
|
||||
fieldsNormalized.insert(order_by.field());
|
||||
}
|
||||
|
||||
// The order of the implicit ordering always matches the last explicit order
|
||||
// by.
|
||||
Direction last_direction = explicit_order_bys_.empty()
|
||||
? Direction::Ascending
|
||||
: explicit_order_bys_.back().direction();
|
||||
|
||||
// Any inequality fields not explicitly ordered should be implicitly ordered
|
||||
// in a lexicographical order. When there are multiple inequality filters on
|
||||
// the same field, the field should be added only once. Note:
|
||||
// `std::set<model::FieldPath>` sorts the key field before other fields.
|
||||
// However, we want the key field to be sorted last.
|
||||
const std::set<model::FieldPath> inequality_fields = InequalityFilterFields();
|
||||
|
||||
for (const model::FieldPath& field : inequality_fields) {
|
||||
if (fieldsNormalized.find(field) == fieldsNormalized.end() &&
|
||||
!field.IsKeyFieldPath()) {
|
||||
result->push_back(OrderBy(field, last_direction));
|
||||
}
|
||||
}
|
||||
|
||||
// The order of the implicit ordering always matches the last explicit order
|
||||
// by.
|
||||
Direction last_direction = explicit_order_bys_.empty()
|
||||
? Direction::Ascending
|
||||
: explicit_order_bys_.back().direction();
|
||||
// Add the document key field to the last if it is not explicitly ordered.
|
||||
if (fieldsNormalized.find(FieldPath::KeyFieldPath()) ==
|
||||
fieldsNormalized.end()) {
|
||||
result->push_back(OrderBy(FieldPath::KeyFieldPath(), last_direction));
|
||||
}
|
||||
|
||||
// Any inequality fields not explicitly ordered should be implicitly ordered
|
||||
// in a lexicographical order. When there are multiple inequality filters on
|
||||
// the same field, the field should be added only once. Note:
|
||||
// `std::set<model::FieldPath>` sorts the key field before other fields.
|
||||
// However, we want the key field to be sorted last.
|
||||
const std::set<model::FieldPath> inequality_fields =
|
||||
InequalityFilterFields();
|
||||
|
||||
for (const model::FieldPath& field : inequality_fields) {
|
||||
if (fieldsNormalized.find(field) == fieldsNormalized.end() &&
|
||||
!field.IsKeyFieldPath()) {
|
||||
result.push_back(OrderBy(field, last_direction));
|
||||
}
|
||||
}
|
||||
|
||||
// Add the document key field to the last if it is not explicitly ordered.
|
||||
if (fieldsNormalized.find(FieldPath::KeyFieldPath()) ==
|
||||
fieldsNormalized.end()) {
|
||||
result.push_back(OrderBy(FieldPath::KeyFieldPath(), last_direction));
|
||||
}
|
||||
|
||||
return result;
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
LimitType Query::limit_type() const {
|
||||
@@ -296,14 +295,12 @@ std::string Query::ToString() const {
|
||||
return absl::StrCat("Query(canonical_id=", CanonicalId(), ")");
|
||||
}
|
||||
|
||||
const Target& Query::ToTarget() const& {
|
||||
return memoized_target_->memoize(
|
||||
[&]() { return ToTarget(normalized_order_bys()); });
|
||||
std::shared_ptr<Target> Query::CalculateTarget() const {
|
||||
return std::make_shared<Target>(ToTarget(normalized_order_bys()));
|
||||
}
|
||||
|
||||
const Target& Query::ToAggregateTarget() const& {
|
||||
return memoized_aggregate_target_->memoize(
|
||||
[&]() { return ToTarget(explicit_order_bys_); });
|
||||
std::shared_ptr<Target> Query::CalculateAggregateTarget() const {
|
||||
return std::make_shared<Target>(ToTarget(explicit_order_bys_));
|
||||
}
|
||||
|
||||
Target Query::ToTarget(const std::vector<OrderBy>& order_bys) const {
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
#ifndef FIRESTORE_CORE_SRC_CORE_QUERY_H_
|
||||
#define FIRESTORE_CORE_SRC_CORE_QUERY_H_
|
||||
|
||||
#include <functional>
|
||||
#include <iosfwd>
|
||||
#include <limits>
|
||||
#include <memory>
|
||||
@@ -148,7 +149,10 @@ class Query {
|
||||
* This might include additional sort orders added implicitly to match the
|
||||
* backend behavior.
|
||||
*/
|
||||
const std::vector<OrderBy>& normalized_order_bys() const;
|
||||
const std::vector<OrderBy>& normalized_order_bys() const {
|
||||
const auto func = std::bind(&Query::CalculateNormalizedOrderBys, this);
|
||||
return memoized_normalized_order_bys_.value(func);
|
||||
}
|
||||
|
||||
bool has_limit() const {
|
||||
return limit_ != Target::kNoLimit;
|
||||
@@ -246,7 +250,10 @@ class Query {
|
||||
* Returns a `Target` instance this query will be mapped to in backend
|
||||
* and local store.
|
||||
*/
|
||||
const Target& ToTarget() const&;
|
||||
const Target& ToTarget() const& {
|
||||
const auto func = std::bind(&Query::CalculateTarget, this);
|
||||
return memoized_target_.value(func);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a `Target` instance this query will be mapped to in backend
|
||||
@@ -254,7 +261,10 @@ class Query {
|
||||
* for non-aggregate queries, aggregate query targets do not contain
|
||||
* normalized order-bys, they only contain explicit order-bys.
|
||||
*/
|
||||
const Target& ToAggregateTarget() const&;
|
||||
const Target& ToAggregateTarget() const& {
|
||||
const auto func = std::bind(&Query::CalculateAggregateTarget, this);
|
||||
return memoized_aggregate_target_.value(func);
|
||||
}
|
||||
|
||||
friend std::ostream& operator<<(std::ostream& os, const Query& query);
|
||||
|
||||
@@ -289,26 +299,21 @@ class Query {
|
||||
|
||||
Target ToTarget(const std::vector<OrderBy>& order_bys) const;
|
||||
|
||||
// For properties below, use a `std::shared_ptr<ThreadSafeMemoizer>` rather
|
||||
// than using `ThreadSafeMemoizer` directly so that this class is copyable
|
||||
// (`ThreadSafeMemoizer` is not copyable because of its `std::once_flag`
|
||||
// member variable, which is not copyable).
|
||||
|
||||
// The memoized list of sort orders.
|
||||
mutable std::shared_ptr<util::ThreadSafeMemoizer<std::vector<OrderBy>>>
|
||||
memoized_normalized_order_bys_{
|
||||
std::make_shared<util::ThreadSafeMemoizer<std::vector<OrderBy>>>()};
|
||||
std::shared_ptr<const std::vector<OrderBy>> CalculateNormalizedOrderBys()
|
||||
const;
|
||||
mutable util::ThreadSafeMemoizer<const std::vector<OrderBy>>
|
||||
memoized_normalized_order_bys_;
|
||||
|
||||
// The corresponding Target of this Query instance.
|
||||
mutable std::shared_ptr<util::ThreadSafeMemoizer<Target>> memoized_target_{
|
||||
std::make_shared<util::ThreadSafeMemoizer<Target>>()};
|
||||
std::shared_ptr<Target> CalculateTarget() const;
|
||||
mutable util::ThreadSafeMemoizer<Target> memoized_target_;
|
||||
|
||||
// The corresponding aggregate Target of this Query instance. Unlike targets
|
||||
// for non-aggregate queries, aggregate query targets do not contain
|
||||
// normalized order-bys, they only contain explicit order-bys.
|
||||
mutable std::shared_ptr<util::ThreadSafeMemoizer<Target>>
|
||||
memoized_aggregate_target_{
|
||||
std::make_shared<util::ThreadSafeMemoizer<Target>>()};
|
||||
std::shared_ptr<Target> CalculateAggregateTarget() const;
|
||||
mutable util::ThreadSafeMemoizer<Target> memoized_aggregate_target_;
|
||||
};
|
||||
|
||||
bool operator==(const Query& lhs, const Query& rhs);
|
||||
|
||||
@@ -112,7 +112,7 @@ void QueryListener::OnError(Status error) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether a snaphsot was raised.
|
||||
* Returns whether a snapshot was raised.
|
||||
*/
|
||||
bool QueryListener::OnOnlineStateChanged(OnlineState online_state) {
|
||||
online_state_ = online_state;
|
||||
|
||||
@@ -219,8 +219,7 @@ Target::IndexBoundValue Target::GetAscendingBound(
|
||||
switch (field_filter.op()) {
|
||||
case FieldFilter::Operator::LessThan:
|
||||
case FieldFilter::Operator::LessThanOrEqual:
|
||||
filter_value =
|
||||
model::GetLowerBound(field_filter.value().which_value_type);
|
||||
filter_value = model::GetLowerBound(field_filter.value());
|
||||
break;
|
||||
case FieldFilter::Operator::Equal:
|
||||
case FieldFilter::Operator::In:
|
||||
@@ -284,8 +283,7 @@ Target::IndexBoundValue Target::GetDescendingBound(
|
||||
switch (field_filter.op()) {
|
||||
case FieldFilter::Operator::GreaterThanOrEqual:
|
||||
case FieldFilter::Operator::GreaterThan:
|
||||
filter_value =
|
||||
model::GetUpperBound(field_filter.value().which_value_type);
|
||||
filter_value = model::GetUpperBound(field_filter.value());
|
||||
filter_inclusive = false;
|
||||
break;
|
||||
case FieldFilter::Operator::Equal:
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#include <memory>
|
||||
#include <mutex> // NOLINT(build/c++11)
|
||||
#include <mutex>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#include <memory>
|
||||
#include <mutex> // NOLINT(build/c++11)
|
||||
#include <mutex>
|
||||
#include <utility>
|
||||
|
||||
#include "Firestore/core/src/credentials/credentials_provider.h"
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
|
||||
#import "FirebaseCore/Extension/FIRAppInternal.h"
|
||||
|
||||
#import "FirebaseAuth/Interop/FIRAuthInterop.h"
|
||||
#import "FirebaseAuth/Interop/Public/FirebaseAuthInterop/FIRAuthInterop.h"
|
||||
|
||||
#include "Firestore/core/src/util/error_apple.h"
|
||||
#include "Firestore/core/src/util/hard_assert.h"
|
||||
|
||||
@@ -47,8 +47,8 @@ auto KeysView(const Range& range) -> KeysRange<decltype(std::begin(range))> {
|
||||
}
|
||||
|
||||
template <typename Range, typename K>
|
||||
auto KeysViewFrom(const Range& range,
|
||||
const K& key) -> KeysRange<decltype(range.lower_bound(key))> {
|
||||
auto KeysViewFrom(const Range& range, const K& key)
|
||||
-> KeysRange<decltype(range.lower_bound(key))> {
|
||||
auto keys_begin = util::make_iterator_first(range.lower_bound(key));
|
||||
auto keys_end = util::make_iterator_first(std::end(range));
|
||||
return util::make_range(keys_begin, keys_end);
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#include <string>
|
||||
|
||||
#include "Firestore/core/src/model/resource_path.h"
|
||||
#include "Firestore/core/src/model/value_util.h"
|
||||
#include "Firestore/core/src/nanopb/nanopb_util.h"
|
||||
|
||||
namespace firebase {
|
||||
@@ -46,6 +47,7 @@ enum IndexType {
|
||||
kReference = 37,
|
||||
kGeopoint = 45,
|
||||
kArray = 50,
|
||||
kVector = 53,
|
||||
kMap = 55,
|
||||
kReferenceSegment = 60,
|
||||
// A terminator that indicates that a truncatable value was not truncated.
|
||||
@@ -105,6 +107,31 @@ void WriteIndexArray(const google_firestore_v1_ArrayValue& array_index_value,
|
||||
}
|
||||
}
|
||||
|
||||
void WriteIndexVector(const google_firestore_v1_MapValue& map_index_value,
|
||||
DirectionalIndexByteEncoder* encoder) {
|
||||
WriteValueTypeLabel(encoder, IndexType::kVector);
|
||||
|
||||
absl::optional<pb_size_t> valueIndex =
|
||||
model::IndexOfKey(map_index_value, model::kRawVectorValueFieldKey,
|
||||
model::kVectorValueFieldKey);
|
||||
|
||||
if (!valueIndex.has_value() ||
|
||||
map_index_value.fields[valueIndex.value()].value.which_value_type !=
|
||||
google_firestore_v1_Value_array_value_tag) {
|
||||
return WriteIndexArray(model::MinArray().array_value, encoder);
|
||||
}
|
||||
|
||||
auto value = map_index_value.fields[valueIndex.value()].value;
|
||||
|
||||
// Vectors sort first by length
|
||||
WriteValueTypeLabel(encoder, IndexType::kNumber);
|
||||
encoder->WriteLong(value.array_value.values_count);
|
||||
|
||||
// Vectors then sort by position value
|
||||
WriteIndexString(model::kVectorValueFieldKey, encoder);
|
||||
WriteIndexValueAux(value, encoder);
|
||||
}
|
||||
|
||||
void WriteIndexMap(google_firestore_v1_MapValue map_index_value,
|
||||
DirectionalIndexByteEncoder* encoder) {
|
||||
WriteValueTypeLabel(encoder, IndexType::kMap);
|
||||
@@ -183,6 +210,9 @@ void WriteIndexValueAux(const google_firestore_v1_Value& index_value,
|
||||
if (model::IsMaxValue(index_value)) {
|
||||
WriteValueTypeLabel(encoder, std::numeric_limits<int>::max());
|
||||
break;
|
||||
} else if (model::IsVectorValue(index_value)) {
|
||||
WriteIndexVector(index_value.map_value, encoder);
|
||||
break;
|
||||
}
|
||||
WriteIndexMap(index_value.map_value, encoder);
|
||||
WriteTruncationMarker(encoder);
|
||||
|
||||
57
Pods/FirebaseFirestoreInternal/Firestore/core/src/local/globals_cache.h
generated
Normal file
57
Pods/FirebaseFirestoreInternal/Firestore/core/src/local/globals_cache.h
generated
Normal file
@@ -0,0 +1,57 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright 2024 Google LLC
|
||||
*
|
||||
* 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_LOCAL_GLOBALS_CACHE_H_
|
||||
#define FIRESTORE_CORE_SRC_LOCAL_GLOBALS_CACHE_H_
|
||||
|
||||
#include "Firestore/core/src/nanopb/byte_string.h"
|
||||
|
||||
using firebase::firestore::nanopb::ByteString;
|
||||
|
||||
namespace firebase {
|
||||
namespace firestore {
|
||||
namespace local {
|
||||
|
||||
/**
|
||||
* General purpose cache for global values.
|
||||
*
|
||||
* Global state that cuts across components should be saved here. Following are
|
||||
* contained herein:
|
||||
*
|
||||
* `sessionToken` tracks server interaction across Listen and Write streams.
|
||||
* This facilitates cache synchronization and invalidation.
|
||||
*/
|
||||
class GlobalsCache {
|
||||
public:
|
||||
virtual ~GlobalsCache() = default;
|
||||
|
||||
/**
|
||||
* Gets session token.
|
||||
*/
|
||||
virtual ByteString GetSessionToken() const = 0;
|
||||
|
||||
/**
|
||||
* Sets session token.
|
||||
*/
|
||||
virtual void SetSessionToken(const ByteString& session_token) = 0;
|
||||
};
|
||||
|
||||
} // namespace local
|
||||
} // namespace firestore
|
||||
} // namespace firebase
|
||||
|
||||
#endif // FIRESTORE_CORE_SRC_LOCAL_GLOBALS_CACHE_H_
|
||||
57
Pods/FirebaseFirestoreInternal/Firestore/core/src/local/leveldb_globals_cache.cc
generated
Normal file
57
Pods/FirebaseFirestoreInternal/Firestore/core/src/local/leveldb_globals_cache.cc
generated
Normal file
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Copyright 2024 Google LLC
|
||||
*
|
||||
* 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 <string>
|
||||
|
||||
#include "Firestore/core/src/local/leveldb_globals_cache.h"
|
||||
#include "Firestore/core/src/local/leveldb_key.h"
|
||||
#include "Firestore/core/src/local/leveldb_persistence.h"
|
||||
|
||||
namespace firebase {
|
||||
namespace firestore {
|
||||
namespace local {
|
||||
|
||||
namespace {
|
||||
|
||||
const char* kSessionToken = "session_token";
|
||||
|
||||
}
|
||||
|
||||
LevelDbGlobalsCache::LevelDbGlobalsCache(LevelDbPersistence* db)
|
||||
: db_(NOT_NULL(db)) {
|
||||
}
|
||||
|
||||
ByteString LevelDbGlobalsCache::GetSessionToken() const {
|
||||
auto key = LevelDbGlobalKey::Key(kSessionToken);
|
||||
|
||||
std::string encoded;
|
||||
auto done = db_->current_transaction()->Get(key, &encoded);
|
||||
|
||||
if (!done.ok()) {
|
||||
return ByteString();
|
||||
}
|
||||
|
||||
return ByteString(encoded);
|
||||
}
|
||||
|
||||
void LevelDbGlobalsCache::SetSessionToken(const ByteString& session_token) {
|
||||
auto key = LevelDbGlobalKey::Key(kSessionToken);
|
||||
db_->current_transaction()->Put(key, session_token.ToString());
|
||||
}
|
||||
|
||||
} // namespace local
|
||||
} // namespace firestore
|
||||
} // namespace firebase
|
||||
52
Pods/FirebaseFirestoreInternal/Firestore/core/src/local/leveldb_globals_cache.h
generated
Normal file
52
Pods/FirebaseFirestoreInternal/Firestore/core/src/local/leveldb_globals_cache.h
generated
Normal file
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright 2024 Google LLC
|
||||
*
|
||||
* 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_LOCAL_LEVELDB_GLOBALS_CACHE_H_
|
||||
#define FIRESTORE_CORE_SRC_LOCAL_LEVELDB_GLOBALS_CACHE_H_
|
||||
|
||||
#include "Firestore/core/src/local/globals_cache.h"
|
||||
|
||||
namespace firebase {
|
||||
namespace firestore {
|
||||
namespace local {
|
||||
|
||||
class LevelDbPersistence;
|
||||
|
||||
class LevelDbGlobalsCache : public GlobalsCache {
|
||||
public:
|
||||
/** Creates a new bundle cache in the given LevelDB. */
|
||||
explicit LevelDbGlobalsCache(LevelDbPersistence* db);
|
||||
|
||||
/**
|
||||
* Gets session token.
|
||||
*/
|
||||
ByteString GetSessionToken() const override;
|
||||
|
||||
/**
|
||||
* Sets session token.
|
||||
*/
|
||||
void SetSessionToken(const ByteString& session_token) override;
|
||||
|
||||
private:
|
||||
// The LevelDbGlobalsCache is owned by LevelDbPersistence.
|
||||
LevelDbPersistence* db_ = nullptr;
|
||||
};
|
||||
|
||||
} // namespace local
|
||||
} // namespace firestore
|
||||
} // namespace firebase
|
||||
|
||||
#endif // FIRESTORE_CORE_SRC_LOCAL_LEVELDB_GLOBALS_CACHE_H_
|
||||
@@ -188,10 +188,15 @@ LevelDbIndexManager::LevelDbIndexManager(const User& user,
|
||||
// The contract for this comparison expected by priority queue is
|
||||
// `std::less`, but std::priority_queue's default order is descending.
|
||||
// We change the order to be ascending by doing left >= right instead.
|
||||
// Note: priority queue has to have a strict ordering, so here using unique_id
|
||||
// to order Field Indexes having same `sequence_number` and `collection_group`
|
||||
auto cmp = [](FieldIndex* left, FieldIndex* right) {
|
||||
if (left->index_state().sequence_number() ==
|
||||
right->index_state().sequence_number()) {
|
||||
return left->collection_group() >= right->collection_group();
|
||||
if (left->collection_group() == right->collection_group()) {
|
||||
return left->unique_id() > right->unique_id();
|
||||
}
|
||||
return left->collection_group() > right->collection_group();
|
||||
}
|
||||
return left->index_state().sequence_number() >
|
||||
right->index_state().sequence_number();
|
||||
|
||||
@@ -39,6 +39,7 @@ namespace local {
|
||||
namespace {
|
||||
|
||||
const char* kVersionGlobalTable = "version";
|
||||
const char* kGlobalsTable = "globals";
|
||||
const char* kMutationsTable = "mutation";
|
||||
const char* kDocumentMutationsTable = "document_mutation";
|
||||
const char* kMutationQueuesTable = "mutation_queue";
|
||||
@@ -159,6 +160,11 @@ enum ComponentLabel {
|
||||
*/
|
||||
DataMigrationName = 25,
|
||||
|
||||
/**
|
||||
* The name of a global.
|
||||
*/
|
||||
GlobalName = 26,
|
||||
|
||||
/**
|
||||
* A path segment describes just a single segment in a resource path. Path
|
||||
* segments that occur sequentially in a key represent successive segments in
|
||||
@@ -245,6 +251,10 @@ class Reader {
|
||||
return ReadLabeledString(ComponentLabel::BundleId);
|
||||
}
|
||||
|
||||
std::string ReadGlobalName() {
|
||||
return ReadLabeledString(ComponentLabel::GlobalName);
|
||||
}
|
||||
|
||||
std::string ReadQueryName() {
|
||||
return ReadLabeledString(ComponentLabel::QueryName);
|
||||
}
|
||||
@@ -718,6 +728,10 @@ class Writer {
|
||||
WriteLabeledString(ComponentLabel::TableName, table_name);
|
||||
}
|
||||
|
||||
void WriteGlobalName(absl::string_view global_name) {
|
||||
WriteLabeledString(ComponentLabel::GlobalName, global_name);
|
||||
}
|
||||
|
||||
void WriteBatchId(model::BatchId batch_id) {
|
||||
WriteLabeledInt32(ComponentLabel::BatchId, batch_id);
|
||||
}
|
||||
@@ -1206,6 +1220,28 @@ bool LevelDbRemoteDocumentReadTimeKey::Decode(absl::string_view key) {
|
||||
return reader.ok();
|
||||
}
|
||||
|
||||
std::string LevelDbGlobalKey::KeyPrefix() {
|
||||
Writer writer;
|
||||
writer.WriteTableName(kGlobalsTable);
|
||||
return writer.result();
|
||||
}
|
||||
|
||||
std::string LevelDbGlobalKey::Key(absl::string_view global_name) {
|
||||
Writer writer;
|
||||
writer.WriteTableName(kGlobalsTable);
|
||||
writer.WriteGlobalName(global_name);
|
||||
writer.WriteTerminator();
|
||||
return writer.result();
|
||||
}
|
||||
|
||||
bool LevelDbGlobalKey::Decode(absl::string_view key) {
|
||||
Reader reader{key};
|
||||
reader.ReadTableNameMatching(kGlobalsTable);
|
||||
global_name_ = reader.ReadGlobalName();
|
||||
reader.ReadTerminator();
|
||||
return reader.ok();
|
||||
}
|
||||
|
||||
std::string LevelDbBundleKey::KeyPrefix() {
|
||||
Writer writer;
|
||||
writer.WriteTableName(kBundlesTable);
|
||||
|
||||
@@ -768,6 +768,41 @@ class LevelDbNamedQueryKey {
|
||||
std::string name_;
|
||||
};
|
||||
|
||||
/**
|
||||
* A key in the globals table, storing the name of the global value.
|
||||
*/
|
||||
class LevelDbGlobalKey {
|
||||
public:
|
||||
/**
|
||||
* Creates a key prefix that points just before the first key of the table.
|
||||
*/
|
||||
static std::string KeyPrefix();
|
||||
|
||||
/**
|
||||
* Creates a key that points to the key for the given name of global value.
|
||||
*/
|
||||
static std::string Key(absl::string_view global_name);
|
||||
|
||||
/**
|
||||
* Decodes the given complete key, storing the decoded values in this
|
||||
* instance.
|
||||
*
|
||||
* @return true if the key successfully decoded, false otherwise. If false is
|
||||
* returned, this instance is in an undefined state until the next call to
|
||||
* `Decode()`.
|
||||
*/
|
||||
ABSL_MUST_USE_RESULT
|
||||
bool Decode(absl::string_view key);
|
||||
|
||||
/** The name that serves as identifier for global value for this entry. */
|
||||
const std::string& global_name() const {
|
||||
return global_name_;
|
||||
}
|
||||
|
||||
private:
|
||||
std::string global_name_;
|
||||
};
|
||||
|
||||
/**
|
||||
* A key in the index_configuration table, storing the index definition proto,
|
||||
* and the collection (group) it applies to.
|
||||
|
||||
@@ -126,6 +126,7 @@ LevelDbPersistence::LevelDbPersistence(std::unique_ptr<leveldb::DB> db,
|
||||
reference_delegate_ =
|
||||
absl::make_unique<LevelDbLruReferenceDelegate>(this, lru_params);
|
||||
bundle_cache_ = absl::make_unique<LevelDbBundleCache>(this, &serializer_);
|
||||
globals_cache_ = absl::make_unique<LevelDbGlobalsCache>(this);
|
||||
|
||||
// TODO(gsoltis): set up a leveldb transaction for these operations.
|
||||
target_cache_->Start();
|
||||
@@ -250,6 +251,10 @@ LevelDbTargetCache* LevelDbPersistence::target_cache() {
|
||||
return target_cache_.get();
|
||||
}
|
||||
|
||||
LevelDbGlobalsCache* LevelDbPersistence::globals_cache() {
|
||||
return globals_cache_.get();
|
||||
}
|
||||
|
||||
LevelDbRemoteDocumentCache* LevelDbPersistence::remote_document_cache() {
|
||||
return document_cache_.get();
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
#include "Firestore/core/src/credentials/user.h"
|
||||
#include "Firestore/core/src/local/leveldb_bundle_cache.h"
|
||||
#include "Firestore/core/src/local/leveldb_document_overlay_cache.h"
|
||||
#include "Firestore/core/src/local/leveldb_globals_cache.h"
|
||||
#include "Firestore/core/src/local/leveldb_index_manager.h"
|
||||
#include "Firestore/core/src/local/leveldb_lru_reference_delegate.h"
|
||||
#include "Firestore/core/src/local/leveldb_migrations.h"
|
||||
@@ -84,6 +85,8 @@ class LevelDbPersistence : public Persistence {
|
||||
|
||||
LevelDbBundleCache* bundle_cache() override;
|
||||
|
||||
LevelDbGlobalsCache* globals_cache() override;
|
||||
|
||||
LevelDbDocumentOverlayCache* GetDocumentOverlayCache(
|
||||
const credentials::User& user) override;
|
||||
LevelDbOverlayMigrationManager* GetOverlayMigrationManager(
|
||||
@@ -154,6 +157,7 @@ class LevelDbPersistence : public Persistence {
|
||||
bool started_ = false;
|
||||
|
||||
std::unique_ptr<LevelDbBundleCache> bundle_cache_;
|
||||
std::unique_ptr<LevelDbGlobalsCache> globals_cache_;
|
||||
std::unordered_map<std::string, std::unique_ptr<LevelDbDocumentOverlayCache>>
|
||||
document_overlay_caches_;
|
||||
std::unordered_map<std::string,
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
#include "Firestore/core/src/local/leveldb_remote_document_cache.h"
|
||||
|
||||
#include <string>
|
||||
#include <thread> // NOLINT(build/c++11)
|
||||
#include <thread>
|
||||
#include <utility>
|
||||
|
||||
#include "Firestore/Protos/nanopb/firestore/local/maybe_document.nanopb.h"
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <thread> // NOLINT(build/c++11)
|
||||
#include <thread>
|
||||
#include <vector>
|
||||
|
||||
#include "Firestore/core/src/core/query.h"
|
||||
|
||||
@@ -585,7 +585,7 @@ LruResults LocalStore::CollectGarbage(LruGarbageCollector* garbage_collector) {
|
||||
});
|
||||
}
|
||||
|
||||
int LocalStore::Backfill() const {
|
||||
size_t LocalStore::Backfill() const {
|
||||
return persistence_->Run("Backfill Indexes", [&] {
|
||||
return index_backfiller_->WriteIndexEntries(this);
|
||||
});
|
||||
|
||||
@@ -254,7 +254,7 @@ class LocalStore : public bundle::BundleCallback {
|
||||
* Runs a single backfill operation and returns the number of documents
|
||||
* processed.
|
||||
*/
|
||||
int Backfill() const;
|
||||
size_t Backfill() const;
|
||||
|
||||
/**
|
||||
* Returns whether the given bundle has already been loaded and its create
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
#include "Firestore/core/src/local/lru_garbage_collector.h"
|
||||
|
||||
#include <chrono> // NOLINT(build/c++11)
|
||||
#include <chrono>
|
||||
#include <queue>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2018 Google
|
||||
* Copyright 2024 Google LLC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -14,22 +14,20 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#import "FIRTimestamp.h"
|
||||
#include "Firestore/core/src/local/memory_globals_cache.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
namespace firebase {
|
||||
namespace firestore {
|
||||
namespace local {
|
||||
|
||||
/** Internal FIRTimestamp API we don't want exposed in our public header files. */
|
||||
@interface FIRTimestamp (Internal)
|
||||
ByteString MemoryGlobalsCache::GetSessionToken() const {
|
||||
return session_token_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the given date to an ISO 8601 timestamp string, useful for rendering in JSON.
|
||||
*
|
||||
* ISO 8601 dates times in UTC look like this: "1912-04-14T23:40:00.000000000Z".
|
||||
*
|
||||
* @see http://www.ecma-international.org/ecma-262/6.0/#sec-date-time-string-format
|
||||
*/
|
||||
- (NSString *)ISO8601String;
|
||||
void MemoryGlobalsCache::SetSessionToken(const ByteString& session_token) {
|
||||
session_token_ = session_token;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
} // namespace local
|
||||
} // namespace firestore
|
||||
} // namespace firebase
|
||||
49
Pods/FirebaseFirestoreInternal/Firestore/core/src/local/memory_globals_cache.h
generated
Normal file
49
Pods/FirebaseFirestoreInternal/Firestore/core/src/local/memory_globals_cache.h
generated
Normal file
@@ -0,0 +1,49 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright 2024 Google LLC
|
||||
*
|
||||
* 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_LOCAL_MEMORY_GLOBALS_CACHE_H_
|
||||
#define FIRESTORE_CORE_SRC_LOCAL_MEMORY_GLOBALS_CACHE_H_
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "Firestore/core/src/local/globals_cache.h"
|
||||
|
||||
namespace firebase {
|
||||
namespace firestore {
|
||||
namespace local {
|
||||
|
||||
class MemoryGlobalsCache : public GlobalsCache {
|
||||
public:
|
||||
/**
|
||||
* Gets session token.
|
||||
*/
|
||||
ByteString GetSessionToken() const override;
|
||||
|
||||
/**
|
||||
* Sets session token.
|
||||
*/
|
||||
void SetSessionToken(const ByteString& session_token) override;
|
||||
|
||||
private:
|
||||
ByteString session_token_;
|
||||
};
|
||||
|
||||
} // namespace local
|
||||
} // namespace firestore
|
||||
} // namespace firebase
|
||||
|
||||
#endif // FIRESTORE_CORE_SRC_LOCAL_MEMORY_GLOBALS_CACHE_H_
|
||||
@@ -17,6 +17,7 @@
|
||||
#ifndef FIRESTORE_CORE_SRC_LOCAL_MEMORY_MUTATION_QUEUE_H_
|
||||
#define FIRESTORE_CORE_SRC_LOCAL_MEMORY_MUTATION_QUEUE_H_
|
||||
|
||||
#include <deque>
|
||||
#include <set>
|
||||
#include <vector>
|
||||
|
||||
@@ -59,7 +60,7 @@ class MemoryMutationQueue : public MutationQueue {
|
||||
void RemoveMutationBatch(const model::MutationBatch& batch) override;
|
||||
|
||||
std::vector<model::MutationBatch> AllMutationBatches() override {
|
||||
return queue_;
|
||||
return std::vector<model::MutationBatch>(queue_.begin(), queue_.end());
|
||||
}
|
||||
|
||||
std::vector<model::MutationBatch> AllMutationBatchesAffectingDocumentKeys(
|
||||
@@ -128,7 +129,7 @@ class MemoryMutationQueue : public MutationQueue {
|
||||
* Once the held write acknowledgements become visible they are removed from
|
||||
* the head of the queue along with any tombstones that follow.
|
||||
*/
|
||||
std::vector<model::MutationBatch> queue_;
|
||||
std::deque<model::MutationBatch> queue_;
|
||||
|
||||
/**
|
||||
* The next value to use when assigning sequential IDs to each mutation
|
||||
|
||||
@@ -102,6 +102,10 @@ MemoryBundleCache* MemoryPersistence::bundle_cache() {
|
||||
return &bundle_cache_;
|
||||
}
|
||||
|
||||
MemoryGlobalsCache* MemoryPersistence::globals_cache() {
|
||||
return &globals_cache_;
|
||||
}
|
||||
|
||||
MemoryDocumentOverlayCache* MemoryPersistence::GetDocumentOverlayCache(
|
||||
const User& user) {
|
||||
auto iter = document_overlay_caches_.find(user);
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
#include "Firestore/core/src/credentials/user.h"
|
||||
#include "Firestore/core/src/local/memory_bundle_cache.h"
|
||||
#include "Firestore/core/src/local/memory_document_overlay_cache.h"
|
||||
#include "Firestore/core/src/local/memory_globals_cache.h"
|
||||
#include "Firestore/core/src/local/memory_index_manager.h"
|
||||
#include "Firestore/core/src/local/memory_mutation_queue.h"
|
||||
#include "Firestore/core/src/local/memory_remote_document_cache.h"
|
||||
@@ -90,6 +91,8 @@ class MemoryPersistence : public Persistence {
|
||||
|
||||
MemoryBundleCache* bundle_cache() override;
|
||||
|
||||
MemoryGlobalsCache* globals_cache() override;
|
||||
|
||||
MemoryDocumentOverlayCache* GetDocumentOverlayCache(
|
||||
const credentials::User& user) override;
|
||||
|
||||
@@ -138,6 +141,8 @@ class MemoryPersistence : public Persistence {
|
||||
|
||||
MemoryBundleCache bundle_cache_;
|
||||
|
||||
MemoryGlobalsCache globals_cache_;
|
||||
|
||||
DocumentOverlayCaches document_overlay_caches_;
|
||||
MemoryOverlayMigrationManager overlay_migration_manager_;
|
||||
|
||||
|
||||
@@ -36,6 +36,7 @@ namespace local {
|
||||
|
||||
class BundleCache;
|
||||
class DocumentOverlayCache;
|
||||
class GlobalsCache;
|
||||
class IndexManager;
|
||||
class MutationQueue;
|
||||
class OverlayMigrationManager;
|
||||
@@ -86,6 +87,11 @@ class Persistence {
|
||||
/** Releases any resources held during eager shutdown. */
|
||||
virtual void Shutdown() = 0;
|
||||
|
||||
/**
|
||||
* Returns GlobalCache representing a general purpose cache for global values.
|
||||
*/
|
||||
virtual GlobalsCache* globals_cache() = 0;
|
||||
|
||||
/**
|
||||
* Returns a MutationQueue representing the persisted mutations for the given
|
||||
* user.
|
||||
|
||||
@@ -150,8 +150,18 @@ class BasePath {
|
||||
std::equal(begin(), end(), potential_child.begin());
|
||||
}
|
||||
|
||||
/**
|
||||
* Compares the current path against another Path object. Paths are compared
|
||||
* segment by segment, prioritizing numeric IDs (e.g., "__id123__") in numeric
|
||||
* ascending order, followed by string segments in lexicographical order.
|
||||
*/
|
||||
util::ComparisonResult CompareTo(const T& rhs) const {
|
||||
return util::CompareContainer(segments_, rhs.segments_);
|
||||
size_t min_size = std::min(size(), rhs.size());
|
||||
for (size_t i = 0; i < min_size; ++i) {
|
||||
auto cmp = CompareSegments(segments_[i], rhs.segments_[i]);
|
||||
if (!util::Same(cmp)) return cmp;
|
||||
}
|
||||
return util::Compare(size(), rhs.size());
|
||||
}
|
||||
|
||||
friend bool operator==(const BasePath& lhs, const BasePath& rhs) {
|
||||
@@ -174,6 +184,38 @@ class BasePath {
|
||||
|
||||
private:
|
||||
SegmentsT segments_;
|
||||
|
||||
static const size_t kNumericIdPrefixLength = 4;
|
||||
static const size_t kNumericIdSuffixLength = 2;
|
||||
static const size_t kNumericIdTotalOverhead =
|
||||
kNumericIdPrefixLength + kNumericIdSuffixLength;
|
||||
|
||||
static util::ComparisonResult CompareSegments(const std::string& lhs,
|
||||
const std::string& rhs) {
|
||||
bool isLhsNumeric = IsNumericId(lhs);
|
||||
bool isRhsNumeric = IsNumericId(rhs);
|
||||
|
||||
if (isLhsNumeric && !isRhsNumeric) {
|
||||
return util::ComparisonResult::Ascending;
|
||||
} else if (!isLhsNumeric && isRhsNumeric) {
|
||||
return util::ComparisonResult::Descending;
|
||||
} else if (isLhsNumeric && isRhsNumeric) {
|
||||
return util::Compare(ExtractNumericId(lhs), ExtractNumericId(rhs));
|
||||
} else {
|
||||
return util::Compare(lhs, rhs);
|
||||
}
|
||||
}
|
||||
|
||||
static bool IsNumericId(const std::string& segment) {
|
||||
return segment.size() > kNumericIdTotalOverhead &&
|
||||
segment.substr(0, kNumericIdPrefixLength) == "__id" &&
|
||||
segment.substr(segment.size() - kNumericIdSuffixLength) == "__";
|
||||
}
|
||||
|
||||
static int64_t ExtractNumericId(const std::string& segment) {
|
||||
return std::stol(segment.substr(kNumericIdPrefixLength,
|
||||
segment.size() - kNumericIdSuffixLength));
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace impl
|
||||
|
||||
@@ -20,6 +20,8 @@ namespace firebase {
|
||||
namespace firestore {
|
||||
namespace model {
|
||||
|
||||
std::atomic<int> FieldIndex::ref_count_{0};
|
||||
|
||||
util::ComparisonResult Segment::CompareTo(const Segment& rhs) const {
|
||||
auto result = field_path().CompareTo(rhs.field_path());
|
||||
if (result != util::ComparisonResult::Same) {
|
||||
|
||||
@@ -243,7 +243,9 @@ class FieldIndex {
|
||||
static util::ComparisonResult SemanticCompare(const FieldIndex& left,
|
||||
const FieldIndex& right);
|
||||
|
||||
FieldIndex() : index_id_(UnknownId()) {
|
||||
FieldIndex()
|
||||
: index_id_(UnknownId()),
|
||||
unique_id_(ref_count_.fetch_add(1, std::memory_order_acq_rel)) {
|
||||
}
|
||||
|
||||
FieldIndex(int32_t index_id,
|
||||
@@ -253,7 +255,50 @@ class FieldIndex {
|
||||
: index_id_(index_id),
|
||||
collection_group_(std::move(collection_group)),
|
||||
segments_(std::move(segments)),
|
||||
state_(std::move(state)) {
|
||||
state_(std::move(state)),
|
||||
unique_id_(ref_count_.fetch_add(1, std::memory_order_acq_rel)) {
|
||||
}
|
||||
|
||||
// Copy constructor
|
||||
FieldIndex(const FieldIndex& other)
|
||||
: index_id_(other.index_id_),
|
||||
collection_group_(other.collection_group_),
|
||||
segments_(other.segments_),
|
||||
state_(other.state_),
|
||||
unique_id_(ref_count_.fetch_add(1, std::memory_order_acq_rel)) {
|
||||
}
|
||||
|
||||
// Copy assignment operator
|
||||
FieldIndex& operator=(const FieldIndex& other) {
|
||||
if (this != &other) {
|
||||
index_id_ = other.index_id_;
|
||||
collection_group_ = other.collection_group_;
|
||||
segments_ = other.segments_;
|
||||
state_ = other.state_;
|
||||
unique_id_ = ref_count_.fetch_add(1, std::memory_order_acq_rel);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Move constructor
|
||||
FieldIndex(FieldIndex&& other) noexcept
|
||||
: index_id_(other.index_id_),
|
||||
collection_group_(std::move(other.collection_group_)),
|
||||
segments_(std::move(other.segments_)),
|
||||
state_(std::move(other.state_)),
|
||||
unique_id_(ref_count_.fetch_add(1, std::memory_order_acq_rel)) {
|
||||
}
|
||||
|
||||
// Move assignment operator
|
||||
FieldIndex& operator=(FieldIndex&& other) noexcept {
|
||||
if (this != &other) {
|
||||
index_id_ = other.index_id_;
|
||||
collection_group_ = std::move(other.collection_group_);
|
||||
segments_ = std::move(other.segments_);
|
||||
state_ = std::move(other.state_);
|
||||
unique_id_ = ref_count_.fetch_add(1, std::memory_order_acq_rel);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -285,6 +330,14 @@ class FieldIndex {
|
||||
/** Returns the ArrayContains/ArrayContainsAny segment for this index. */
|
||||
absl::optional<Segment> GetArraySegment() const;
|
||||
|
||||
/**
|
||||
* Returns the unique identifier for this object, ensuring a strict ordering
|
||||
* in the priority queue's comparison function.
|
||||
*/
|
||||
int unique_id() const {
|
||||
return unique_id_;
|
||||
}
|
||||
|
||||
/**
|
||||
* A type that can be used as the "Compare" template parameter of ordered
|
||||
* collections to have the elements ordered using
|
||||
@@ -308,6 +361,10 @@ class FieldIndex {
|
||||
std::string collection_group_;
|
||||
std::vector<Segment> segments_;
|
||||
IndexState state_;
|
||||
int unique_id_;
|
||||
|
||||
// TODO(C++17): Replace with inline static std::atomic<int> ref_count_ = 0;
|
||||
static std::atomic<int> ref_count_;
|
||||
};
|
||||
|
||||
inline bool operator==(const FieldIndex& lhs, const FieldIndex& rhs) {
|
||||
|
||||
@@ -38,26 +38,33 @@
|
||||
namespace firebase {
|
||||
namespace firestore {
|
||||
namespace model {
|
||||
namespace {
|
||||
|
||||
using nanopb::Message;
|
||||
using util::ComparisonResult;
|
||||
|
||||
/** The smallest reference value. */
|
||||
pb_bytes_array_s* kMinimumReferenceValue =
|
||||
nanopb::MakeBytesArray("projects//databases//documents/");
|
||||
|
||||
/** The field type of a maximum proto value. */
|
||||
const char* kRawMaxValueFieldKey = "__type__";
|
||||
pb_bytes_array_s* kMaxValueFieldKey =
|
||||
nanopb::MakeBytesArray(kRawMaxValueFieldKey);
|
||||
/** The field type of a special object type. */
|
||||
const char* kRawTypeValueFieldKey = "__type__";
|
||||
pb_bytes_array_s* kTypeValueFieldKey =
|
||||
nanopb::MakeBytesArray(kRawTypeValueFieldKey);
|
||||
|
||||
/** The field value of a maximum proto value. */
|
||||
const char* kRawMaxValueFieldValue = "__max__";
|
||||
pb_bytes_array_s* kMaxValueFieldValue =
|
||||
nanopb::MakeBytesArray(kRawMaxValueFieldValue);
|
||||
|
||||
} // namespace
|
||||
/** The type of a VectorValue proto. */
|
||||
const char* kRawVectorTypeFieldValue = "__vector__";
|
||||
pb_bytes_array_s* kVectorTypeFieldValue =
|
||||
nanopb::MakeBytesArray(kRawVectorTypeFieldValue);
|
||||
|
||||
using nanopb::Message;
|
||||
using util::ComparisonResult;
|
||||
/** The value key of a VectorValue proto. */
|
||||
const char* kRawVectorValueFieldKey = "value";
|
||||
pb_bytes_array_s* kVectorValueFieldKey =
|
||||
nanopb::MakeBytesArray(kRawVectorValueFieldKey);
|
||||
|
||||
TypeOrder GetTypeOrder(const google_firestore_v1_Value& value) {
|
||||
switch (value.which_value_type) {
|
||||
@@ -94,6 +101,8 @@ TypeOrder GetTypeOrder(const google_firestore_v1_Value& value) {
|
||||
return TypeOrder::kServerTimestamp;
|
||||
} else if (IsMaxValue(value)) {
|
||||
return TypeOrder::kMaxValue;
|
||||
} else if (IsVectorValue(value)) {
|
||||
return TypeOrder::kVector;
|
||||
}
|
||||
return TypeOrder::kMap;
|
||||
}
|
||||
@@ -253,6 +262,43 @@ ComparisonResult CompareMaps(const google_firestore_v1_MapValue& left,
|
||||
return util::Compare(left_map->fields_count, right_map->fields_count);
|
||||
}
|
||||
|
||||
ComparisonResult CompareVectors(const google_firestore_v1_Value& left,
|
||||
const google_firestore_v1_Value& right) {
|
||||
HARD_ASSERT(IsVectorValue(left) && IsVectorValue(right),
|
||||
"Cannot compare non-vector values as vectors.");
|
||||
|
||||
absl::optional<pb_size_t> leftIndex =
|
||||
IndexOfKey(left.map_value, kRawVectorValueFieldKey, kVectorValueFieldKey);
|
||||
absl::optional<pb_size_t> rightIndex = IndexOfKey(
|
||||
right.map_value, kRawVectorValueFieldKey, kVectorValueFieldKey);
|
||||
|
||||
pb_size_t leftArrayLength = 0;
|
||||
google_firestore_v1_Value leftArray;
|
||||
if (leftIndex.has_value()) {
|
||||
leftArray = left.map_value.fields[leftIndex.value()].value;
|
||||
leftArrayLength = leftArray.array_value.values_count;
|
||||
}
|
||||
|
||||
pb_size_t rightArrayLength = 0;
|
||||
google_firestore_v1_Value rightArray;
|
||||
if (leftIndex.has_value()) {
|
||||
rightArray = right.map_value.fields[rightIndex.value()].value;
|
||||
rightArrayLength = rightArray.array_value.values_count;
|
||||
}
|
||||
|
||||
if (leftArrayLength == 0 && rightArrayLength == 0) {
|
||||
return ComparisonResult::Same;
|
||||
}
|
||||
|
||||
ComparisonResult lengthCompare =
|
||||
util::Compare(leftArrayLength, rightArrayLength);
|
||||
if (lengthCompare != ComparisonResult::Same) {
|
||||
return lengthCompare;
|
||||
}
|
||||
|
||||
return CompareArrays(leftArray, rightArray);
|
||||
}
|
||||
|
||||
ComparisonResult Compare(const google_firestore_v1_Value& left,
|
||||
const google_firestore_v1_Value& right) {
|
||||
TypeOrder left_type = GetTypeOrder(left);
|
||||
@@ -297,6 +343,9 @@ ComparisonResult Compare(const google_firestore_v1_Value& left,
|
||||
case TypeOrder::kMap:
|
||||
return CompareMaps(left.map_value, right.map_value);
|
||||
|
||||
case TypeOrder::kVector:
|
||||
return CompareVectors(left, right);
|
||||
|
||||
case TypeOrder::kMaxValue:
|
||||
return util::ComparisonResult::Same;
|
||||
|
||||
@@ -425,6 +474,7 @@ bool Equals(const google_firestore_v1_Value& lhs,
|
||||
case TypeOrder::kArray:
|
||||
return ArrayEquals(lhs.array_value, rhs.array_value);
|
||||
|
||||
case TypeOrder::kVector:
|
||||
case TypeOrder::kMap:
|
||||
return MapValueEquals(lhs.map_value, rhs.map_value);
|
||||
|
||||
@@ -539,106 +589,87 @@ std::string CanonicalId(const google_firestore_v1_ArrayValue& value) {
|
||||
return CanonifyArray(value);
|
||||
}
|
||||
|
||||
google_firestore_v1_Value GetLowerBound(pb_size_t value_tag) {
|
||||
switch (value_tag) {
|
||||
google_firestore_v1_Value GetLowerBound(
|
||||
const google_firestore_v1_Value& value) {
|
||||
switch (value.which_value_type) {
|
||||
case google_firestore_v1_Value_null_value_tag:
|
||||
return NullValue();
|
||||
|
||||
case google_firestore_v1_Value_boolean_value_tag: {
|
||||
google_firestore_v1_Value value;
|
||||
value.which_value_type = value_tag;
|
||||
value.boolean_value = false;
|
||||
return value;
|
||||
return MinBoolean();
|
||||
}
|
||||
|
||||
case google_firestore_v1_Value_integer_value_tag:
|
||||
case google_firestore_v1_Value_double_value_tag: {
|
||||
return NaNValue();
|
||||
return MinNumber();
|
||||
}
|
||||
|
||||
case google_firestore_v1_Value_timestamp_value_tag: {
|
||||
google_firestore_v1_Value value;
|
||||
value.which_value_type = value_tag;
|
||||
value.timestamp_value.seconds = std::numeric_limits<int64_t>::min();
|
||||
value.timestamp_value.nanos = 0;
|
||||
return value;
|
||||
return MinTimestamp();
|
||||
}
|
||||
|
||||
case google_firestore_v1_Value_string_value_tag: {
|
||||
google_firestore_v1_Value value;
|
||||
value.which_value_type = value_tag;
|
||||
value.string_value = nullptr;
|
||||
return value;
|
||||
return MinString();
|
||||
}
|
||||
|
||||
case google_firestore_v1_Value_bytes_value_tag: {
|
||||
google_firestore_v1_Value value;
|
||||
value.which_value_type = value_tag;
|
||||
value.bytes_value = nullptr;
|
||||
return value;
|
||||
return MinBytes();
|
||||
}
|
||||
|
||||
case google_firestore_v1_Value_reference_value_tag: {
|
||||
google_firestore_v1_Value result;
|
||||
result.which_value_type = google_firestore_v1_Value_reference_value_tag;
|
||||
result.reference_value = kMinimumReferenceValue;
|
||||
return result;
|
||||
return MinReference();
|
||||
}
|
||||
|
||||
case google_firestore_v1_Value_geo_point_value_tag: {
|
||||
google_firestore_v1_Value value;
|
||||
value.which_value_type = value_tag;
|
||||
value.geo_point_value.latitude = -90.0;
|
||||
value.geo_point_value.longitude = -180.0;
|
||||
return value;
|
||||
return MinGeoPoint();
|
||||
}
|
||||
|
||||
case google_firestore_v1_Value_array_value_tag: {
|
||||
google_firestore_v1_Value value;
|
||||
value.which_value_type = value_tag;
|
||||
value.array_value.values = nullptr;
|
||||
value.array_value.values_count = 0;
|
||||
return value;
|
||||
return MinArray();
|
||||
}
|
||||
|
||||
case google_firestore_v1_Value_map_value_tag: {
|
||||
google_firestore_v1_Value value;
|
||||
value.which_value_type = value_tag;
|
||||
value.map_value.fields = nullptr;
|
||||
value.map_value.fields_count = 0;
|
||||
return value;
|
||||
if (IsVectorValue(value)) {
|
||||
return MinVector();
|
||||
}
|
||||
|
||||
return MinMap();
|
||||
}
|
||||
|
||||
default:
|
||||
HARD_FAIL("Invalid type value: %s", value_tag);
|
||||
HARD_FAIL("Invalid type value: %s", value.which_value_type);
|
||||
}
|
||||
}
|
||||
|
||||
google_firestore_v1_Value GetUpperBound(pb_size_t value_tag) {
|
||||
switch (value_tag) {
|
||||
google_firestore_v1_Value GetUpperBound(
|
||||
const google_firestore_v1_Value& value) {
|
||||
switch (value.which_value_type) {
|
||||
case google_firestore_v1_Value_null_value_tag:
|
||||
return GetLowerBound(google_protobuf_BoolValue_value_tag);
|
||||
return MinBoolean();
|
||||
case google_firestore_v1_Value_boolean_value_tag:
|
||||
return GetLowerBound(google_firestore_v1_Value_integer_value_tag);
|
||||
return MinNumber();
|
||||
case google_firestore_v1_Value_integer_value_tag:
|
||||
case google_firestore_v1_Value_double_value_tag:
|
||||
return GetLowerBound(google_firestore_v1_Value_timestamp_value_tag);
|
||||
return MinTimestamp();
|
||||
case google_firestore_v1_Value_timestamp_value_tag:
|
||||
return GetLowerBound(google_firestore_v1_Value_string_value_tag);
|
||||
return MinString();
|
||||
case google_firestore_v1_Value_string_value_tag:
|
||||
return GetLowerBound(google_firestore_v1_Value_bytes_value_tag);
|
||||
return MinBytes();
|
||||
case google_firestore_v1_Value_bytes_value_tag:
|
||||
return GetLowerBound(google_firestore_v1_Value_reference_value_tag);
|
||||
return MinReference();
|
||||
case google_firestore_v1_Value_reference_value_tag:
|
||||
return GetLowerBound(google_firestore_v1_Value_geo_point_value_tag);
|
||||
return MinGeoPoint();
|
||||
case google_firestore_v1_Value_geo_point_value_tag:
|
||||
return GetLowerBound(google_firestore_v1_Value_array_value_tag);
|
||||
return MinArray();
|
||||
case google_firestore_v1_Value_array_value_tag:
|
||||
return GetLowerBound(google_firestore_v1_Value_map_value_tag);
|
||||
return MinVector();
|
||||
case google_firestore_v1_Value_map_value_tag:
|
||||
if (IsVectorValue(value)) {
|
||||
return MinMap();
|
||||
}
|
||||
return MaxValue();
|
||||
default:
|
||||
HARD_FAIL("Invalid type value: %s", value_tag);
|
||||
HARD_FAIL("Invalid type value: %s", value.which_value_type);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -693,7 +724,7 @@ google_firestore_v1_Value MaxValue() {
|
||||
"google_firestore_v1_MapValue_FieldsEntry should be "
|
||||
"trivially-destructible; otherwise, it should use NoDestructor below.");
|
||||
static google_firestore_v1_MapValue_FieldsEntry field_entry;
|
||||
field_entry.key = kMaxValueFieldKey;
|
||||
field_entry.key = kTypeValueFieldKey;
|
||||
field_entry.value = value;
|
||||
|
||||
google_firestore_v1_MapValue map_value;
|
||||
@@ -718,9 +749,9 @@ bool IsMaxValue(const google_firestore_v1_Value& value) {
|
||||
|
||||
// Comparing the pointer address, then actual content if addresses are
|
||||
// different.
|
||||
if (value.map_value.fields[0].key != kMaxValueFieldKey &&
|
||||
if (value.map_value.fields[0].key != kTypeValueFieldKey &&
|
||||
nanopb::MakeStringView(value.map_value.fields[0].key) !=
|
||||
kRawMaxValueFieldKey) {
|
||||
kRawTypeValueFieldKey) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -736,6 +767,65 @@ bool IsMaxValue(const google_firestore_v1_Value& value) {
|
||||
kRawMaxValueFieldValue;
|
||||
}
|
||||
|
||||
absl::optional<pb_size_t> IndexOfKey(
|
||||
const google_firestore_v1_MapValue& mapValue,
|
||||
const char* kRawTypeValueFieldKey,
|
||||
pb_bytes_array_s* kTypeValueFieldKey) {
|
||||
for (pb_size_t i = 0; i < mapValue.fields_count; i++) {
|
||||
if (mapValue.fields[i].key == kTypeValueFieldKey ||
|
||||
nanopb::MakeStringView(mapValue.fields[i].key) ==
|
||||
kRawTypeValueFieldKey) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return absl::nullopt;
|
||||
}
|
||||
|
||||
bool IsVectorValue(const google_firestore_v1_Value& value) {
|
||||
if (value.which_value_type != google_firestore_v1_Value_map_value_tag) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (value.map_value.fields_count < 2) {
|
||||
return false;
|
||||
}
|
||||
|
||||
absl::optional<pb_size_t> typeFieldIndex =
|
||||
IndexOfKey(value.map_value, kRawTypeValueFieldKey, kTypeValueFieldKey);
|
||||
if (!typeFieldIndex.has_value()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (value.map_value.fields[typeFieldIndex.value()].value.which_value_type !=
|
||||
google_firestore_v1_Value_string_value_tag) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Comparing the pointer address, then actual content if addresses are
|
||||
// different.
|
||||
if (value.map_value.fields[typeFieldIndex.value()].value.string_value !=
|
||||
kVectorTypeFieldValue &&
|
||||
nanopb::MakeStringView(
|
||||
value.map_value.fields[typeFieldIndex.value()].value.string_value) !=
|
||||
kRawVectorTypeFieldValue) {
|
||||
return false;
|
||||
}
|
||||
|
||||
absl::optional<pb_size_t> valueFieldIndex = IndexOfKey(
|
||||
value.map_value, kRawVectorValueFieldKey, kVectorValueFieldKey);
|
||||
if (!valueFieldIndex.has_value()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (value.map_value.fields[valueFieldIndex.value()].value.which_value_type !=
|
||||
google_firestore_v1_Value_array_value_tag) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
google_firestore_v1_Value NaNValue() {
|
||||
google_firestore_v1_Value nan_value;
|
||||
nan_value.which_value_type = google_firestore_v1_Value_double_value_tag;
|
||||
@@ -748,6 +838,98 @@ bool IsNaNValue(const google_firestore_v1_Value& value) {
|
||||
std::isnan(value.double_value);
|
||||
}
|
||||
|
||||
google_firestore_v1_Value MinBoolean() {
|
||||
google_firestore_v1_Value lowerBound;
|
||||
lowerBound.which_value_type = google_firestore_v1_Value_boolean_value_tag;
|
||||
lowerBound.boolean_value = false;
|
||||
return lowerBound;
|
||||
}
|
||||
|
||||
google_firestore_v1_Value MinNumber() {
|
||||
return NaNValue();
|
||||
}
|
||||
|
||||
google_firestore_v1_Value MinTimestamp() {
|
||||
google_firestore_v1_Value lowerBound;
|
||||
lowerBound.which_value_type = google_firestore_v1_Value_timestamp_value_tag;
|
||||
lowerBound.timestamp_value.seconds = std::numeric_limits<int64_t>::min();
|
||||
lowerBound.timestamp_value.nanos = 0;
|
||||
return lowerBound;
|
||||
}
|
||||
|
||||
google_firestore_v1_Value MinString() {
|
||||
google_firestore_v1_Value lowerBound;
|
||||
lowerBound.which_value_type = google_firestore_v1_Value_string_value_tag;
|
||||
lowerBound.string_value = nullptr;
|
||||
return lowerBound;
|
||||
}
|
||||
|
||||
google_firestore_v1_Value MinBytes() {
|
||||
google_firestore_v1_Value lowerBound;
|
||||
lowerBound.which_value_type = google_firestore_v1_Value_bytes_value_tag;
|
||||
lowerBound.bytes_value = nullptr;
|
||||
return lowerBound;
|
||||
}
|
||||
|
||||
google_firestore_v1_Value MinReference() {
|
||||
google_firestore_v1_Value result;
|
||||
result.which_value_type = google_firestore_v1_Value_reference_value_tag;
|
||||
result.reference_value = kMinimumReferenceValue;
|
||||
return result;
|
||||
}
|
||||
|
||||
google_firestore_v1_Value MinGeoPoint() {
|
||||
google_firestore_v1_Value lowerBound;
|
||||
lowerBound.which_value_type = google_firestore_v1_Value_geo_point_value_tag;
|
||||
lowerBound.geo_point_value.latitude = -90.0;
|
||||
lowerBound.geo_point_value.longitude = -180.0;
|
||||
return lowerBound;
|
||||
}
|
||||
|
||||
google_firestore_v1_Value MinArray() {
|
||||
google_firestore_v1_Value lowerBound;
|
||||
lowerBound.which_value_type = google_firestore_v1_Value_array_value_tag;
|
||||
lowerBound.array_value.values = nullptr;
|
||||
lowerBound.array_value.values_count = 0;
|
||||
return lowerBound;
|
||||
}
|
||||
|
||||
google_firestore_v1_Value MinVector() {
|
||||
google_firestore_v1_Value typeValue;
|
||||
typeValue.which_value_type = google_firestore_v1_Value_string_value_tag;
|
||||
typeValue.string_value = kVectorTypeFieldValue;
|
||||
|
||||
google_firestore_v1_MapValue_FieldsEntry* field_entries =
|
||||
nanopb::MakeArray<google_firestore_v1_MapValue_FieldsEntry>(2);
|
||||
field_entries[0].key = kTypeValueFieldKey;
|
||||
field_entries[0].value = typeValue;
|
||||
|
||||
google_firestore_v1_Value arrayValue;
|
||||
arrayValue.which_value_type = google_firestore_v1_Value_array_value_tag;
|
||||
arrayValue.array_value.values = nullptr;
|
||||
arrayValue.array_value.values_count = 0;
|
||||
field_entries[1].key = kVectorValueFieldKey;
|
||||
field_entries[1].value = arrayValue;
|
||||
|
||||
google_firestore_v1_MapValue map_value;
|
||||
map_value.fields_count = 2;
|
||||
map_value.fields = field_entries;
|
||||
|
||||
google_firestore_v1_Value lowerBound;
|
||||
lowerBound.which_value_type = google_firestore_v1_Value_map_value_tag;
|
||||
lowerBound.map_value = map_value;
|
||||
|
||||
return lowerBound;
|
||||
}
|
||||
|
||||
google_firestore_v1_Value MinMap() {
|
||||
google_firestore_v1_Value lowerBound;
|
||||
lowerBound.which_value_type = google_firestore_v1_Value_map_value_tag;
|
||||
lowerBound.map_value.fields = nullptr;
|
||||
lowerBound.map_value.fields_count = 0;
|
||||
return lowerBound;
|
||||
}
|
||||
|
||||
Message<google_firestore_v1_Value> RefValue(
|
||||
const model::DatabaseId& database_id,
|
||||
const model::DocumentKey& document_key) {
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
|
||||
#include "Firestore/Protos/nanopb/google/firestore/v1/document.nanopb.h"
|
||||
#include "Firestore/core/src/nanopb/message.h"
|
||||
#include "Firestore/core/src/nanopb/nanopb_util.h"
|
||||
#include "absl/types/optional.h"
|
||||
|
||||
namespace firebase {
|
||||
@@ -37,6 +38,25 @@ namespace model {
|
||||
class DocumentKey;
|
||||
class DatabaseId;
|
||||
|
||||
/** The smallest reference value. */
|
||||
extern pb_bytes_array_s* kMinimumReferenceValue;
|
||||
|
||||
/** The field type of a special object type. */
|
||||
extern const char* kRawTypeValueFieldKey;
|
||||
extern pb_bytes_array_s* kTypeValueFieldKey;
|
||||
|
||||
/** The field value of a maximum proto value. */
|
||||
extern const char* kRawMaxValueFieldValue;
|
||||
extern pb_bytes_array_s* kMaxValueFieldValue;
|
||||
|
||||
/** The type of a VectorValue proto. */
|
||||
extern const char* kRawVectorTypeFieldValue;
|
||||
extern pb_bytes_array_s* kVectorTypeFieldValue;
|
||||
|
||||
/** The value key of a VectorValue proto. */
|
||||
extern const char* kRawVectorValueFieldKey;
|
||||
extern pb_bytes_array_s* kVectorValueFieldKey;
|
||||
|
||||
/**
|
||||
* The order of types in Firestore. This order is based on the backend's
|
||||
* ordering, but modified to support server timestamps.
|
||||
@@ -52,8 +72,9 @@ enum class TypeOrder {
|
||||
kReference = 7,
|
||||
kGeoPoint = 8,
|
||||
kArray = 9,
|
||||
kMap = 10,
|
||||
kMaxValue = 11
|
||||
kVector = 10,
|
||||
kMap = 11,
|
||||
kMaxValue = 12
|
||||
};
|
||||
|
||||
/** Returns the backend's type order of the given Value type. */
|
||||
@@ -94,7 +115,7 @@ std::string CanonicalId(const google_firestore_v1_Value& value);
|
||||
* The returned value might point to heap allocated memory that is owned by
|
||||
* this function. To take ownership of this memory, call `DeepClone`.
|
||||
*/
|
||||
google_firestore_v1_Value GetLowerBound(pb_size_t value_tag);
|
||||
google_firestore_v1_Value GetLowerBound(const google_firestore_v1_Value& value);
|
||||
|
||||
/**
|
||||
* Returns the largest value for the given value type (exclusive).
|
||||
@@ -102,7 +123,7 @@ google_firestore_v1_Value GetLowerBound(pb_size_t value_tag);
|
||||
* The returned value might point to heap allocated memory that is owned by
|
||||
* this function. To take ownership of this memory, call `DeepClone`.
|
||||
*/
|
||||
google_firestore_v1_Value GetUpperBound(pb_size_t value_tag);
|
||||
google_firestore_v1_Value GetUpperBound(const google_firestore_v1_Value& value);
|
||||
|
||||
/**
|
||||
* Generates the canonical ID for the provided array value (as used in Target
|
||||
@@ -155,6 +176,22 @@ google_firestore_v1_Value MaxValue();
|
||||
*/
|
||||
bool IsMaxValue(const google_firestore_v1_Value& value);
|
||||
|
||||
/**
|
||||
* Returns `true` if `value` represents a VectorValue..
|
||||
*/
|
||||
bool IsVectorValue(const google_firestore_v1_Value& value);
|
||||
|
||||
/**
|
||||
* Returns the index of the specified key (`kRawTypeValueFieldKey`) in the
|
||||
* map (`mapValue`). `kTypeValueFieldKey` is an alternative representation
|
||||
* of the key specified in `kRawTypeValueFieldKey`.
|
||||
* If the key is not found, then `absl::nullopt` is returned.
|
||||
*/
|
||||
absl::optional<pb_size_t> IndexOfKey(
|
||||
const google_firestore_v1_MapValue& mapValue,
|
||||
const char* kRawTypeValueFieldKey,
|
||||
pb_bytes_array_s* kTypeValueFieldKey);
|
||||
|
||||
/**
|
||||
* Returns `NaN` in its Protobuf representation.
|
||||
*
|
||||
@@ -166,6 +203,26 @@ google_firestore_v1_Value NaNValue();
|
||||
/** Returns `true` if `value` is `NaN` in its Protobuf representation. */
|
||||
bool IsNaNValue(const google_firestore_v1_Value& value);
|
||||
|
||||
google_firestore_v1_Value MinBoolean();
|
||||
|
||||
google_firestore_v1_Value MinNumber();
|
||||
|
||||
google_firestore_v1_Value MinTimestamp();
|
||||
|
||||
google_firestore_v1_Value MinString();
|
||||
|
||||
google_firestore_v1_Value MinBytes();
|
||||
|
||||
google_firestore_v1_Value MinReference();
|
||||
|
||||
google_firestore_v1_Value MinGeoPoint();
|
||||
|
||||
google_firestore_v1_Value MinArray();
|
||||
|
||||
google_firestore_v1_Value MinVector();
|
||||
|
||||
google_firestore_v1_Value MinMap();
|
||||
|
||||
/**
|
||||
* Returns a Protobuf reference value representing the given location.
|
||||
*
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
#include "Firestore/core/src/nanopb/byte_string.h"
|
||||
|
||||
#include <cctype>
|
||||
#include <cstdlib>
|
||||
#include <cstdlib> // NOLINT(build/include_order)
|
||||
#include <cstring>
|
||||
#include <iomanip>
|
||||
#include <ostream>
|
||||
|
||||
@@ -179,6 +179,7 @@ inline NSData* _Nonnull MakeNSData(const ByteString& str) {
|
||||
}
|
||||
|
||||
inline NSData* _Nonnull MakeNSData(const pb_bytes_array_t* _Nullable data) {
|
||||
if (data == nil) return [[NSData alloc] init];
|
||||
return [[NSData alloc] initWithBytes:data->bytes length:data->size];
|
||||
}
|
||||
|
||||
|
||||
@@ -18,8 +18,7 @@
|
||||
|
||||
#if defined(__APPLE__)
|
||||
|
||||
#if TARGET_OS_IOS || TARGET_OS_TV || \
|
||||
(defined(TARGET_OS_VISION) && TARGET_OS_VISION)
|
||||
#if TARGET_OS_IOS || TARGET_OS_TV || TARGET_OS_VISION
|
||||
#import <UIKit/UIKit.h>
|
||||
#endif
|
||||
|
||||
@@ -50,7 +49,7 @@ NetworkStatus ToNetworkStatus(SCNetworkReachabilityFlags flags) {
|
||||
return NetworkStatus::Unavailable;
|
||||
}
|
||||
|
||||
#if TARGET_OS_IPHONE || (defined(TARGET_OS_VISION) && TARGET_OS_VISION)
|
||||
#if TARGET_OS_IPHONE || TARGET_OS_VISION
|
||||
if (flags & kSCNetworkReachabilityFlagsIsWWAN) {
|
||||
return NetworkStatus::AvailableViaCellular;
|
||||
}
|
||||
@@ -113,8 +112,7 @@ class ConnectivityMonitorApple : public ConnectivityMonitor {
|
||||
return;
|
||||
}
|
||||
|
||||
#if TARGET_OS_IOS || TARGET_OS_TV || \
|
||||
(defined(TARGET_OS_VISION) && TARGET_OS_VISION)
|
||||
#if TARGET_OS_IOS || TARGET_OS_TV || TARGET_OS_VISION
|
||||
this->observer_ = [[NSNotificationCenter defaultCenter]
|
||||
addObserverForName:UIApplicationWillEnterForegroundNotification
|
||||
object:nil
|
||||
@@ -126,8 +124,7 @@ class ConnectivityMonitorApple : public ConnectivityMonitor {
|
||||
}
|
||||
|
||||
~ConnectivityMonitorApple() {
|
||||
#if TARGET_OS_IOS || TARGET_OS_TV || \
|
||||
(defined(TARGET_OS_VISION) && TARGET_OS_VISION)
|
||||
#if TARGET_OS_IOS || TARGET_OS_TV || TARGET_OS_VISION
|
||||
[[NSNotificationCenter defaultCenter] removeObserver:this->observer_];
|
||||
#endif
|
||||
|
||||
@@ -142,8 +139,7 @@ class ConnectivityMonitorApple : public ConnectivityMonitor {
|
||||
}
|
||||
}
|
||||
|
||||
#if TARGET_OS_IOS || TARGET_OS_TV || \
|
||||
(defined(TARGET_OS_VISION) && TARGET_OS_VISION)
|
||||
#if TARGET_OS_IOS || TARGET_OS_TV || TARGET_OS_VISION
|
||||
void OnEnteredForeground() {
|
||||
SCNetworkReachabilityFlags flags{};
|
||||
if (!SCNetworkReachabilityGetFlags(reachability_, &flags)) return;
|
||||
@@ -171,8 +167,7 @@ class ConnectivityMonitorApple : public ConnectivityMonitor {
|
||||
|
||||
private:
|
||||
SCNetworkReachabilityRef reachability_ = nil;
|
||||
#if TARGET_OS_IOS || TARGET_OS_TV || \
|
||||
(defined(TARGET_OS_VISION) && TARGET_OS_VISION)
|
||||
#if TARGET_OS_IOS || TARGET_OS_TV || TARGET_OS_VISION
|
||||
id<NSObject> observer_ = nil;
|
||||
#endif
|
||||
};
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
#ifndef FIRESTORE_CORE_SRC_REMOTE_EXPONENTIAL_BACKOFF_H_
|
||||
#define FIRESTORE_CORE_SRC_REMOTE_EXPONENTIAL_BACKOFF_H_
|
||||
|
||||
#include <chrono> // NOLINT(build/c++11)
|
||||
#include <chrono>
|
||||
#include <memory>
|
||||
|
||||
#include "Firestore/core/src/util/async_queue.h"
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
|
||||
#import "FirebaseCore/Extension/FIRAppInternal.h"
|
||||
#import "FirebaseCore/Extension/FIRHeartbeatLogger.h"
|
||||
#import "FirebaseCore/Extension/FIROptionsInternal.h"
|
||||
#import "FirebaseCore/Sources/FIROptionsInternal.h"
|
||||
|
||||
#include "Firestore/core/src/util/string_apple.h"
|
||||
|
||||
|
||||
@@ -17,9 +17,9 @@
|
||||
#ifndef FIRESTORE_CORE_SRC_REMOTE_GRPC_COMPLETION_H_
|
||||
#define FIRESTORE_CORE_SRC_REMOTE_GRPC_COMPLETION_H_
|
||||
|
||||
#include <chrono> // NOLINT(build/c++11)
|
||||
#include <chrono>
|
||||
#include <functional>
|
||||
#include <future> // NOLINT(build/c++11)
|
||||
#include <future>
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
#include <cstdlib>
|
||||
|
||||
#include <algorithm>
|
||||
#include <mutex> // NOLINT(build/c++11)
|
||||
#include <mutex>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -16,8 +16,8 @@
|
||||
|
||||
#include "Firestore/core/src/remote/grpc_stream.h"
|
||||
|
||||
#include <chrono> // NOLINT(build/c++11)
|
||||
#include <future> // NOLINT(build/c++11)
|
||||
#include <chrono>
|
||||
#include <future>
|
||||
|
||||
#include "Firestore/core/src/remote/grpc_connection.h"
|
||||
#include "Firestore/core/src/remote/grpc_util.h"
|
||||
@@ -98,7 +98,7 @@ GrpcStream::GrpcStream(
|
||||
}
|
||||
|
||||
GrpcStream::~GrpcStream() {
|
||||
LOG_DEBUG("GrpcStream('%s'): destroying stream", this);
|
||||
LOG_DEBUG("GrpcStream('%x'): destroying stream", this);
|
||||
HARD_ASSERT(completions_.empty(),
|
||||
"GrpcStream is being destroyed without proper shutdown");
|
||||
MaybeUnregister();
|
||||
@@ -160,14 +160,14 @@ void GrpcStream::MaybeWrite(absl::optional<BufferedWrite> maybe_write) {
|
||||
}
|
||||
|
||||
void GrpcStream::FinishImmediately() {
|
||||
LOG_DEBUG("GrpcStream('%s'): finishing without notifying observers", this);
|
||||
LOG_DEBUG("GrpcStream('%x'): finishing without notifying observers", this);
|
||||
|
||||
Shutdown();
|
||||
UnsetObserver();
|
||||
}
|
||||
|
||||
void GrpcStream::FinishAndNotify(const Status& status) {
|
||||
LOG_DEBUG("GrpcStream('%s'): finishing and notifying observers", this);
|
||||
LOG_DEBUG("GrpcStream('%x'): finishing and notifying observers", this);
|
||||
|
||||
Shutdown();
|
||||
|
||||
@@ -181,7 +181,7 @@ void GrpcStream::FinishAndNotify(const Status& status) {
|
||||
}
|
||||
|
||||
void GrpcStream::Shutdown() {
|
||||
LOG_DEBUG("GrpcStream('%s'): shutting down; completions: %s, is finished: %s",
|
||||
LOG_DEBUG("GrpcStream('%x'): shutting down; completions: %s, is finished: %s",
|
||||
this, completions_.size(), is_grpc_call_finished_);
|
||||
|
||||
MaybeUnregister();
|
||||
@@ -216,7 +216,7 @@ void GrpcStream::MaybeUnregister() {
|
||||
}
|
||||
|
||||
void GrpcStream::FinishGrpcCall(const OnSuccess& callback) {
|
||||
LOG_DEBUG("GrpcStream('%s'): finishing the underlying call", this);
|
||||
LOG_DEBUG("GrpcStream('%x'): finishing the underlying call", this);
|
||||
|
||||
HARD_ASSERT(!is_grpc_call_finished_, "FinishGrpcCall called twice");
|
||||
is_grpc_call_finished_ = true;
|
||||
@@ -229,7 +229,7 @@ void GrpcStream::FinishGrpcCall(const OnSuccess& callback) {
|
||||
}
|
||||
|
||||
void GrpcStream::FastFinishCompletionsBlocking() {
|
||||
LOG_DEBUG("GrpcStream('%s'): fast finishing %s completion(s)", this,
|
||||
LOG_DEBUG("GrpcStream('%x'): fast finishing %s completion(s)", this,
|
||||
completions_.size());
|
||||
|
||||
// TODO(varconst): reset buffered_writer_? Should not be necessary, because it
|
||||
@@ -344,7 +344,7 @@ std::shared_ptr<GrpcCompletion> GrpcStream::NewCompletion(
|
||||
} else {
|
||||
// Use the same error-handling for all operations; all errors are
|
||||
// unrecoverable.
|
||||
LOG_DEBUG("GrpcStream('%s'): operation of type %s failed", this,
|
||||
LOG_DEBUG("GrpcStream('%x'): operation of type %s failed", this,
|
||||
completion->type());
|
||||
OnOperationFailed();
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
#include "Firestore/core/src/remote/online_state_tracker.h"
|
||||
|
||||
#include <chrono> // NOLINT(build/c++11)
|
||||
#include <chrono>
|
||||
|
||||
#include "Firestore/core/src/util/executor.h"
|
||||
#include "Firestore/core/src/util/hard_assert.h"
|
||||
|
||||
@@ -85,14 +85,14 @@ void RemoteStore::Start() {
|
||||
[this](ConnectivityMonitor::NetworkStatus network_status) {
|
||||
if (network_status == ConnectivityMonitor::NetworkStatus::Unavailable) {
|
||||
LOG_DEBUG(
|
||||
"RemoteStore %s ignoring connectivity callback for unavailable "
|
||||
"RemoteStore %x ignoring connectivity callback for unavailable "
|
||||
"network",
|
||||
this);
|
||||
return;
|
||||
}
|
||||
|
||||
if (CanUseNetwork()) {
|
||||
LOG_DEBUG("RemoteStore %s restarting streams as connectivity changed",
|
||||
LOG_DEBUG("RemoteStore %x restarting streams as connectivity changed",
|
||||
this);
|
||||
RestartNetwork();
|
||||
}
|
||||
@@ -139,7 +139,7 @@ void RemoteStore::DisableNetworkInternal() {
|
||||
}
|
||||
|
||||
void RemoteStore::Shutdown() {
|
||||
LOG_DEBUG("RemoteStore %s shutting down", this);
|
||||
LOG_DEBUG("RemoteStore %x shutting down", this);
|
||||
is_network_enabled_ = false;
|
||||
DisableNetworkInternal();
|
||||
|
||||
@@ -514,7 +514,7 @@ void RemoteStore::HandleHandshakeError(const Status& status) {
|
||||
if (Datastore::IsPermanentError(status)) {
|
||||
std::string token = util::ToString(write_stream_->last_stream_token());
|
||||
LOG_DEBUG(
|
||||
"RemoteStore %s error before completed handshake; resetting "
|
||||
"RemoteStore %x error before completed handshake; resetting "
|
||||
"stream token %s: "
|
||||
"error code: '%s', details: '%s'",
|
||||
this, token, status.code(), status.error_message());
|
||||
@@ -590,7 +590,7 @@ void RemoteStore::HandleCredentialChange() {
|
||||
// Tear down and re-create our network streams. This will ensure we get a
|
||||
// fresh auth token for the new user and re-fill the write pipeline with new
|
||||
// mutations from the `LocalStore` (since mutations are per-user).
|
||||
LOG_DEBUG("RemoteStore %s restarting streams for new credential", this);
|
||||
LOG_DEBUG("RemoteStore %x restarting streams for new credential", this);
|
||||
RestartNetwork();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
#include "Firestore/core/src/remote/stream.h"
|
||||
|
||||
#include <chrono> // NOLINT(build/c++11)
|
||||
#include <chrono>
|
||||
#include <utility>
|
||||
|
||||
#include "Firestore/core/include/firebase/firestore/firestore_errors.h"
|
||||
@@ -380,7 +380,7 @@ void Stream::Write(grpc::ByteBuffer&& message) {
|
||||
|
||||
std::string Stream::GetDebugDescription() const {
|
||||
EnsureOnQueue();
|
||||
return StringFormat("%s (%s)", GetDebugName(), this);
|
||||
return StringFormat("%s (%x)", GetDebugName(), this);
|
||||
}
|
||||
|
||||
} // namespace remote
|
||||
|
||||
@@ -56,7 +56,7 @@ class WatchStreamCallback {
|
||||
|
||||
/**
|
||||
* Called by the `WatchStream` with changes and the snapshot versions
|
||||
* included in in the `WatchChange` responses sent back by the server.
|
||||
* included in the `WatchChange` responses sent back by the server.
|
||||
*/
|
||||
virtual void OnWatchStreamChange(
|
||||
const WatchChange& change,
|
||||
|
||||
@@ -20,8 +20,6 @@
|
||||
|
||||
#if defined(__APPLE__)
|
||||
#import <CoreFoundation/CoreFoundation.h>
|
||||
#elif defined(_STLPORT_VERSION)
|
||||
#include <ctime>
|
||||
#endif
|
||||
|
||||
#include "Firestore/core/src/util/hard_assert.h"
|
||||
@@ -76,29 +74,16 @@ Timestamp Timestamp::Now() {
|
||||
auto nanos = static_cast<int32_t>(fraction * kNanosPerSecond);
|
||||
return MakeNormalizedTimestamp(seconds, nanos);
|
||||
|
||||
#elif !defined(_STLPORT_VERSION)
|
||||
// Use the standard <chrono> library from C++11 if possible.
|
||||
return FromTimePoint(std::chrono::system_clock::now());
|
||||
#else
|
||||
// If <chrono> is unavailable, use clock_gettime from POSIX, which supports
|
||||
// up to nanosecond resolution. Note that it's a non-standard function
|
||||
// contained in <time.h>.
|
||||
//
|
||||
// Note: it's possible to check for availability of POSIX clock_gettime using
|
||||
// macros (see "Availability" at https://linux.die.net/man/3/clock_gettime).
|
||||
// However, the only platform where <chrono> isn't available is Android with
|
||||
// STLPort standard library, where clock_gettime is known to be available.
|
||||
timespec now;
|
||||
clock_gettime(CLOCK_REALTIME, &now);
|
||||
return MakeNormalizedTimestamp(now.tv_sec, now.tv_nsec);
|
||||
#endif // !defined(_STLPORT_VERSION)
|
||||
// Use the standard <chrono> library from C++11.
|
||||
return FromTimePoint(std::chrono::system_clock::now());
|
||||
#endif // defined(__APPLE__)
|
||||
}
|
||||
|
||||
Timestamp Timestamp::FromTimeT(const time_t seconds_since_unix_epoch) {
|
||||
return {seconds_since_unix_epoch, 0};
|
||||
}
|
||||
|
||||
#if !defined(_STLPORT_VERSION)
|
||||
Timestamp Timestamp::FromTimePoint(
|
||||
const std::chrono::time_point<std::chrono::system_clock> time_point) {
|
||||
namespace chr = std::chrono;
|
||||
@@ -111,8 +96,6 @@ Timestamp Timestamp::FromTimePoint(
|
||||
return result;
|
||||
}
|
||||
|
||||
#endif // !defined(_STLPORT_VERSION)
|
||||
|
||||
std::string Timestamp::ToString() const {
|
||||
return absl::StrCat("Timestamp(seconds=", seconds_,
|
||||
", nanoseconds=", nanoseconds_, ")");
|
||||
|
||||
@@ -18,10 +18,10 @@
|
||||
#define FIRESTORE_CORE_SRC_UTIL_ASYNC_QUEUE_H_
|
||||
|
||||
#include <atomic>
|
||||
#include <chrono> // NOLINT(build/c++11)
|
||||
#include <chrono>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <mutex> // NOLINT(build/c++11)
|
||||
#include <mutex>
|
||||
#include <vector>
|
||||
|
||||
#include "Firestore/core/src/util/executor.h"
|
||||
|
||||
@@ -17,9 +17,9 @@
|
||||
#ifndef FIRESTORE_CORE_SRC_UTIL_BACKGROUND_QUEUE_H_
|
||||
#define FIRESTORE_CORE_SRC_UTIL_BACKGROUND_QUEUE_H_
|
||||
|
||||
#include <condition_variable> // NOLINT(build/c++11)
|
||||
#include <condition_variable>
|
||||
#include <functional>
|
||||
#include <mutex> // NOLINT(build/c++11)
|
||||
#include <mutex>
|
||||
|
||||
namespace firebase {
|
||||
namespace firestore {
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
#ifndef FIRESTORE_CORE_SRC_UTIL_EXECUTOR_H_
|
||||
#define FIRESTORE_CORE_SRC_UTIL_EXECUTOR_H_
|
||||
|
||||
#include <chrono> // NOLINT(build/c++11)
|
||||
#include <chrono>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
@@ -84,7 +84,7 @@ class Executor {
|
||||
// object prevents any tasks from running that could observe a partially
|
||||
// destroyed object graph.
|
||||
//
|
||||
// Requirements for implementors:
|
||||
// Requirements for implementers:
|
||||
// * Dispose implementations must be idempotent.
|
||||
// * Dispose implementations must exclude concurrent execution of other
|
||||
// methods.
|
||||
|
||||
@@ -19,11 +19,11 @@
|
||||
|
||||
#include <dispatch/dispatch.h>
|
||||
|
||||
#include <chrono> // NOLINT(build/c++11)
|
||||
#include <condition_variable> // NOLINT(build/c++11)
|
||||
#include <chrono>
|
||||
#include <condition_variable>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <mutex> // NOLINT(build/c++11)
|
||||
#include <mutex>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
#include "Firestore/core/src/util/executor_std.h"
|
||||
|
||||
#include <future> // NOLINT(build/c++11)
|
||||
#include <future>
|
||||
#include <memory>
|
||||
#include <sstream>
|
||||
|
||||
|
||||
@@ -19,12 +19,12 @@
|
||||
|
||||
#include <algorithm>
|
||||
#include <atomic>
|
||||
#include <condition_variable> // NOLINT(build/c++11)
|
||||
#include <condition_variable>
|
||||
#include <deque>
|
||||
#include <memory>
|
||||
#include <mutex> // NOLINT(build/c++11)
|
||||
#include <mutex>
|
||||
#include <string>
|
||||
#include <thread> // NOLINT(build/c++11)
|
||||
#include <thread>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
|
||||
@@ -45,8 +45,7 @@ Status Filesystem::ExcludeFromBackups(const Path& dir) {
|
||||
}
|
||||
|
||||
StatusOr<Path> Filesystem::AppDataDir(absl::string_view app_name) {
|
||||
#if TARGET_OS_IOS || TARGET_OS_OSX || \
|
||||
(defined(TARGET_OS_VISION) && TARGET_OS_VISION)
|
||||
#if TARGET_OS_IOS || TARGET_OS_OSX || TARGET_OS_VISION
|
||||
NSArray<NSString*>* directories = NSSearchPathForDirectoriesInDomains(
|
||||
NSApplicationSupportDirectory, NSUserDomainMask, YES);
|
||||
return Path::FromNSString(directories[0]).AppendUtf8(app_name);
|
||||
@@ -62,7 +61,7 @@ StatusOr<Path> Filesystem::AppDataDir(absl::string_view app_name) {
|
||||
}
|
||||
|
||||
StatusOr<Path> Filesystem::LegacyDocumentsDir(absl::string_view app_name) {
|
||||
#if TARGET_OS_IOS || (defined(TARGET_OS_VISION) && TARGET_OS_VISION)
|
||||
#if TARGET_OS_IOS || TARGET_OS_VISION
|
||||
NSArray<NSString*>* directories = NSSearchPathForDirectoriesInDomains(
|
||||
NSDocumentDirectory, NSUserDomainMask, YES);
|
||||
return Path::FromNSString(directories[0]).AppendUtf8(app_name);
|
||||
|
||||
@@ -132,7 +132,7 @@ Path Filesystem::TempDir() {
|
||||
|
||||
#if !__APPLE__
|
||||
Status Filesystem::IsDirectory(const Path& path) {
|
||||
struct stat buffer {};
|
||||
struct stat buffer{};
|
||||
if (::stat(path.c_str(), &buffer)) {
|
||||
if (errno == ENOENT) {
|
||||
// Expected common error case.
|
||||
@@ -168,7 +168,7 @@ Status Filesystem::IsDirectory(const Path& path) {
|
||||
}
|
||||
|
||||
StatusOr<int64_t> Filesystem::FileSize(const Path& path) {
|
||||
struct stat st {};
|
||||
struct stat st{};
|
||||
if (::stat(path.c_str(), &st) == 0) {
|
||||
return st.st_size;
|
||||
} else {
|
||||
|
||||
@@ -28,13 +28,11 @@
|
||||
#include "Firestore/core/include/firebase/firestore/firestore_errors.h"
|
||||
|
||||
#if defined(__ANDROID__)
|
||||
// Abseil does not support STLPort, so avoid their config.h here.
|
||||
//
|
||||
// TODO(b/163140650): Remove once the Firebase support floor moves to NDK R18.
|
||||
//
|
||||
// Meanwhile, NDK R16b (the current minimum) includes Clang 5.0.3 and GCC 4.9.
|
||||
// While Clang supports `__cpp_exceptions` at that version, GCC does not. Both
|
||||
// support `__EXCEPTIONS`.
|
||||
// The firebase-cpp-sdk has issues compiling Abseil on Android in some cases;
|
||||
// therefore, use `__EXCEPTIONS`, which is known to be set by clang in Android
|
||||
// NDK r21e, instead of using `ABSL_HAVE_EXCEPTIONS`. In the future, consider
|
||||
// using `__cpp_exceptions` instead, as the internet seems to suggest that it
|
||||
// is more reliable with modern c++ compilers, such as those in NDK r21e.
|
||||
#if __EXCEPTIONS
|
||||
#define FIRESTORE_HAVE_EXCEPTIONS 1
|
||||
#endif
|
||||
|
||||
@@ -190,8 +190,8 @@ auto RankedInvokeHash(const Range& range, HashChoice<3>)
|
||||
* value can itself be hashed.
|
||||
*/
|
||||
template <typename K>
|
||||
auto RankedInvokeHash(const absl::optional<K>& option,
|
||||
HashChoice<4>) -> decltype(InvokeHash(*option)) {
|
||||
auto RankedInvokeHash(const absl::optional<K>& option, HashChoice<4>)
|
||||
-> decltype(InvokeHash(*option)) {
|
||||
return option ? InvokeHash(*option) : -1171;
|
||||
}
|
||||
|
||||
@@ -202,8 +202,8 @@ size_t RankedInvokeHash(K value, HashChoice<5>) {
|
||||
}
|
||||
|
||||
template <typename K>
|
||||
auto RankedInvokeHash(const std::unique_ptr<K>& ptr,
|
||||
HashChoice<6>) -> decltype(InvokeHash(*ptr)) {
|
||||
auto RankedInvokeHash(const std::unique_ptr<K>& ptr, HashChoice<6>)
|
||||
-> decltype(InvokeHash(*ptr)) {
|
||||
return ptr ? InvokeHash(*ptr) : 23631;
|
||||
}
|
||||
|
||||
|
||||
@@ -35,39 +35,46 @@ namespace {
|
||||
|
||||
const FIRLoggerService kFIRLoggerFirestore = @"[FirebaseFirestore]";
|
||||
|
||||
// Translates a C++ LogLevel to the equivalent Objective-C FIRLoggerLevel
|
||||
FIRLoggerLevel ToFIRLoggerLevel(LogLevel level) {
|
||||
switch (level) {
|
||||
case kLogLevelDebug:
|
||||
return FIRLoggerLevelDebug;
|
||||
case kLogLevelNotice:
|
||||
return FIRLoggerLevelNotice;
|
||||
case kLogLevelWarning:
|
||||
return FIRLoggerLevelWarning;
|
||||
case kLogLevelError:
|
||||
return FIRLoggerLevelError;
|
||||
default:
|
||||
// Unsupported log level. FIRSetLoggerLevel will deal with it.
|
||||
return static_cast<FIRLoggerLevel>(-1);
|
||||
}
|
||||
}
|
||||
|
||||
// Actually logs a message via FIRLogger. This must be a C varargs function
|
||||
// so that we can call FIRLogBasic which takes a `va_list`.
|
||||
void LogMessageV(LogLevel level, NSString* format, ...) {
|
||||
va_list list;
|
||||
va_start(list, format);
|
||||
|
||||
FIRLogBasic(ToFIRLoggerLevel(level), kFIRLoggerFirestore, @"I-FST000001",
|
||||
format, list);
|
||||
|
||||
switch (level) {
|
||||
case kLogLevelDebug:
|
||||
FIRLogBasicDebug(kFIRLoggerFirestore, @"I-FST000001", format, list);
|
||||
break;
|
||||
case kLogLevelNotice:
|
||||
FIRLogBasicNotice(kFIRLoggerFirestore, @"I-FST000001", format, list);
|
||||
break;
|
||||
case kLogLevelWarning:
|
||||
FIRLogBasicWarning(kFIRLoggerFirestore, @"I-FST000001", format, list);
|
||||
break;
|
||||
case kLogLevelError:
|
||||
FIRLogBasicError(kFIRLoggerFirestore, @"I-FST000001", format, list);
|
||||
break;
|
||||
}
|
||||
va_end(list);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
void LogSetLevel(LogLevel level) {
|
||||
FIRSetLoggerLevel(ToFIRLoggerLevel(level));
|
||||
switch (level) {
|
||||
case kLogLevelDebug:
|
||||
FIRSetLoggerLevelDebug();
|
||||
break;
|
||||
case kLogLevelNotice:
|
||||
FIRSetLoggerLevelNotice();
|
||||
break;
|
||||
case kLogLevelWarning:
|
||||
FIRSetLoggerLevelWarning();
|
||||
break;
|
||||
case kLogLevelError:
|
||||
FIRSetLoggerLevelError();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Note that FIRLogger's default level can be changed by persisting a
|
||||
@@ -81,7 +88,17 @@ void LogSetLevel(LogLevel level) {
|
||||
// defaults write firestore_util_test /google/firebase/debug_mode NO
|
||||
|
||||
bool LogIsLoggable(LogLevel level) {
|
||||
return FIRIsLoggableLevel(ToFIRLoggerLevel(level), false);
|
||||
switch (level) {
|
||||
case kLogLevelDebug:
|
||||
return FIRIsLoggableLevelDebug();
|
||||
case kLogLevelNotice:
|
||||
return FIRIsLoggableLevelNotice();
|
||||
case kLogLevelWarning:
|
||||
return FIRIsLoggableLevelWarning();
|
||||
case kLogLevelError:
|
||||
return FIRIsLoggableLevelError();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void LogMessage(LogLevel level, const std::string& message) {
|
||||
|
||||
@@ -18,9 +18,9 @@
|
||||
#define FIRESTORE_CORE_SRC_UTIL_SCHEDULE_H_
|
||||
|
||||
#include <algorithm>
|
||||
#include <condition_variable> // NOLINT(build/c++11)
|
||||
#include <condition_variable>
|
||||
#include <deque>
|
||||
#include <mutex> // NOLINT(build/c++11)
|
||||
#include <mutex>
|
||||
#include <vector>
|
||||
|
||||
#include "Firestore/core/src/util/executor.h"
|
||||
|
||||
@@ -16,6 +16,10 @@
|
||||
|
||||
#include "Firestore/core/src/util/string_format.h"
|
||||
|
||||
#include <string>
|
||||
#include "absl/strings/escaping.h"
|
||||
#include "absl/strings/string_view.h"
|
||||
|
||||
namespace firebase {
|
||||
namespace firestore {
|
||||
namespace util {
|
||||
@@ -24,7 +28,13 @@ namespace internal {
|
||||
static const char* kMissing = "<missing>";
|
||||
static const char* kInvalid = "<invalid>";
|
||||
|
||||
std::string StringFormatPieces(
|
||||
// Disable asan for this function because of the way it manages stack
|
||||
// (nested closure) is flagged with stack underflow by clang on Ubuntu.
|
||||
#if defined(_MSC_VER)
|
||||
__declspec(no_sanitize_address) std::string StringFormatPieces(
|
||||
#else
|
||||
__attribute__((no_sanitize_address)) std::string StringFormatPieces(
|
||||
#endif
|
||||
const char* format, std::initializer_list<absl::string_view> pieces) {
|
||||
std::string result;
|
||||
|
||||
@@ -33,7 +43,7 @@ std::string StringFormatPieces(
|
||||
|
||||
auto pieces_iter = pieces.begin();
|
||||
auto pieces_end = pieces.end();
|
||||
auto append_next_piece = [&](std::string* dest) {
|
||||
auto append_next_string_piece = [&](std::string* dest) {
|
||||
if (pieces_iter == pieces_end) {
|
||||
dest->append(kMissing);
|
||||
} else {
|
||||
@@ -43,6 +53,17 @@ std::string StringFormatPieces(
|
||||
}
|
||||
};
|
||||
|
||||
auto append_next_hex_piece = [&](std::string* dest) {
|
||||
if (pieces_iter == pieces_end) {
|
||||
dest->append(kMissing);
|
||||
} else {
|
||||
std::string hex =
|
||||
absl::BytesToHexString(absl::string_view(pieces_iter->data()));
|
||||
dest->append(hex.data(), hex.size());
|
||||
++pieces_iter;
|
||||
}
|
||||
};
|
||||
|
||||
auto append_specifier = [&](char spec) {
|
||||
switch (spec) {
|
||||
case '%':
|
||||
@@ -51,7 +72,12 @@ std::string StringFormatPieces(
|
||||
break;
|
||||
|
||||
case 's': {
|
||||
append_next_piece(&result);
|
||||
append_next_string_piece(&result);
|
||||
break;
|
||||
}
|
||||
|
||||
case 'x': {
|
||||
append_next_hex_piece(&result);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@@ -62,11 +62,20 @@ struct FormatChoice<5> {};
|
||||
* formatting of the value as an unsigned integer.
|
||||
* * Otherwise the value is interpreted as anything absl::AlphaNum accepts.
|
||||
*/
|
||||
class FormatArg : public absl::AlphaNum {
|
||||
class FormatArg final : public absl::AlphaNum {
|
||||
public:
|
||||
template <typename T>
|
||||
FormatArg(T&& value) // NOLINT(runtime/explicit)
|
||||
: FormatArg{std::forward<T>(value), internal::FormatChoice<0>{}} {
|
||||
FormatArg(
|
||||
T&& value,
|
||||
// TODO(b/388888512) Remove the usage of StringifySink since it is not
|
||||
// part of absl's public API. Moreover, subclassing AlphaNum is not
|
||||
// supported either, so find a way to do this without these two caveats.
|
||||
// See https://github.com/firebase/firebase-ios-sdk/pull/14331 for a
|
||||
// partial proposal.
|
||||
absl::strings_internal::StringifySink&& sink =
|
||||
{}) // NOLINT(runtime/explicit)
|
||||
: FormatArg{std::forward<T>(value), std::move(sink),
|
||||
internal::FormatChoice<0>{}} {
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -79,7 +88,9 @@ class FormatArg : public absl::AlphaNum {
|
||||
*/
|
||||
template <typename T,
|
||||
typename = typename std::enable_if<std::is_same<bool, T>{}>::type>
|
||||
FormatArg(T bool_value, internal::FormatChoice<0>)
|
||||
FormatArg(T bool_value,
|
||||
absl::strings_internal::StringifySink&&,
|
||||
internal::FormatChoice<0>)
|
||||
: AlphaNum(bool_value ? "true" : "false") {
|
||||
}
|
||||
|
||||
@@ -90,7 +101,9 @@ class FormatArg : public absl::AlphaNum {
|
||||
template <
|
||||
typename T,
|
||||
typename = typename std::enable_if<objc::is_objc_pointer<T>{}>::type>
|
||||
FormatArg(T object, internal::FormatChoice<1>)
|
||||
FormatArg(T object,
|
||||
absl::strings_internal::StringifySink&&,
|
||||
internal::FormatChoice<1>)
|
||||
: AlphaNum(MakeStringView([object description])) {
|
||||
}
|
||||
|
||||
@@ -98,7 +111,9 @@ class FormatArg : public absl::AlphaNum {
|
||||
* Creates a FormatArg from any Objective-C Class type. Objective-C Class
|
||||
* types are a special struct that aren't of a type derived from NSObject.
|
||||
*/
|
||||
FormatArg(Class object, internal::FormatChoice<1>)
|
||||
FormatArg(Class object,
|
||||
absl::strings_internal::StringifySink&&,
|
||||
internal::FormatChoice<1>)
|
||||
: AlphaNum(MakeStringView(NSStringFromClass(object))) {
|
||||
}
|
||||
#endif
|
||||
@@ -108,7 +123,10 @@ class FormatArg : public absl::AlphaNum {
|
||||
* handled specially to avoid ambiguity with generic pointers, which are
|
||||
* handled differently.
|
||||
*/
|
||||
FormatArg(std::nullptr_t, internal::FormatChoice<2>) : AlphaNum("null") {
|
||||
FormatArg(std::nullptr_t,
|
||||
absl::strings_internal::StringifySink&&,
|
||||
internal::FormatChoice<2>)
|
||||
: AlphaNum("null") {
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -116,7 +134,9 @@ class FormatArg : public absl::AlphaNum {
|
||||
* handled specially to avoid ambiguity with generic pointers, which are
|
||||
* handled differently.
|
||||
*/
|
||||
FormatArg(const char* string_value, internal::FormatChoice<3>)
|
||||
FormatArg(const char* string_value,
|
||||
absl::strings_internal::StringifySink&&,
|
||||
internal::FormatChoice<3>)
|
||||
: AlphaNum(string_value == nullptr ? "null" : string_value) {
|
||||
}
|
||||
|
||||
@@ -125,8 +145,11 @@ class FormatArg : public absl::AlphaNum {
|
||||
* hexadecimal integer literal.
|
||||
*/
|
||||
template <typename T>
|
||||
FormatArg(T* pointer_value, internal::FormatChoice<4>)
|
||||
: AlphaNum(absl::Hex(reinterpret_cast<uintptr_t>(pointer_value))) {
|
||||
FormatArg(T* pointer_value,
|
||||
absl::strings_internal::StringifySink&& sink,
|
||||
internal::FormatChoice<4>)
|
||||
: AlphaNum(absl::Hex(reinterpret_cast<uintptr_t>(pointer_value)),
|
||||
std::move(sink)) {
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -134,7 +157,9 @@ class FormatArg : public absl::AlphaNum {
|
||||
* absl::AlphaNum accepts.
|
||||
*/
|
||||
template <typename T>
|
||||
FormatArg(T&& value, internal::FormatChoice<5>)
|
||||
FormatArg(T&& value,
|
||||
absl::strings_internal::StringifySink&&,
|
||||
internal::FormatChoice<5>)
|
||||
: AlphaNum(std::forward<T>(value)) {
|
||||
}
|
||||
};
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
#include "Firestore/core/src/util/task.h"
|
||||
|
||||
#include <chrono> // NOLINT(build/c++11)
|
||||
#include <chrono>
|
||||
#include <cstdint>
|
||||
#include <utility>
|
||||
|
||||
|
||||
@@ -18,10 +18,10 @@
|
||||
#define FIRESTORE_CORE_SRC_UTIL_TASK_H_
|
||||
|
||||
#include <atomic>
|
||||
#include <condition_variable> // NOLINT(build/c++11)
|
||||
#include <condition_variable>
|
||||
#include <memory>
|
||||
#include <mutex> // NOLINT(build/c++11)
|
||||
#include <thread> // NOLINT(build/c++11)
|
||||
#include <mutex>
|
||||
#include <thread>
|
||||
|
||||
#include "Firestore/core/src/util/executor.h"
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
#include "Firestore/core/src/util/testing_hooks.h"
|
||||
|
||||
#include <functional>
|
||||
#include <mutex> // NOLINT(build/c++11)
|
||||
#include <mutex>
|
||||
#include <type_traits>
|
||||
#include <unordered_map>
|
||||
#include <utility>
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <mutex> // NOLINT(build/c++11)
|
||||
#include <mutex>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2023 Google
|
||||
* Copyright 2025 Google LLC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -18,8 +18,10 @@
|
||||
#define FIRESTORE_CORE_SRC_UTIL_THREAD_SAFE_MEMOIZER_H_
|
||||
|
||||
#include <functional>
|
||||
#include <mutex> // NOLINT(build/c++11)
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
|
||||
#include "Firestore/core/src/util/hard_assert.h"
|
||||
|
||||
namespace firebase {
|
||||
namespace firestore {
|
||||
@@ -28,51 +30,135 @@ namespace util {
|
||||
/**
|
||||
* Stores a memoized value in a manner that is safe to be shared between
|
||||
* multiple threads.
|
||||
*
|
||||
* TODO(b/299933587) Make `ThreadSafeMemoizer` copyable and moveable.
|
||||
*/
|
||||
template <typename T>
|
||||
class ThreadSafeMemoizer {
|
||||
public:
|
||||
ThreadSafeMemoizer() = default;
|
||||
|
||||
~ThreadSafeMemoizer() {
|
||||
// Call `std::call_once` in order to synchronize with the "active"
|
||||
// invocation of `memoize()`. Without this synchronization, there is a data
|
||||
// race between this destructor, which "reads" `memoized_value_` to destroy
|
||||
// it, and the write to `memoized_value_` done by the "active" invocation of
|
||||
// `memoize()`.
|
||||
std::call_once(once_, [&]() {});
|
||||
/**
|
||||
* Creates a new ThreadSafeMemoizer with no memoized value.
|
||||
*/
|
||||
ThreadSafeMemoizer() {
|
||||
std::atomic_store(&memoized_, std::shared_ptr<T>());
|
||||
}
|
||||
|
||||
// This class cannot be copied or moved, because it has `std::once_flag`
|
||||
// member.
|
||||
ThreadSafeMemoizer(const ThreadSafeMemoizer&) = delete;
|
||||
ThreadSafeMemoizer(ThreadSafeMemoizer&&) = delete;
|
||||
ThreadSafeMemoizer& operator=(const ThreadSafeMemoizer&) = delete;
|
||||
ThreadSafeMemoizer& operator=(ThreadSafeMemoizer&&) = delete;
|
||||
/**
|
||||
* Copy constructor: creates a new ThreadSafeMemoizer object with the same
|
||||
* memoized value as the ThreadSafeMemoizer object referred to by the given
|
||||
* reference.
|
||||
*
|
||||
* The runtime performance of this function is O(1).
|
||||
*/
|
||||
ThreadSafeMemoizer(const ThreadSafeMemoizer& other) {
|
||||
operator=(other);
|
||||
}
|
||||
|
||||
/**
|
||||
* Memoize a value.
|
||||
* Copy assignment operator: replaces this object's memoized value with the
|
||||
* memoized value of the ThreadSafeMemoizer object referred to by the given
|
||||
* reference.
|
||||
*
|
||||
* The std::function object specified by the first invocation of this
|
||||
* function (the "active" invocation) will be invoked synchronously.
|
||||
* None of the std::function objects specified by the subsequent
|
||||
* invocations of this function (the "passive" invocations) will be
|
||||
* invoked. All invocations, both "active" and "passive", will return a
|
||||
* reference to the std::vector created by copying the return value from
|
||||
* the std::function specified by the "active" invocation. It is,
|
||||
* therefore, the "active" invocation's job to return the std::vector
|
||||
* to memoize.
|
||||
* The runtime performance of this function is O(1).
|
||||
*/
|
||||
const T& memoize(std::function<T()> func) {
|
||||
std::call_once(once_, [&]() { memoized_value_ = func(); });
|
||||
return memoized_value_;
|
||||
ThreadSafeMemoizer& operator=(const ThreadSafeMemoizer& other) {
|
||||
if (&other == this) {
|
||||
return *this;
|
||||
}
|
||||
|
||||
std::atomic_store(&memoized_, std::atomic_load(&other.memoized_));
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Move constructor: creates a new ThreadSafeMemoizer object with the same
|
||||
* memoized value as the ThreadSafeMemoizer object referred to by the given
|
||||
* reference, also clearing its memoized value.
|
||||
*
|
||||
* The runtime performance of this function is O(1).
|
||||
*/
|
||||
ThreadSafeMemoizer(ThreadSafeMemoizer&& other) noexcept {
|
||||
operator=(std::move(other));
|
||||
}
|
||||
|
||||
/**
|
||||
* Move assignment operator: replaces this object's memoized value with the
|
||||
* memoized value of the ThreadSafeMemoizer object referred to by the given
|
||||
* reference, also clearing its memoized value.
|
||||
*
|
||||
* The runtime performance of this function is O(1).
|
||||
*/
|
||||
ThreadSafeMemoizer& operator=(ThreadSafeMemoizer&& other) noexcept {
|
||||
std::atomic_store(&memoized_, std::atomic_load(&other.memoized_));
|
||||
std::atomic_store(&other.memoized_, std::shared_ptr<T>());
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the memoized value, calculating it with the given function if
|
||||
* needed.
|
||||
*
|
||||
* If this object _does_ have a memoized value then this function simply
|
||||
* returns a reference to it and does _not_ call the given function.
|
||||
*
|
||||
* On the other hand, if this object does _not_ have a memoized value then
|
||||
* the given function is called to calculate the value to memoize. The value
|
||||
* returned by the function is stored internally as the "memoized value" and
|
||||
* then returned. If multiple threads race in calls to this function then
|
||||
* more than one of them may have their functions called but only one of them
|
||||
* will be memoized, with the others being discarded.
|
||||
*
|
||||
* The given function will be called synchronously by this function either
|
||||
* zero times or one time. No reference to the given function is retained by
|
||||
* this object.
|
||||
*
|
||||
* The given function _must_ return an initialized `std::shared_ptr<T>`; that
|
||||
* is, the returned `std::shared_ptr<T>` _must_ evaluate to `true` when
|
||||
* converted to `bool`. It is undefined behavior if the returned
|
||||
* `std::shared_ptr<T>` does _not_ satisfy this requirement.
|
||||
*
|
||||
* This function is thread-safe and may be called concurrently by multiple
|
||||
* threads.
|
||||
*
|
||||
* The returned reference is "valid" only as long as this `ThreadSafeMemoizer`
|
||||
* object is alive; namely, once this `ThreadSafeMemoizer` object's destructor
|
||||
* starts running, the reference returned by this function is invalid and
|
||||
* using it is undefined behavior.
|
||||
*/
|
||||
const T& value(const std::function<std::shared_ptr<T>()>& func) {
|
||||
std::shared_ptr<T> old_memoized = std::atomic_load(&memoized_);
|
||||
|
||||
std::shared_ptr<T> new_memoized;
|
||||
bool new_memoized_is_initialized = false;
|
||||
|
||||
while (true) {
|
||||
if (old_memoized) {
|
||||
return *old_memoized;
|
||||
}
|
||||
|
||||
if (!new_memoized_is_initialized) {
|
||||
new_memoized = func();
|
||||
new_memoized_is_initialized = true;
|
||||
HARD_ASSERT(new_memoized);
|
||||
}
|
||||
|
||||
if (std::atomic_compare_exchange_weak(&memoized_, &old_memoized,
|
||||
new_memoized)) {
|
||||
return *new_memoized;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
std::once_flag once_;
|
||||
T memoized_value_;
|
||||
// NOTE: Always use the std::atomic_XXX() functions to access the memoized_
|
||||
// std::shared_ptr to ensure thread safety.
|
||||
// See https://en.cppreference.com/w/cpp/memory/shared_ptr/atomic.
|
||||
|
||||
// TODO(c++20): Use std::atomic<std::shared_ptr<T>> instead of a bare
|
||||
// std::shared_ptr<T> and the std::atomic_XXX() functions. The
|
||||
// std::atomic_XXX() free functions are deprecated in C++20, and are also
|
||||
// more error-prone than their std::atomic<std::shared_ptr<T>> member
|
||||
// function counterparts.
|
||||
|
||||
std::shared_ptr<T> memoized_;
|
||||
};
|
||||
|
||||
} // namespace util
|
||||
|
||||
12
Pods/FirebaseFirestoreInternal/Firestore/third_party/nlohmann_json/json.hpp
generated
vendored
12
Pods/FirebaseFirestoreInternal/Firestore/third_party/nlohmann_json/json.hpp
generated
vendored
@@ -5142,7 +5142,7 @@ auto input_adapter(T (&array)[N]) -> decltype(input_adapter(array, array + N))
|
||||
}
|
||||
|
||||
// This class only handles inputs of input_buffer_adapter type.
|
||||
// It's required so that expressions like {ptr, len} can be implicitely casted
|
||||
// It's required so that expressions like {ptr, len} can be implicitly casted
|
||||
// to the correct adapter.
|
||||
class span_input_adapter
|
||||
{
|
||||
@@ -9916,7 +9916,7 @@ class binary_reader
|
||||
|
||||
@return whether conversion completed
|
||||
|
||||
@note This function needs to respect the system's endianess, because
|
||||
@note This function needs to respect the system's endianness, because
|
||||
bytes in CBOR, MessagePack, and UBJSON are stored in network order
|
||||
(big endian) and therefore need reordering on little endian systems.
|
||||
*/
|
||||
@@ -10088,7 +10088,7 @@ class binary_reader
|
||||
/// the number of characters read
|
||||
std::size_t chars_read = 0;
|
||||
|
||||
/// whether we can assume little endianess
|
||||
/// whether we can assume little endianness
|
||||
const bool is_little_endian = little_endianess();
|
||||
|
||||
/// the SAX parser
|
||||
@@ -14227,7 +14227,7 @@ class binary_writer
|
||||
@tparam OutputIsLittleEndian Set to true if output data is
|
||||
required to be little endian
|
||||
|
||||
@note This function needs to respect the system's endianess, because bytes
|
||||
@note This function needs to respect the system's endianness, because bytes
|
||||
in CBOR, MessagePack, and UBJSON are stored in network order (big
|
||||
endian) and therefore need reordering on little endian systems.
|
||||
*/
|
||||
@@ -14310,7 +14310,7 @@ class binary_writer
|
||||
}
|
||||
|
||||
private:
|
||||
/// whether we can assume little endianess
|
||||
/// whether we can assume little endianness
|
||||
const bool is_little_endian = little_endianess();
|
||||
|
||||
/// the output
|
||||
@@ -21337,7 +21337,7 @@ class basic_json
|
||||
`key()` returns an empty string.
|
||||
|
||||
@warning Using `items()` on temporary objects is dangerous. Make sure the
|
||||
object's lifetime exeeds the iteration. See
|
||||
object's lifetime exceeds the iteration. See
|
||||
<https://github.com/nlohmann/json/issues/2040> for more
|
||||
information.
|
||||
|
||||
|
||||
11
Pods/FirebaseFirestoreInternal/README.md
generated
11
Pods/FirebaseFirestoreInternal/README.md
generated
@@ -86,7 +86,7 @@ For details on using Firebase from a Framework or a library, refer to [firebase_
|
||||
To develop Firebase software in this repository, ensure that you have at least
|
||||
the following software:
|
||||
|
||||
* Xcode 14.1 (or later)
|
||||
* Xcode 16.2 (or later)
|
||||
|
||||
CocoaPods is still the canonical way to develop, but much of the repo now supports
|
||||
development with Swift Package Manager.
|
||||
@@ -137,7 +137,7 @@ Alternatively, disable signing in each target:
|
||||
|
||||
### Adding a New Firebase Pod
|
||||
|
||||
Refer to [AddNewPod](AddNewPod.md) Markdown file for details.
|
||||
Refer to [AddNewPod](docs/AddNewPod.md) Markdown file for details.
|
||||
|
||||
### Managing Headers and Imports
|
||||
|
||||
@@ -153,7 +153,7 @@ GitHub Actions will verify that any code changes are done in a style-compliant
|
||||
way. Install `clang-format` and `mint`:
|
||||
|
||||
```console
|
||||
brew install clang-format@18
|
||||
brew install clang-format@20
|
||||
brew install mint
|
||||
```
|
||||
|
||||
@@ -235,6 +235,11 @@ at **Project Settings > Cloud Messaging > [Your Firebase App]**.
|
||||
The iOS Simulator cannot register for remote notifications and will not receive push notifications.
|
||||
To receive push notifications, follow the steps above and run the app on a physical device.
|
||||
|
||||
### Vertex AI for Firebase
|
||||
|
||||
See the [Vertex AI for Firebase README](FirebaseVertexAI#development) for
|
||||
instructions about building and testing the SDK.
|
||||
|
||||
## Building with Firebase on Apple platforms
|
||||
|
||||
Firebase provides official beta support for macOS, Catalyst, and tvOS. visionOS and watchOS
|
||||
|
||||
Reference in New Issue
Block a user