From 740a9b57dcc5ac388fa61864579eb6c45dfd2bbd Mon Sep 17 00:00:00 2001 From: Dariusz Rybicki <dariusz@elixxir.io> Date: Tue, 30 Aug 2022 12:09:10 +0100 Subject: [PATCH 1/5] Update JSONHelpers --- ...NumberToString.swift => JSONHelpers.swift} | 18 ++ .../ConvertJsonNumberToStringTests.swift | 127 ----------- .../Helpers/JSONHelpersTests.swift | 214 ++++++++++++++++++ 3 files changed, 232 insertions(+), 127 deletions(-) rename Sources/XXClient/Helpers/{ConvertJsonNumberToString.swift => JSONHelpers.swift} (67%) delete mode 100644 Tests/XXClientTests/Helpers/ConvertJsonNumberToStringTests.swift create mode 100644 Tests/XXClientTests/Helpers/JSONHelpersTests.swift diff --git a/Sources/XXClient/Helpers/ConvertJsonNumberToString.swift b/Sources/XXClient/Helpers/JSONHelpers.swift similarity index 67% rename from Sources/XXClient/Helpers/ConvertJsonNumberToString.swift rename to Sources/XXClient/Helpers/JSONHelpers.swift index 8390ba1c..5653752d 100644 --- a/Sources/XXClient/Helpers/ConvertJsonNumberToString.swift +++ b/Sources/XXClient/Helpers/JSONHelpers.swift @@ -35,3 +35,21 @@ func convertJsonNumberToString( } return output } + +func convertJsonStringToNumber( + in input: Data, + at key: String +) -> Data { + guard var string = String(data: input, encoding: .utf8) else { + return input + } + string = string.replacingOccurrences( + of: #""\#(key)"( *):( *)"([0-9]+)"( *)(,*)"#, + with: #""\#(key)"$1:$2$3$4$5"#, + options: [.regularExpression] + ) + guard let output = string.data(using: .utf8) else { + return input + } + return output +} diff --git a/Tests/XXClientTests/Helpers/ConvertJsonNumberToStringTests.swift b/Tests/XXClientTests/Helpers/ConvertJsonNumberToStringTests.swift deleted file mode 100644 index 4fc1ecd7..00000000 --- a/Tests/XXClientTests/Helpers/ConvertJsonNumberToStringTests.swift +++ /dev/null @@ -1,127 +0,0 @@ -import CustomDump -import XCTest -@testable import XXClient - -final class ConvertJsonNumberToStringTests: XCTestCase { - func testConverting() { - assert( - input: #"{"number":1234567890,"text":"hello"}"#, - key: "number", - expected: #"{"number":"1234567890","text":"hello"}"# - ) - - assert( - input: #"{"text":"hello","number":1234567890}"#, - key: "number", - expected: #"{"text":"hello","number":"1234567890"}"# - ) - - assert( - input: #"{ "number" : 1234567890 , "text" : "hello" }"#, - key: "number", - expected: #"{ "number" : "1234567890" , "text" : "hello" }"# - ) - - assert( - input: #"{ "text" : "hello" , "number" : 1234567890 }"#, - key: "number", - expected: #"{ "text" : "hello" , "number" : "1234567890" }"# - ) - - assert( - input: """ - { - "number": 1234567890, - "text": "hello" - } - """, - key: "number", - expected: """ - { - "number": "1234567890", - "text": "hello" - } - """ - ) - - assert( - input: """ - { - "text": "hello", - "number": 1234567890 - } - """, - key: "number", - expected: """ - { - "text": "hello", - "number": "1234567890" - } - """ - ) - - assert( - input: """ - { - "text": "hello", - "number1": 123456789, - "number2": 1234567890, - "number3": 123456789, - "number4": 1234567890 - } - """, - minNumberLength: 10, - expected: """ - { - "text": "hello", - "number1": 123456789, - "number2": "1234567890", - "number3": 123456789, - "number4": "1234567890" - } - """ - ) - } -} - -private func assert( - input: String, - key: String, - expected: String, - file: StaticString = #file, - line: UInt = #line -) { - XCTAssertNoDifference( - String( - data: convertJsonNumberToString( - in: input.data(using: .utf8)!, - at: key - ), - encoding: .utf8 - )!, - expected, - file: file, - line: line - ) -} - -private func assert( - input: String, - minNumberLength: Int, - expected: String, - file: StaticString = #file, - line: UInt = #line -) { - XCTAssertNoDifference( - String( - data: convertJsonNumberToString( - in: input.data(using: .utf8)!, - minNumberLength: minNumberLength - ), - encoding: .utf8 - )!, - expected, - file: file, - line: line - ) -} diff --git a/Tests/XXClientTests/Helpers/JSONHelpersTests.swift b/Tests/XXClientTests/Helpers/JSONHelpersTests.swift new file mode 100644 index 00000000..20a90116 --- /dev/null +++ b/Tests/XXClientTests/Helpers/JSONHelpersTests.swift @@ -0,0 +1,214 @@ +import CustomDump +import XCTest +@testable import XXClient + +final class JSONHelpersTests: XCTestCase { + func testConvertingNumberToStringByKey() { + assertConvertingJsonNumberToString( + input: #"{"number":1234567890,"text":"hello"}"#, + key: "number", + expected: #"{"number":"1234567890","text":"hello"}"# + ) + + assertConvertingJsonNumberToString( + input: #"{"text":"hello","number":1234567890}"#, + key: "number", + expected: #"{"text":"hello","number":"1234567890"}"# + ) + + assertConvertingJsonNumberToString( + input: #"{ "number" : 1234567890 , "text" : "hello" }"#, + key: "number", + expected: #"{ "number" : "1234567890" , "text" : "hello" }"# + ) + + assertConvertingJsonNumberToString( + input: #"{ "text" : "hello" , "number" : 1234567890 }"#, + key: "number", + expected: #"{ "text" : "hello" , "number" : "1234567890" }"# + ) + + assertConvertingJsonNumberToString( + input: """ + { + "number": 1234567890, + "text": "hello" + } + """, + key: "number", + expected: """ + { + "number": "1234567890", + "text": "hello" + } + """ + ) + + assertConvertingJsonNumberToString( + input: """ + { + "text": "hello", + "number": 1234567890 + } + """, + key: "number", + expected: """ + { + "text": "hello", + "number": "1234567890" + } + """ + ) + } + + func testConvertingNumberToStringByLength() { + assertConvertingJsonNumberToString( + input: """ + { + "text": "hello", + "number1": 123456789, + "number2": 1234567890, + "number3": 123456789, + "number4": 1234567890 + } + """, + minNumberLength: 10, + expected: """ + { + "text": "hello", + "number1": 123456789, + "number2": "1234567890", + "number3": 123456789, + "number4": "1234567890" + } + """ + ) + + assertConvertingJsonNumberToString( + input: #"{"text":"hello","number1":123456789,"number2":1234567890,"number3":123456789,"number4":1234567890}"#, + minNumberLength: 10, + expected: #"{"text":"hello","number1":123456789,"number2":"1234567890","number3":123456789,"number4":"1234567890"}"# + ) + } + + func testConvertingStringToNumber() { + assertConvertingJsonStringToNumber( + input: #"{"number":"1234567890","text":"hello"}"#, + key: "number", + expected: #"{"number":1234567890,"text":"hello"}"# + ) + + assertConvertingJsonStringToNumber( + input: #"{"text":"hello","number":"1234567890"}"#, + key: "number", + expected: #"{"text":"hello","number":1234567890}"# + ) + + assertConvertingJsonStringToNumber( + input: #"{ "number" : "1234567890" , "text" : "hello" }"#, + key: "number", + expected: #"{ "number" : 1234567890 , "text" : "hello" }"# + ) + + assertConvertingJsonStringToNumber( + input: #"{ "text" : "hello" , "number" : "1234567890" }"#, + key: "number", + expected: #"{ "text" : "hello" , "number" : 1234567890 }"# + ) + + assertConvertingJsonStringToNumber( + input: """ + { + "number": "1234567890", + "text": "hello" + } + """, + key: "number", + expected: """ + { + "number": 1234567890, + "text": "hello" + } + """ + ) + + assertConvertingJsonStringToNumber( + input: """ + { + "text": "hello", + "number": "1234567890" + } + """, + key: "number", + expected: """ + { + "text": "hello", + "number": 1234567890 + } + """ + ) + } +} + +private func assertConvertingJsonNumberToString( + input: String, + key: String, + expected: String, + file: StaticString = #file, + line: UInt = #line +) { + XCTAssertNoDifference( + String( + data: convertJsonNumberToString( + in: input.data(using: .utf8)!, + at: key + ), + encoding: .utf8 + )!, + expected, + file: file, + line: line + ) +} + +private func assertConvertingJsonNumberToString( + input: String, + minNumberLength: Int, + expected: String, + file: StaticString = #file, + line: UInt = #line +) { + XCTAssertNoDifference( + String( + data: convertJsonNumberToString( + in: input.data(using: .utf8)!, + minNumberLength: minNumberLength + ), + encoding: .utf8 + )!, + expected, + file: file, + line: line + ) +} + +private func assertConvertingJsonStringToNumber( + input: String, + key: String, + expected: String, + file: StaticString = #file, + line: UInt = #line +) { + XCTAssertNoDifference( + String( + data: convertJsonStringToNumber( + in: input.data(using: .utf8)!, + at: key + ), + encoding: .utf8 + )!, + expected, + file: file, + line: line + ) +} -- GitLab From 427344f476f12533e5f2dc135d21d4efac231f97 Mon Sep 17 00:00:00 2001 From: Dariusz Rybicki <dariusz@elixxir.io> Date: Tue, 30 Aug 2022 12:09:54 +0100 Subject: [PATCH 2/5] Add DHKey model --- Sources/XXClient/Models/DHKey.swift | 28 +++++++++++++++++++ Tests/XXClientTests/Models/DHKeyTests.swift | 31 +++++++++++++++++++++ 2 files changed, 59 insertions(+) create mode 100644 Sources/XXClient/Models/DHKey.swift create mode 100644 Tests/XXClientTests/Models/DHKeyTests.swift diff --git a/Sources/XXClient/Models/DHKey.swift b/Sources/XXClient/Models/DHKey.swift new file mode 100644 index 00000000..5dc94983 --- /dev/null +++ b/Sources/XXClient/Models/DHKey.swift @@ -0,0 +1,28 @@ +import Foundation + +public struct DHKey: Equatable { + public init(value: String, fingerprint: UInt64) { + self.value = value + self.fingerprint = fingerprint + } + + public var value: String + public var fingerprint: UInt64 +} + +extension DHKey: Codable { + enum CodingKeys: String, CodingKey { + case value = "Value" + case fingerprint = "Fingerprint" + } + + public static func decode(_ data: Data) throws -> Self { + let data = convertJsonNumberToString(in: data, at: "Value") + return try JSONDecoder().decode(Self.self, from: data) + } + + public func encode() throws -> Data { + let data = try JSONEncoder().encode(self) + return convertJsonStringToNumber(in: data, at: "Value") + } +} diff --git a/Tests/XXClientTests/Models/DHKeyTests.swift b/Tests/XXClientTests/Models/DHKeyTests.swift new file mode 100644 index 00000000..eea82bf3 --- /dev/null +++ b/Tests/XXClientTests/Models/DHKeyTests.swift @@ -0,0 +1,31 @@ +import CustomDump +import XCTest +@testable import XXClient + +final class DHKeyTests: XCTestCase { + func testCoding() throws { + let value = "1759426033802606996617132861414734059978289057332806031357800676138355264622676606691435603603751978195460163638145821347601916259127578968570412642641025630452893097179266022832268525346700655861033031712000288680395716922501450233258587788020541937373196899001184700899008948530359980753630443486308876999029238453979779103124291315202352475056237021681172884599194016245219278368648568458514708567045834427853469072638665888791358582182353417065794210125797368093469194927663862565508608719835557592421245749381164023134450699040591219966988201315627676532245052123725278573237006510683695959381015415110970848376498637637944431576313526294020390694483472829278364602405292767170719547347485307956614210210673321959886410245334772057212077704024337636501108566655549055129066343309591274727538343075929837698653965640646190405582788894021694347212874155979958144038307500444865955516612526623220973497735316081265793063949" + let fingerprint: UInt64 = 15989433043166758754 + let jsonString = """ + { + "Value": \(value), + "Fingerprint": \(fingerprint) + } + """ + let jsonData = jsonString.data(using: .utf8)! + let model = try DHKey.decode(jsonData) + + XCTAssertNoDifference(model, DHKey( + value: value, + fingerprint: fingerprint + )) + + let encodedModel = try model.encode() + let encodedModelString = String(data: encodedModel, encoding: .utf8) + + XCTAssertNoDifference( + encodedModelString, + #"{"Value":\#(value),"Fingerprint":\#(fingerprint)}"# + ) + } +} -- GitLab From 0d5e46d0adb523dab7595c8792b157315a5d329f Mon Sep 17 00:00:00 2001 From: Dariusz Rybicki <dariusz@elixxir.io> Date: Tue, 30 Aug 2022 12:28:03 +0100 Subject: [PATCH 3/5] Add DHKey to GroupMember model --- Sources/XXClient/Models/GroupMember.swift | 21 ++++++++++--- .../Models/GroupMemberTests.swift | 31 ++++++++++++++++--- 2 files changed, 44 insertions(+), 8 deletions(-) diff --git a/Sources/XXClient/Models/GroupMember.swift b/Sources/XXClient/Models/GroupMember.swift index 8ce7120a..cb5d9843 100644 --- a/Sources/XXClient/Models/GroupMember.swift +++ b/Sources/XXClient/Models/GroupMember.swift @@ -1,27 +1,40 @@ import Foundation public struct GroupMember: Equatable { - public init(id: Data) { + public init(id: Data, dhKey: DHKey) { self.id = id + self.dhKey = dhKey } public var id: Data + public var dhKey: DHKey } -extension GroupMember: Decodable { +extension GroupMember: Codable { enum CodingKeys: String, CodingKey { case id = "ID" + case dhKey = "DhKey" } public static func decode(_ data: Data) throws -> Self { - let data = convertJsonNumberToString(in: data, minNumberLength: 19) + let data = convertJsonNumberToString(in: data, at: "Value") return try JSONDecoder().decode(Self.self, from: data) } + + public func encode() throws -> Data { + let data = try JSONEncoder().encode(self) + return convertJsonStringToNumber(in: data, at: "Value") + } } extension Array where Element == GroupMember { public static func decode(_ data: Data) throws -> Self { - let data = convertJsonNumberToString(in: data, minNumberLength: 19) + let data = convertJsonNumberToString(in: data, at: "Value") return try JSONDecoder().decode(Self.self, from: data) } + + public func encode() throws -> Data { + let data = try JSONEncoder().encode(self) + return convertJsonStringToNumber(in: data, at: "Value") + } } diff --git a/Tests/XXClientTests/Models/GroupMemberTests.swift b/Tests/XXClientTests/Models/GroupMemberTests.swift index 36e178c0..eed1a473 100644 --- a/Tests/XXClientTests/Models/GroupMemberTests.swift +++ b/Tests/XXClientTests/Models/GroupMemberTests.swift @@ -4,13 +4,15 @@ import XCTest final class GroupMemberTests: XCTestCase { func testCoding() throws { - let idB64 = "U4x/lrFkvxuXu59LtHLon1sUhPJSCcnZND6SugndnVID" + let idB64 = "SGVsbG8sIFdvcmxkISBHcm91cCBNZW1iZXIgVGVzdCBJRA==" + let dhKeyValue = "1759426033802606996617132861414734059978289057332806031357800676138355264622676606691435603603751978195460163638145821347601916259127578968570412642641025630452893097179266022832268525346700655861033031712000288680395716922501450233258587788020541937373196899001184700899008948530359980753630443486308876999029238453979779103124291315202352475056237021681172884599194016245219278368648568458514708567045834427853469072638665888791358582182353417065794210125797368093469194927663862565508608719835557592421245749381164023134450699040591219966988201315627676532245052123725278573237006510683695959381015415110970848376498637637944431576313526294020390694483472829278364602405292767170719547347485307956614210210673321959886410245334772057212077704024337636501108566655549055129066343309591274727538343075929837698653965640646190405582788894021694347212874155979958144038307500444865955516612526623220973497735316081265793063949" + let dhKeyFingerprint: UInt64 = 15989433043166758754 let jsonString = """ { "ID": "\(idB64)", "DhKey": { - "Value": 1759426033802606996617132861414734059978289057332806031357800676138355264622676606691435603603751978195460163638145821347601916259127578968570412642641025630452893097179266022832268525346700655861033031712000288680395716922501450233258587788020541937373196899001184700899008948530359980753630443486308876999029238453979779103124291315202352475056237021681172884599194016245219278368648568458514708567045834427853469072638665888791358582182353417065794210125797368093469194927663862565508608719835557592421245749381164023134450699040591219966988201315627676532245052123725278573237006510683695959381015415110970848376498637637944431576313526294020390694483472829278364602405292767170719547347485307956614210210673321959886410245334772057212077704024337636501108566655549055129066343309591274727538343075929837698653965640646190405582788894021694347212874155979958144038307500444865955516612526623220973497735316081265793063949, - "Fingerprint": 15989433043166758754 + "Value": \(dhKeyValue), + "Fingerprint": \(dhKeyFingerprint) } } """ @@ -18,13 +20,34 @@ final class GroupMemberTests: XCTestCase { let model = try GroupMember.decode(jsonData) XCTAssertNoDifference(model, GroupMember( - id: Data(base64Encoded: idB64)! + id: Data(base64Encoded: idB64)!, + dhKey: DHKey( + value: dhKeyValue, + fingerprint: dhKeyFingerprint + ) )) + let encodedModel = try model.encode() + let encodedModelString = String(data: encodedModel, encoding: .utf8)! + XCTAssertNoDifference( + encodedModelString, + """ + {"ID":"\(idB64)","DhKey":{"Value":\(dhKeyValue),"Fingerprint":\(dhKeyFingerprint)}} + """ + ) + let jsonArrayString = "[\(jsonString)]" let jsonArrayData = jsonArrayString.data(using: .utf8)! let decodedModels = try [GroupMember].decode(jsonArrayData) XCTAssertNoDifference(decodedModels, [model]) + + let encodedModels = try decodedModels.encode() + let encodedModelsString = String(data: encodedModels, encoding: .utf8)! + + XCTAssertNoDifference( + encodedModelsString, + "[\(encodedModelString)]" + ) } } -- GitLab From 014027c212dc7def0beb6a3c8f18c622a0f19bea Mon Sep 17 00:00:00 2001 From: Dariusz Rybicki <dariusz@elixxir.io> Date: Tue, 30 Aug 2022 12:30:11 +0100 Subject: [PATCH 4/5] Remove unused JSON helper function convertJsonNumberToString(in:minNumberLength:) --- Sources/XXClient/Helpers/JSONHelpers.swift | 18 ------- .../Helpers/JSONHelpersTests.swift | 51 ------------------- 2 files changed, 69 deletions(-) diff --git a/Sources/XXClient/Helpers/JSONHelpers.swift b/Sources/XXClient/Helpers/JSONHelpers.swift index 5653752d..eb719ec9 100644 --- a/Sources/XXClient/Helpers/JSONHelpers.swift +++ b/Sources/XXClient/Helpers/JSONHelpers.swift @@ -18,24 +18,6 @@ func convertJsonNumberToString( return output } -func convertJsonNumberToString( - in input: Data, - minNumberLength: Int -) -> Data { - guard var string = String(data: input, encoding: .utf8) else { - return input - } - string = string.replacingOccurrences( - of: #":( *)([0-9]{\#(minNumberLength),})( *)(,*)"#, - with: #":$1"$2"$3$4"#, - options: [.regularExpression] - ) - guard let output = string.data(using: .utf8) else { - return input - } - return output -} - func convertJsonStringToNumber( in input: Data, at key: String diff --git a/Tests/XXClientTests/Helpers/JSONHelpersTests.swift b/Tests/XXClientTests/Helpers/JSONHelpersTests.swift index 20a90116..2ebe8530 100644 --- a/Tests/XXClientTests/Helpers/JSONHelpersTests.swift +++ b/Tests/XXClientTests/Helpers/JSONHelpersTests.swift @@ -61,36 +61,6 @@ final class JSONHelpersTests: XCTestCase { ) } - func testConvertingNumberToStringByLength() { - assertConvertingJsonNumberToString( - input: """ - { - "text": "hello", - "number1": 123456789, - "number2": 1234567890, - "number3": 123456789, - "number4": 1234567890 - } - """, - minNumberLength: 10, - expected: """ - { - "text": "hello", - "number1": 123456789, - "number2": "1234567890", - "number3": 123456789, - "number4": "1234567890" - } - """ - ) - - assertConvertingJsonNumberToString( - input: #"{"text":"hello","number1":123456789,"number2":1234567890,"number3":123456789,"number4":1234567890}"#, - minNumberLength: 10, - expected: #"{"text":"hello","number1":123456789,"number2":"1234567890","number3":123456789,"number4":"1234567890"}"# - ) - } - func testConvertingStringToNumber() { assertConvertingJsonStringToNumber( input: #"{"number":"1234567890","text":"hello"}"#, @@ -171,27 +141,6 @@ private func assertConvertingJsonNumberToString( ) } -private func assertConvertingJsonNumberToString( - input: String, - minNumberLength: Int, - expected: String, - file: StaticString = #file, - line: UInt = #line -) { - XCTAssertNoDifference( - String( - data: convertJsonNumberToString( - in: input.data(using: .utf8)!, - minNumberLength: minNumberLength - ), - encoding: .utf8 - )!, - expected, - file: file, - line: line - ) -} - private func assertConvertingJsonStringToNumber( input: String, key: String, -- GitLab From 5c455732176f074d34ab082345d7346c903aec2c Mon Sep 17 00:00:00 2001 From: Dariusz Rybicki <dariusz@elixxir.io> Date: Tue, 30 Aug 2022 12:33:54 +0100 Subject: [PATCH 5/5] Add some documentation --- Sources/XXClient/Helpers/JSONHelpers.swift | 48 ++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/Sources/XXClient/Helpers/JSONHelpers.swift b/Sources/XXClient/Helpers/JSONHelpers.swift index eb719ec9..7527ac9a 100644 --- a/Sources/XXClient/Helpers/JSONHelpers.swift +++ b/Sources/XXClient/Helpers/JSONHelpers.swift @@ -1,5 +1,29 @@ import Foundation +/// Replaces all numbers at provided key with string equivalents +/// +/// Example input: +/// { +/// "key": 123, +/// "object": { +/// "hello": "world", +/// "key": 321 +/// } +/// } +/// +/// Example output: +/// { +/// "key": "123", +/// "object": { +/// "hello": "world", +/// "key": "321" +/// } +/// } +/// +/// - Parameters: +/// - input: JSON data +/// - key: the key which values should be converted +/// - Returns: JSON data func convertJsonNumberToString( in input: Data, at key: String @@ -18,6 +42,30 @@ func convertJsonNumberToString( return output } +/// Replaces all strings at provided key with number equivalents +/// +/// Example input: +/// { +/// "key": "123", +/// "object": { +/// "hello": "world", +/// "key": "321" +/// } +/// } +/// +/// Example output: +/// { +/// "key": 123, +/// "object": { +/// "hello": "world", +/// "key": 321 +/// } +/// } +/// +/// - Parameters: +/// - input: JSON data +/// - key: the key which values should be converted +/// - Returns: JSON data func convertJsonStringToNumber( in input: Data, at key: String -- GitLab