diff --git a/Signal/src/AppDelegate.m b/Signal/src/AppDelegate.m index 79438d5ee..367869aad 100644 --- a/Signal/src/AppDelegate.m +++ b/Signal/src/AppDelegate.m @@ -244,8 +244,7 @@ static NSString *const kURLHostVerifyPrefix = @"verify"; }]; self.incomingMessageReadObserver = - [[OWSIncomingMessageReadObserver alloc] initWithStorageManager:[TSStorageManager sharedManager] - messageSender:[Environment getCurrent].messageSender]; + [[OWSIncomingMessageReadObserver alloc] initWithMessageSender:[Environment getCurrent].messageSender]; [self.incomingMessageReadObserver startObserving]; self.staleNotificationObserver = [OWSStaleNotificationObserver new]; diff --git a/Signal/src/util/AppUpdateNag.m b/Signal/src/util/AppUpdateNag.m index 111c8afae..cf33e81e6 100644 --- a/Signal/src/util/AppUpdateNag.m +++ b/Signal/src/util/AppUpdateNag.m @@ -14,7 +14,7 @@ NSString *const TSStorageManagerAppUpgradeNagDate = @"TSStorageManagerAppUpgrade @interface AppUpdateNag () -@property (nonatomic, readonly) TSStorageManager *storageManager; +@property (nonatomic, readonly) YapDatabaseConnection *dbConnection; @end @@ -49,7 +49,7 @@ NSString *const TSStorageManagerAppUpgradeNagDate = @"TSStorageManagerAppUpgrade OWSAssert(storageManager); - _storageManager = storageManager; + _dbConnection = storageManager.newDatabaseConnection; OWSSingletonAssert(); @@ -68,9 +68,9 @@ NSString *const TSStorageManagerAppUpgradeNagDate = @"TSStorageManagerAppUpgrade if (!canPresent) { return; } - - NSDate *lastNagDate = [[TSStorageManager sharedManager] dateForKey:TSStorageManagerAppUpgradeNagDate - inCollection:TSStorageManagerAppUpgradeNagCollection]; + + NSDate *lastNagDate = [self.dbConnection dateForKey:TSStorageManagerAppUpgradeNagDate + inCollection:TSStorageManagerAppUpgradeNagCollection]; const NSTimeInterval kNagFrequency = kDayInterval * 14; BOOL canNag = (!lastNagDate || fabs(lastNagDate.timeIntervalSinceNow) > kNagFrequency); if (!canNag) { @@ -96,9 +96,9 @@ NSString *const TSStorageManagerAppUpgradeNagDate = @"TSStorageManagerAppUpgrade { DDLogInfo(@"%@ %s", self.tag, __PRETTY_FUNCTION__); - [[TSStorageManager sharedManager] setDate:[NSDate new] - forKey:TSStorageManagerAppUpgradeNagDate - inCollection:TSStorageManagerAppUpgradeNagCollection]; + [self.dbConnection setDate:[NSDate new] + forKey:TSStorageManagerAppUpgradeNagDate + inCollection:TSStorageManagerAppUpgradeNagCollection]; } - (void)appUpdaterUserDidLaunchAppStore diff --git a/SignalServiceKit/src/Messages/OWSBlockingManager.m b/SignalServiceKit/src/Messages/OWSBlockingManager.m index ba9e61e70..6ec156920 100644 --- a/SignalServiceKit/src/Messages/OWSBlockingManager.m +++ b/SignalServiceKit/src/Messages/OWSBlockingManager.m @@ -20,7 +20,7 @@ NSString *const kOWSBlockingManager_SyncedBlockedPhoneNumbersKey = @"kOWSBlockin @interface OWSBlockingManager () -@property (nonatomic, readonly) TSStorageManager *storageManager; +@property (nonatomic, readonly) YapDatabaseConnection *dbConnection; @property (nonatomic, readonly) OWSMessageSender *messageSender; // We don't store the phone numbers as instances of PhoneNumber to avoid @@ -63,7 +63,7 @@ NSString *const kOWSBlockingManager_SyncedBlockedPhoneNumbersKey = @"kOWSBlockin OWSAssert(storageManager); OWSAssert(messageSender); - _storageManager = storageManager; + _dbConnection = storageManager.newDatabaseConnection; _messageSender = messageSender; OWSSingletonAssert(); @@ -173,9 +173,9 @@ NSString *const kOWSBlockingManager_SyncedBlockedPhoneNumbersKey = @"kOWSBlockin { NSArray *blockedPhoneNumbers = [self blockedPhoneNumbers]; - [_storageManager setObject:blockedPhoneNumbers - forKey:kOWSBlockingManager_BlockedPhoneNumbersKey - inCollection:kOWSBlockingManager_BlockedPhoneNumbersCollection]; + [self.dbConnection setObject:blockedPhoneNumbers + forKey:kOWSBlockingManager_BlockedPhoneNumbersKey + inCollection:kOWSBlockingManager_BlockedPhoneNumbersCollection]; dispatch_async(dispatch_get_main_queue(), ^{ if (sendSyncMessage) { @@ -211,8 +211,8 @@ NSString *const kOWSBlockingManager_SyncedBlockedPhoneNumbersKey = @"kOWSBlockin } NSArray *blockedPhoneNumbers = - [_storageManager objectForKey:kOWSBlockingManager_BlockedPhoneNumbersKey - inCollection:kOWSBlockingManager_BlockedPhoneNumbersCollection]; + [self.dbConnection objectForKey:kOWSBlockingManager_BlockedPhoneNumbersKey + inCollection:kOWSBlockingManager_BlockedPhoneNumbersCollection]; _blockedPhoneNumberSet = [[NSMutableSet alloc] initWithArray:(blockedPhoneNumbers ?: [NSArray new])]; [self syncBlockedPhoneNumbersIfNecessary]; @@ -227,8 +227,8 @@ NSString *const kOWSBlockingManager_SyncedBlockedPhoneNumbersKey = @"kOWSBlockin // If we haven't yet successfully synced the current "blocked phone numbers" changes, // try again to sync now. NSArray *syncedBlockedPhoneNumbers = - [_storageManager objectForKey:kOWSBlockingManager_SyncedBlockedPhoneNumbersKey - inCollection:kOWSBlockingManager_BlockedPhoneNumbersCollection]; + [self.dbConnection objectForKey:kOWSBlockingManager_SyncedBlockedPhoneNumbersKey + inCollection:kOWSBlockingManager_BlockedPhoneNumbersCollection]; NSSet *syncedBlockedPhoneNumberSet = [[NSSet alloc] initWithArray:(syncedBlockedPhoneNumbers ?: [NSArray new])]; if (![_blockedPhoneNumberSet isEqualToSet:syncedBlockedPhoneNumberSet]) { DDLogInfo(@"%@ retrying sync of blocked phone numbers", self.tag); @@ -262,9 +262,9 @@ NSString *const kOWSBlockingManager_SyncedBlockedPhoneNumbersKey = @"kOWSBlockin OWSAssert(blockedPhoneNumbers); // Record the last set of "blocked phone numbers" which we successfully synced. - [_storageManager setObject:blockedPhoneNumbers - forKey:kOWSBlockingManager_SyncedBlockedPhoneNumbersKey - inCollection:kOWSBlockingManager_BlockedPhoneNumbersCollection]; + [self.dbConnection setObject:blockedPhoneNumbers + forKey:kOWSBlockingManager_SyncedBlockedPhoneNumbersKey + inCollection:kOWSBlockingManager_BlockedPhoneNumbersCollection]; } #pragma mark - Notifications diff --git a/SignalServiceKit/src/Messages/OWSDisappearingMessagesJob.m b/SignalServiceKit/src/Messages/OWSDisappearingMessagesJob.m index 269ac80ea..9bee45deb 100644 --- a/SignalServiceKit/src/Messages/OWSDisappearingMessagesJob.m +++ b/SignalServiceKit/src/Messages/OWSDisappearingMessagesJob.m @@ -18,8 +18,6 @@ NS_ASSUME_NONNULL_BEGIN @interface OWSDisappearingMessagesJob () -@property (nonatomic, readonly) TSStorageManager *storageManager; - @property (nonatomic, readonly) YapDatabaseConnection *databaseConnection; @property (nonatomic, readonly) OWSDisappearingMessagesFinder *disappearingMessagesFinder; @@ -52,7 +50,6 @@ NS_ASSUME_NONNULL_BEGIN return self; } - _storageManager = storageManager; _databaseConnection = storageManager.newDatabaseConnection; _disappearingMessagesFinder = [OWSDisappearingMessagesFinder new]; diff --git a/SignalServiceKit/src/Messages/OWSIdentityManager.m b/SignalServiceKit/src/Messages/OWSIdentityManager.m index e71da5174..31f7a6fc3 100644 --- a/SignalServiceKit/src/Messages/OWSIdentityManager.m +++ b/SignalServiceKit/src/Messages/OWSIdentityManager.m @@ -50,6 +50,7 @@ NSString *const kNSNotificationName_IdentityStateDidChange = @"kNSNotificationNa @interface OWSIdentityManager () @property (nonatomic, readonly) TSStorageManager *storageManager; +@property (nonatomic, readonly) YapDatabaseConnection *dbConnection; @property (nonatomic, readonly) OWSMessageSender *messageSender; @end @@ -89,6 +90,7 @@ NSString *const kNSNotificationName_IdentityStateDidChange = @"kNSNotificationNa OWSAssert(messageSender); _storageManager = storageManager; + _dbConnection = storageManager.newDatabaseConnection; _messageSender = messageSender; OWSSingletonAssert(); @@ -113,9 +115,9 @@ NSString *const kNSNotificationName_IdentityStateDidChange = @"kNSNotificationNa - (void)generateNewIdentityKey { - [self.storageManager setObject:[Curve25519 generateKeyPair] - forKey:TSStorageManagerIdentityKeyStoreIdentityKey - inCollection:TSStorageManagerIdentityKeyStoreCollection]; + [self.dbConnection setObject:[Curve25519 generateKeyPair] + forKey:TSStorageManagerIdentityKeyStoreIdentityKey + inCollection:TSStorageManagerIdentityKeyStoreCollection]; } - (nullable NSData *)identityKeyForRecipientId:(NSString *)recipientId @@ -128,8 +130,8 @@ NSString *const kNSNotificationName_IdentityStateDidChange = @"kNSNotificationNa - (nullable ECKeyPair *)identityKeyPair { - return [self.storageManager keyPairForKey:TSStorageManagerIdentityKeyStoreIdentityKey - inCollection:TSStorageManagerIdentityKeyStoreCollection]; + return [self.dbConnection keyPairForKey:TSStorageManagerIdentityKeyStoreIdentityKey + inCollection:TSStorageManagerIdentityKeyStoreCollection]; } - (int)localRegistrationId @@ -148,9 +150,7 @@ NSString *const kNSNotificationName_IdentityStateDidChange = @"kNSNotificationNa // decisions, but it's desirable to try to keep it up to date with our trusted identitys // while we're switching between versions, e.g. so we don't get into a state where we have a // session for an identity not in our key store. - [self.storageManager setObject:identityKey - forKey:recipientId - inCollection:TSStorageManagerTrustedKeysCollection]; + [self.dbConnection setObject:identityKey forKey:recipientId inCollection:TSStorageManagerTrustedKeysCollection]; OWSRecipientIdentity *existingIdentity = [OWSRecipientIdentity fetchObjectWithUniqueID:recipientId]; @@ -415,7 +415,7 @@ NSString *const kNSNotificationName_IdentityStateDidChange = @"kNSNotificationNa [messages addObject:[TSErrorMessage nonblockingIdentityChangeInThread:groupThread recipientId:recipientId]]; } - [self.storageManager.dbReadWriteConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) { + [self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) { for (TSMessage *message in messages) { [message saveWithTransaction:transaction]; } @@ -429,9 +429,9 @@ NSString *const kNSNotificationName_IdentityStateDidChange = @"kNSNotificationNa dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ @synchronized(self) { - [self.storageManager setObject:recipientId - forKey:recipientId - inCollection:OWSIdentityManager_QueuedVerificationStateSyncMessages]; + [self.dbConnection setObject:recipientId + forKey:recipientId + inCollection:OWSIdentityManager_QueuedVerificationStateSyncMessages]; } dispatch_async(dispatch_get_main_queue(), ^{ @@ -455,8 +455,7 @@ NSString *const kNSNotificationName_IdentityStateDidChange = @"kNSNotificationNa @synchronized(self) { NSMutableArray *recipientIds = [NSMutableArray new]; - [self.storageManager.dbReadWriteConnection readWriteWithBlock:^( - YapDatabaseReadWriteTransaction *transaction) { + [self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) { [transaction enumerateKeysAndObjectsInCollection:OWSIdentityManager_QueuedVerificationStateSyncMessages usingBlock:^(NSString *_Nonnull recipientId, id _Nonnull object, @@ -558,8 +557,8 @@ NSString *const kNSNotificationName_IdentityStateDidChange = @"kNSNotificationNa dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ @synchronized(self) { - [self.storageManager removeObjectForKey:recipientId - inCollection:OWSIdentityManager_QueuedVerificationStateSyncMessages]; + [self.dbConnection removeObjectForKey:recipientId + inCollection:OWSIdentityManager_QueuedVerificationStateSyncMessages]; } }); } @@ -742,7 +741,7 @@ NSString *const kNSNotificationName_IdentityStateDidChange = @"kNSNotificationNa isLocalChange:isLocalChange]]; } - [self.storageManager.dbReadWriteConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) { + [self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) { for (TSMessage *message in messages) { [message saveWithTransaction:transaction]; } diff --git a/SignalServiceKit/src/Messages/OWSIncomingMessageReadObserver.h b/SignalServiceKit/src/Messages/OWSIncomingMessageReadObserver.h index 2067031a9..f33cf5480 100644 --- a/SignalServiceKit/src/Messages/OWSIncomingMessageReadObserver.h +++ b/SignalServiceKit/src/Messages/OWSIncomingMessageReadObserver.h @@ -1,5 +1,6 @@ -// Created by Michael Kirk on 9/24/16. -// Copyright © 2016 Open Whisper Systems. All rights reserved. +// +// Copyright (c) 2017 Open Whisper Systems. All rights reserved. +// NS_ASSUME_NONNULL_BEGIN @@ -9,8 +10,7 @@ NS_ASSUME_NONNULL_BEGIN @interface OWSIncomingMessageReadObserver : NSObject - (instancetype)init NS_UNAVAILABLE; -- (instancetype)initWithStorageManager:(TSStorageManager *)storageManager - messageSender:(OWSMessageSender *)messageSender NS_DESIGNATED_INITIALIZER; +- (instancetype)initWithMessageSender:(OWSMessageSender *)messageSender NS_DESIGNATED_INITIALIZER; - (void)startObserving; diff --git a/SignalServiceKit/src/Messages/OWSIncomingMessageReadObserver.m b/SignalServiceKit/src/Messages/OWSIncomingMessageReadObserver.m index 20c581e4d..81c21de35 100644 --- a/SignalServiceKit/src/Messages/OWSIncomingMessageReadObserver.m +++ b/SignalServiceKit/src/Messages/OWSIncomingMessageReadObserver.m @@ -23,8 +23,7 @@ NS_ASSUME_NONNULL_BEGIN [[NSNotificationCenter defaultCenter] removeObserver:self]; } -- (instancetype)initWithStorageManager:(TSStorageManager *)storageManager - messageSender:(OWSMessageSender *)messageSender +- (instancetype)initWithMessageSender:(OWSMessageSender *)messageSender { self = [super init]; if (!self) { diff --git a/SignalServiceKit/src/Profiles/OWSProfilesManager.m b/SignalServiceKit/src/Profiles/OWSProfilesManager.m index d110b7cf9..61b7284e8 100644 --- a/SignalServiceKit/src/Profiles/OWSProfilesManager.m +++ b/SignalServiceKit/src/Profiles/OWSProfilesManager.m @@ -87,8 +87,8 @@ static const NSInteger kProfileKeyLength = 16; @interface OWSProfilesManager () -@property (nonatomic, readonly) TSStorageManager *storageManager; @property (nonatomic, readonly) OWSMessageSender *messageSender; +@property (nonatomic, readonly) YapDatabaseConnection *dbConnection; @property (atomic, readonly, nullable) NSData *localProfileKey; @@ -136,8 +136,8 @@ static const NSInteger kProfileKeyLength = 16; OWSAssert(storageManager); OWSAssert(messageSender); - _storageManager = storageManager; _messageSender = messageSender; + _dbConnection = storageManager.newDatabaseConnection; OWSSingletonAssert(); @@ -146,13 +146,13 @@ static const NSInteger kProfileKeyLength = 16; [messageSender setProfilesManager:self]; // Try to load. - _localProfileKey = [self.storageManager objectForKey:kOWSProfilesManager_LocalProfileSecretKey + _localProfileKey = [self.dbConnection objectForKey:kOWSProfilesManager_LocalProfileSecretKey inCollection:kOWSProfilesManager_Collection]; if (!_localProfileKey) { // Generate _localProfileKey = [OWSProfilesManager generateLocalProfileKey]; // Persist - [self.storageManager setObject:_localProfileKey + [self.dbConnection setObject:_localProfileKey forKey:kOWSProfilesManager_LocalProfileSecretKey inCollection:kOWSProfilesManager_Collection]; } @@ -214,20 +214,20 @@ static const NSInteger kProfileKeyLength = 16; self.localProfileAvatarMetadata = localProfileAvatarMetadata; if (localProfileName) { - [self.storageManager setObject:localProfileName - forKey:kOWSProfilesManager_LocalProfileNameKey - inCollection:kOWSProfilesManager_Collection]; + [self.dbConnection setObject:localProfileName + forKey:kOWSProfilesManager_LocalProfileNameKey + inCollection:kOWSProfilesManager_Collection]; } else { - [self.storageManager removeObjectForKey:kOWSProfilesManager_LocalProfileNameKey - inCollection:kOWSProfilesManager_Collection]; + [self.dbConnection removeObjectForKey:kOWSProfilesManager_LocalProfileNameKey + inCollection:kOWSProfilesManager_Collection]; } if (localProfileAvatarMetadata) { - [self.storageManager setObject:localProfileAvatarMetadata - forKey:kOWSProfilesManager_LocalProfileAvatarMetadataKey - inCollection:kOWSProfilesManager_Collection]; + [self.dbConnection setObject:localProfileAvatarMetadata + forKey:kOWSProfilesManager_LocalProfileAvatarMetadataKey + inCollection:kOWSProfilesManager_Collection]; } else { - [self.storageManager removeObjectForKey:kOWSProfilesManager_LocalProfileAvatarMetadataKey - inCollection:kOWSProfilesManager_Collection]; + [self.dbConnection removeObjectForKey:kOWSProfilesManager_LocalProfileAvatarMetadataKey + inCollection:kOWSProfilesManager_Collection]; } [[NSNotificationCenter defaultCenter] postNotificationName:kNSNotificationName_LocalProfileDidChange @@ -378,11 +378,11 @@ static const NSInteger kProfileKeyLength = 16; - (void)loadLocalProfileAsync { dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ - NSString *_Nullable localProfileName = [self.storageManager objectForKey:kOWSProfilesManager_LocalProfileNameKey - inCollection:kOWSProfilesManager_Collection]; + NSString *_Nullable localProfileName = [self.dbConnection objectForKey:kOWSProfilesManager_LocalProfileNameKey + inCollection:kOWSProfilesManager_Collection]; AvatarMetadata *_Nullable localProfileAvatarMetadata = - [self.storageManager objectForKey:kOWSProfilesManager_LocalProfileAvatarMetadataKey - inCollection:kOWSProfilesManager_Collection]; + [self.dbConnection objectForKey:kOWSProfilesManager_LocalProfileAvatarMetadataKey + inCollection:kOWSProfilesManager_Collection]; UIImage *_Nullable localProfileAvatarImage = nil; if (localProfileAvatarMetadata) { localProfileAvatarImage = [self loadProfileAvatarWithFilename:localProfileAvatarMetadata.fileName]; diff --git a/SignalServiceKit/src/Storage/TSStorageManager.h b/SignalServiceKit/src/Storage/TSStorageManager.h index 6c39745ec..4af7e44cc 100644 --- a/SignalServiceKit/src/Storage/TSStorageManager.h +++ b/SignalServiceKit/src/Storage/TSStorageManager.h @@ -3,7 +3,7 @@ // #import "TSStorageKeys.h" - +#import "YapDatabaseConnection+OWS.h" #import #import diff --git a/SignalServiceKit/src/Storage/YapDatabaseConnection+OWS.h b/SignalServiceKit/src/Storage/YapDatabaseConnection+OWS.h new file mode 100644 index 000000000..a568529bb --- /dev/null +++ b/SignalServiceKit/src/Storage/YapDatabaseConnection+OWS.h @@ -0,0 +1,37 @@ +// +// Copyright (c) 2017 Open Whisper Systems. All rights reserved. +// + +#import + +@class ECKeyPair; +@class PreKeyRecord; +@class SignedPreKeyRecord; + +NS_ASSUME_NONNULL_BEGIN + +@interface YapDatabaseConnection (OWS) + +- (BOOL)boolForKey:(NSString *)key inCollection:(NSString *)collection; +- (int)intForKey:(NSString *)key inCollection:(NSString *)collection; +- (nullable id)objectForKey:(NSString *)key inCollection:(NSString *)collection; +- (nullable NSDate *)dateForKey:(NSString *)key inCollection:(NSString *)collection; +- (nullable NSDictionary *)dictionaryForKey:(NSString *)key inCollection:(NSString *)collection; +- (nullable NSString *)stringForKey:(NSString *)key inCollection:(NSString *)collection; +- (nullable NSData *)dataForKey:(NSString *)key inCollection:(NSString *)collection; +- (nullable ECKeyPair *)keyPairForKey:(NSString *)key inCollection:(NSString *)collection; +- (nullable PreKeyRecord *)preKeyRecordForKey:(NSString *)key inCollection:(NSString *)collection; +- (nullable SignedPreKeyRecord *)signedPreKeyRecordForKey:(NSString *)key inCollection:(NSString *)collection; + +#pragma mark - + +- (void)setObject:(id)object forKey:(NSString *)key inCollection:(NSString *)collection; +- (void)removeObjectForKey:(NSString *)string inCollection:(NSString *)collection; +- (void)setInt:(int)integer forKey:(NSString *)key inCollection:(NSString *)collection; +- (void)setDate:(NSDate *)value forKey:(NSString *)key inCollection:(NSString *)collection; +- (void)purgeCollection:(NSString *)collection; +- (int)incrementIntForKey:(NSString *)key inCollection:(NSString *)collection; + +@end + +NS_ASSUME_NONNULL_END diff --git a/SignalServiceKit/src/Storage/YapDatabaseConnection+OWS.m b/SignalServiceKit/src/Storage/YapDatabaseConnection+OWS.m new file mode 100644 index 000000000..acf2c3c29 --- /dev/null +++ b/SignalServiceKit/src/Storage/YapDatabaseConnection+OWS.m @@ -0,0 +1,143 @@ +// +// Copyright (c) 2017 Open Whisper Systems. All rights reserved. +// + +#import "YapDatabaseConnection+OWS.h" +#import <25519/Curve25519.h> +#import +#import +#import + +NS_ASSUME_NONNULL_BEGIN + +@implementation YapDatabaseConnection (OWS) + +- (nullable id)objectForKey:(NSString *)key inCollection:(NSString *)collection +{ + OWSAssert(key.length > 0); + OWSAssert(collection.length > 0); + + __block NSString *_Nullable object; + + [self readWithBlock:^(YapDatabaseReadTransaction *transaction) { + object = [transaction objectForKey:key inCollection:collection]; + }]; + + return object; +} + +- (nullable id)objectForKey:(NSString *)key inCollection:(NSString *)collection ofExpectedType:(Class) class { + id _Nullable value = [self objectForKey:key inCollection:collection]; + OWSAssert(!value || [value isKindOfClass:class]); + return value; +} + + - (nullable NSDictionary *)dictionaryForKey : (NSString *)key inCollection : (NSString *)collection +{ + return [self objectForKey:key inCollection:collection ofExpectedType:[NSDictionary class]]; +} + +- (nullable NSString *)stringForKey:(NSString *)key inCollection:(NSString *)collection +{ + return [self objectForKey:key inCollection:collection ofExpectedType:[NSString class]]; +} + +- (BOOL)boolForKey:(NSString *)key inCollection:(NSString *)collection +{ + NSNumber *_Nullable number = [self objectForKey:key inCollection:collection ofExpectedType:[NSNumber class]]; + return [number boolValue]; +} + +- (nullable NSData *)dataForKey:(NSString *)key inCollection:(NSString *)collection +{ + return [self objectForKey:key inCollection:collection ofExpectedType:[NSData class]]; +} + +- (nullable ECKeyPair *)keyPairForKey:(NSString *)key inCollection:(NSString *)collection +{ + return [self objectForKey:key inCollection:collection ofExpectedType:[ECKeyPair class]]; +} + +- (nullable PreKeyRecord *)preKeyRecordForKey:(NSString *)key inCollection:(NSString *)collection +{ + return [self objectForKey:key inCollection:collection ofExpectedType:[PreKeyRecord class]]; +} + +- (nullable SignedPreKeyRecord *)signedPreKeyRecordForKey:(NSString *)key inCollection:(NSString *)collection +{ + return [self objectForKey:key inCollection:collection ofExpectedType:[SignedPreKeyRecord class]]; +} + +- (int)intForKey:(NSString *)key inCollection:(NSString *)collection +{ + NSNumber *_Nullable number = [self objectForKey:key inCollection:collection ofExpectedType:[NSNumber class]]; + return [number intValue]; +} + +- (nullable NSDate *)dateForKey:(NSString *)key inCollection:(NSString *)collection +{ + NSNumber *_Nullable value = [self objectForKey:key inCollection:collection ofExpectedType:[NSNumber class]]; + if (value) { + return [NSDate dateWithTimeIntervalSince1970:value.doubleValue]; + } else { + return nil; + } +} + +#pragma mark - + +- (void)purgeCollection:(NSString *)collection +{ + [self readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) { + [transaction removeAllObjectsInCollection:collection]; + }]; +} + +- (void)setObject:(id)object forKey:(NSString *)key inCollection:(NSString *)collection +{ + OWSAssert(object); + OWSAssert(key.length > 0); + OWSAssert(collection.length > 0); + + [self readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) { + [transaction setObject:object forKey:key inCollection:collection]; + }]; +} + +- (void)removeObjectForKey:(NSString *)key inCollection:(NSString *)collection +{ + OWSAssert(key.length > 0); + OWSAssert(collection.length > 0); + + [self readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) { + [transaction removeObjectForKey:key inCollection:collection]; + }]; +} + +- (void)setInt:(int)integer forKey:(NSString *)key inCollection:(NSString *)collection +{ + OWSAssert(key.length > 0); + OWSAssert(collection.length > 0); + + [self setObject:@(integer) forKey:key inCollection:collection]; +} + +- (int)incrementIntForKey:(NSString *)key inCollection:(NSString *)collection +{ + __block int value = 0; + [self readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) { + value = [[transaction objectForKey:key inCollection:collection] intValue]; + value++; + [transaction setObject:@(value) forKey:key inCollection:collection]; + }]; + return value; +} + +- (void)setDate:(NSDate *)value forKey:(NSString *)key inCollection:(NSString *)collection +{ + [self setObject:@(value.timeIntervalSince1970) forKey:key inCollection:collection]; +} + +@end + +NS_ASSUME_NONNULL_END