Path: blob/main/SignalServiceKit/Storage/Database/SDSSerializable.swift
1 views
//
// Copyright 2019 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
//
import Foundation
import GRDB
func convertDateForGrdb(_ value: Date) -> Double {
return value.timeIntervalSince1970
}
// MARK: - SDSSerializer
public protocol SDSSerializer {
func asRecord() -> SDSRecord
}
// MARK: - SDSSerializer Helpers
public extension SDSSerializer {
// MARK: - Numeric Primitive
func archiveOptionalNSNumber<T>(_ value: NSNumber?, conversion: (NSNumber) -> T) -> T? {
guard let value else {
return nil
}
return conversion(value)
}
func archiveNSNumber<T>(_ value: NSNumber, conversion: (NSNumber) -> T) -> T {
return conversion(value)
}
// MARK: - Date
func archiveOptionalDate(_ value: Date?) -> Double? {
guard let value else {
return nil
}
return archiveDate(value)
}
func archiveDate(_ value: Date) -> Double {
return convertDateForGrdb(value)
}
// MARK: - Blob
func optionalArchive<T: NSObject & NSSecureCoding>(_ value: T?) -> Data? {
guard let value else {
return nil
}
return requiredArchive(value)
}
func optionalArchive(_ value: [SignalServiceAddress: TSOutgoingMessageRecipientState]?) -> Data? {
return optionalArchive(value as NSDictionary?)
}
func optionalArchive(_ value: [InfoMessageUserInfoKey: Any]?) -> Data? {
return optionalArchive(value as NSDictionary?)
}
/// Avoid the cost of actually archiving empty string arrays that are
/// declared optional (e.g. TSInteraction.attachmentIds)
func optionalArchive(_ value: [String]?) -> Data? {
guard let value, !value.isEmpty else {
return nil
}
return requiredArchive(value as [NSString] as NSArray)
}
/// Avoide the cost of actually archiving empty message body range objects.
func optionalArchive(_ value: MessageBodyRanges?) -> Data? {
guard let value, value.hasRanges else {
return nil
}
return requiredArchive(value)
}
func requiredArchive<T: NSObject & NSSecureCoding>(_ value: [T]) -> Data {
return requiredArchive(value as NSArray)
}
func requiredArchive<T: NSObject & NSSecureCoding>(_ value: T) -> Data {
return try! NSKeyedArchiver.archivedData(withRootObject: value, requiringSecureCoding: true)
}
}