From 9f6d9d8a43f852d436b9b10fd2b6e214b661fc46 Mon Sep 17 00:00:00 2001 From: NachoSoto Date: Thu, 22 Jun 2023 12:36:20 -0700 Subject: [PATCH] Refactored `Data.asString` implementation This was duplicated with the `hexString` implementation, which is also memory efficient. Also renamed the file and removed any unnecessary references to `NSData` --- RevenueCat.xcodeproj/project.pbxproj | 8 +++--- .../Data+Extensions.swift | 25 +++++-------------- ...sTests.swift => DataExtensionsTests.swift} | 12 ++++----- ...ReceiptParsing+TestsWithRealReceipts.swift | 4 +-- .../PurchasesSubscriberAttributesTests.swift | 2 +- .../SubscriberAttributesManagerTests.swift | 9 +++---- 6 files changed, 21 insertions(+), 39 deletions(-) rename Tests/UnitTests/FoundationExtensions/{NSData+RCExtensionsTests.swift => DataExtensionsTests.swift} (88%) diff --git a/RevenueCat.xcodeproj/project.pbxproj b/RevenueCat.xcodeproj/project.pbxproj index ec2b3a7005..03b741c2b9 100644 --- a/RevenueCat.xcodeproj/project.pbxproj +++ b/RevenueCat.xcodeproj/project.pbxproj @@ -542,7 +542,7 @@ B302206E2728B798008F1A0D /* BackendErrorStrings.swift in Sources */ = {isa = PBXBuildFile; fileRef = B302206D2728B798008F1A0D /* BackendErrorStrings.swift */; }; B3022072272B3DDC008F1A0D /* DescribableError.swift in Sources */ = {isa = PBXBuildFile; fileRef = B3022071272B3DDC008F1A0D /* DescribableError.swift */; }; B3083A132699334C007B5503 /* Offering.swift in Sources */ = {isa = PBXBuildFile; fileRef = B3083A122699334C007B5503 /* Offering.swift */; }; - B319514926C19856002CA9AC /* NSData+RCExtensionsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37E35ABEE9FD79CCA64E4F8B /* NSData+RCExtensionsTests.swift */; }; + B319514926C19856002CA9AC /* DataExtensionsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37E35ABEE9FD79CCA64E4F8B /* DataExtensionsTests.swift */; }; B319514B26C1991E002CA9AC /* base64EncodedReceiptSampleForDataExtension.txt in Resources */ = {isa = PBXBuildFile; fileRef = B319514A26C1991E002CA9AC /* base64EncodedReceiptSampleForDataExtension.txt */; }; B31C8BEC285BD58F001017B7 /* MockIdentityAPI.swift in Sources */ = {isa = PBXBuildFile; fileRef = B31C8BEB285BD58F001017B7 /* MockIdentityAPI.swift */; }; B31C8BEF285BDD76001017B7 /* MockIdentityAPI.swift in Sources */ = {isa = PBXBuildFile; fileRef = B31C8BEB285BD58F001017B7 /* MockIdentityAPI.swift */; }; @@ -904,7 +904,7 @@ 37E3582920E16E065502E5FC /* EntitlementInfosTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EntitlementInfosTests.swift; sourceTree = ""; }; 37E3583675928C01D92E3166 /* ProductRequestDataExtensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ProductRequestDataExtensions.swift; sourceTree = ""; }; 37E359D8F304C83184560135 /* CustomerInfoTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CustomerInfoTests.swift; sourceTree = ""; }; - 37E35ABEE9FD79CCA64E4F8B /* NSData+RCExtensionsTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NSData+RCExtensionsTests.swift"; sourceTree = ""; }; + 37E35ABEE9FD79CCA64E4F8B /* DataExtensionsTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DataExtensionsTests.swift; sourceTree = ""; }; 37E35B08709090FBBFB16EBD /* MockProductsRequest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MockProductsRequest.swift; sourceTree = ""; }; 37E35B9AC7A350CA2437049D /* ISOPeriodFormatterTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ISOPeriodFormatterTests.swift; sourceTree = ""; }; 37E35C1554F296F7F1317747 /* MockAppleReceiptBuilder.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MockAppleReceiptBuilder.swift; sourceTree = ""; }; @@ -2044,13 +2044,13 @@ children = ( 572247F627BF1ADF00C524A7 /* ArrayExtensionsTests.swift */, 57069A5D28E398E100B86355 /* AsyncExtensionsTests.swift */, + 37E35ABEE9FD79CCA64E4F8B /* DataExtensionsTests.swift */, 37E3508EC20EEBAB4EAC4C82 /* DateExtensionsTests.swift */, 37E35FDA0A44EA03EA12DAA2 /* DateFormatter+ExtensionsTests.swift */, 57ACB13628184CF1000DCC9F /* DecoderExtensionTests.swift */, 2DD269162522A20A006AC4BC /* DictionaryExtensionsTests.swift */, 57910CB229C3889B006209D5 /* DispatchTimeIntervalExtensionsTests.swift */, 4F5C05BE2A43A2C500651C7D /* LocaleExtensionsTests.swift */, - 37E35ABEE9FD79CCA64E4F8B /* NSData+RCExtensionsTests.swift */, 37E353AF2CAD3CEDE6D9B368 /* NSError+RCExtensionsTests.swift */, 5766AA41283C768600FA6091 /* OperatorExtensionsTests.swift */, 5759B321296DEF56002472D5 /* OptionalExtensionsTests.swift */, @@ -3527,7 +3527,7 @@ 2DDF41CE24F6F4C3005BC22D /* InAppPurchaseBuilderTests.swift in Sources */, 573A10DB2800AF4700F976E5 /* PurchaseErrorTests.swift in Sources */, 351B513F26D4496000BD2BD7 /* MockIdentityManager.swift in Sources */, - B319514926C19856002CA9AC /* NSData+RCExtensionsTests.swift in Sources */, + B319514926C19856002CA9AC /* DataExtensionsTests.swift in Sources */, 5733B1A427FF9F8300EC2045 /* NetworkErrorTests.swift in Sources */, 351B517026D44E8D00BD2BD7 /* MockDateProvider.swift in Sources */, 57FDAAC028493C13009A48F1 /* MockSandboxEnvironmentDetector.swift in Sources */, diff --git a/Sources/FoundationExtensions/Data+Extensions.swift b/Sources/FoundationExtensions/Data+Extensions.swift index b009d2708a..0ca29f9ebe 100644 --- a/Sources/FoundationExtensions/Data+Extensions.swift +++ b/Sources/FoundationExtensions/Data+Extensions.swift @@ -17,28 +17,15 @@ import CommonCrypto import CryptoKit import Foundation -extension NSData { - - func asString() -> String { - // 2 characters per byte - let deviceTokenString = NSMutableString(capacity: self.length * 2) - - self.enumerateBytes { bytes, byteRange, _ in - for index in stride(from: 0, to: byteRange.length, by: 1) { - let byte = bytes.load(fromByteOffset: index, as: UInt8.self) - deviceTokenString.appendFormat("%02x", byte) - } - } - - return deviceTokenString as String - } - -} - extension Data { var asString: String { - return (self as NSData).asString() + return Self.hexString( + self + .lazy + .map { $0 } // Extract byte + .makeIterator() + ) } /// - Returns: `UUID` from the first 16 bytes of the underlying data. diff --git a/Tests/UnitTests/FoundationExtensions/NSData+RCExtensionsTests.swift b/Tests/UnitTests/FoundationExtensions/DataExtensionsTests.swift similarity index 88% rename from Tests/UnitTests/FoundationExtensions/NSData+RCExtensionsTests.swift rename to Tests/UnitTests/FoundationExtensions/DataExtensionsTests.swift index 8ef10901c3..5ef78c09fa 100644 --- a/Tests/UnitTests/FoundationExtensions/NSData+RCExtensionsTests.swift +++ b/Tests/UnitTests/FoundationExtensions/DataExtensionsTests.swift @@ -9,7 +9,7 @@ import XCTest @testable import RevenueCat -class NSDataExtensionsTests: TestCase { +class DataExtensionsTests: TestCase { func testAsString() { let data = Data([ @@ -23,14 +23,12 @@ class NSDataExtensionsTests: TestCase { 0x40, 0xfd, 0x9d, 0x91 ]) - let nsData = data as NSData - - expect(nsData.asString()) == "e388152d6c67f4d5f7a78edf073946f158357f89a1dc74dff80a796740fd9d91" + expect(data.asString) == "e388152d6c67f4d5f7a78edf073946f158357f89a1dc74dff80a796740fd9d91" } func testAsFetchToken() { - let storedReceiptText = NSDataExtensionsTests.readFile(named: Self.receiptFilename) - let storedReceiptData = NSDataExtensionsTests.sampleReceiptData(receiptName: Self.receiptFilename) + let storedReceiptText = Self.readFile(named: Self.receiptFilename) + let storedReceiptData = Self.sampleReceiptData(receiptName: Self.receiptFilename) let fetchToken = storedReceiptData.asFetchToken expect(fetchToken).to(equal(storedReceiptText)) @@ -75,7 +73,7 @@ class NSDataExtensionsTests: TestCase { } -extension NSDataExtensionsTests { +extension DataExtensionsTests { static func sampleReceiptData(receiptName: String) -> Data { let receiptText = self.readFile(named: receiptName) diff --git a/Tests/UnitTests/LocalReceiptParsing/TestsAgainstRealReceipts/ReceiptParsing+TestsWithRealReceipts.swift b/Tests/UnitTests/LocalReceiptParsing/TestsAgainstRealReceipts/ReceiptParsing+TestsWithRealReceipts.swift index 77213da614..6e86217544 100644 --- a/Tests/UnitTests/LocalReceiptParsing/TestsAgainstRealReceipts/ReceiptParsing+TestsWithRealReceipts.swift +++ b/Tests/UnitTests/LocalReceiptParsing/TestsAgainstRealReceipts/ReceiptParsing+TestsWithRealReceipts.swift @@ -184,11 +184,11 @@ private extension ReceiptParsingRealReceiptTests { static let receipt1Name = "base64encodedreceiptsample1" static func sampleReceiptData(receiptName: String) -> Data { - NSDataExtensionsTests.sampleReceiptData(receiptName: receiptName) + DataExtensionsTests.sampleReceiptData(receiptName: receiptName) } static func readFile(named filename: String) -> String { - NSDataExtensionsTests.readFile(named: filename) + DataExtensionsTests.readFile(named: filename) } } diff --git a/Tests/UnitTests/SubscriberAttributes/PurchasesSubscriberAttributesTests.swift b/Tests/UnitTests/SubscriberAttributes/PurchasesSubscriberAttributesTests.swift index b3dd375397..8983567791 100644 --- a/Tests/UnitTests/SubscriberAttributes/PurchasesSubscriberAttributesTests.swift +++ b/Tests/UnitTests/SubscriberAttributes/PurchasesSubscriberAttributesTests.swift @@ -516,7 +516,7 @@ class PurchasesSubscriberAttributesTests: TestCase { let receivedPushToken = self.mockSubscriberAttributesManager.invokedSetPushTokenParameters!.pushToken! - expect((receivedPushToken as NSData).asString()) == tokenString + expect(receivedPushToken.asString) == tokenString expect(self.mockSubscriberAttributesManager.invokedSetPushTokenParameters?.appUserID) == mockIdentityManager .currentAppUserID } diff --git a/Tests/UnitTests/SubscriberAttributes/SubscriberAttributesManagerTests.swift b/Tests/UnitTests/SubscriberAttributes/SubscriberAttributesManagerTests.swift index 742ec5c39c..f9ebea0632 100644 --- a/Tests/UnitTests/SubscriberAttributes/SubscriberAttributesManagerTests.swift +++ b/Tests/UnitTests/SubscriberAttributes/SubscriberAttributesManagerTests.swift @@ -298,8 +298,7 @@ class SubscriberAttributesManagerTests: TestCase { let receivedAttribute = invokedParams.attribute expect(receivedAttribute.key) == "$apnsTokens" - let tokenString = (tokenData as NSData).asString() - expect(receivedAttribute.value) == tokenString + expect(receivedAttribute.value) == tokenData.asString expect(receivedAttribute.isSynced) == false } @@ -321,9 +320,8 @@ class SubscriberAttributesManagerTests: TestCase { func testSetPushTokenSkipsIfSameValue() { let tokenData = "ligai32g32ig".asData - let tokenString = (tokenData as NSData).asString() self.mockDeviceCache.stubbedSubscriberAttributeResult = SubscriberAttribute(withKey: "$apnsTokens", - value: tokenString) + value: tokenData.asString) self.subscriberAttributesManager.setPushToken(tokenData, appUserID: "kratos") @@ -332,7 +330,6 @@ class SubscriberAttributesManagerTests: TestCase { func testSetPushTokenOverwritesIfNewValue() { let tokenData = "ligai32g32ig".asData - let tokenString = (tokenData as NSData).asString() let oldSyncTime = Date() self.mockDeviceCache.stubbedSubscriberAttributeResult = SubscriberAttribute(withKey: "$apnsTokens", @@ -348,7 +345,7 @@ class SubscriberAttributesManagerTests: TestCase { } let receivedAttribute = invokedParams.attribute expect(receivedAttribute.key) == "$apnsTokens" - expect(receivedAttribute.value) == tokenString + expect(receivedAttribute.value) == tokenData.asString expect(receivedAttribute.isSynced) == false expect(receivedAttribute.setTime) > oldSyncTime }