Skip to content

Commit

Permalink
Added xdr decoding
Browse files Browse the repository at this point in the history
  • Loading branch information
Volendi committed Mar 4, 2020
1 parent a108065 commit ea7c33f
Show file tree
Hide file tree
Showing 10 changed files with 277 additions and 30 deletions.
4 changes: 2 additions & 2 deletions Example/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ EXTERNAL SOURCES:
SPEC CHECKSUMS:
DLCryptoKit: 491c522583e92c90c09c06bf1192ef741022af33
DLOpenSSL: 78d928228cb6d95fcaa354f4f9aba041ccf95457
TokenDWallet: c66abb4a51c2c035ea439e27cf64e8589773a63f
TokenDWallet: a740f7767f3e66566e4a507f351a2bbf5901aa22

PODFILE CHECKSUM: 2ff703f484f93022caae12590846b6530f3c4419

COCOAPODS: 1.6.1
COCOAPODS: 1.8.0
199 changes: 199 additions & 0 deletions Example/Tests/XDRDecodingTests.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,199 @@
import XCTest
@testable import TokenDWallet

// swiftlint:disable identifier_name

class XDRDecodingTests: XCTestCase {

func testBasicTypes() {
// Int
XCTAssertEqual(try! Int32(xdrBase64: "AAAABQ=="), Int32(5))
XCTAssertEqual(try! UInt32(xdrBase64: "AAAABQ=="), UInt32(5))
XCTAssertEqual(try! UInt64(xdrBase64: "AAAAAAAAAAU="), UInt64(5))
XCTAssertEqual(try! Int64(xdrBase64: "AAAAAAAAAAU="), Int64(5))

// Float, Double and Quadruple is unsupported

// Bool
XCTAssertEqual(try! Bool(xdrBase64: "AAAAAQ=="), true)
}

func testEnum() {
enum TestEnum: Int32, XDREnum {
case a = 0
case b = 1
case c = -1
}

XCTAssertEqual(try! TestEnum(xdrBase64: "AAAAAA=="), TestEnum.a)
XCTAssertEqual(try! TestEnum(xdrBase64: "AAAAAQ=="), TestEnum.b)
XCTAssertEqual(try! TestEnum(xdrBase64: "/////w=="), TestEnum.c)
}

func testOptional() {
var test: Int32?
XCTAssertEqual(decodeOptionalInt32(xdrBase64: "AAAAAA=="), test)
test = 5
XCTAssertEqual(decodeOptionalInt32(xdrBase64: "AAAAAQAAAAU="), test)
}

private func decodeOptionalInt32(xdrBase64: String) -> Int32? {
var data = Data(base64Encoded: xdrBase64)!
if (try! Bool(xdrData: &data)) {
return try! Int32(xdrData: &data)
} else {
return nil
}
}

func testString() {
XCTAssertEqual(try! String(xdrBase64: "AAAABHRlc3Q="), "test")
}

func testOpaque() {
// Dinamic size
let data = Data(bytes: [1])
XCTAssertEqual(try! Data(xdrBase64: "AAAAAQE="), data)
// Fixed size
struct XDRDataFixed1: XDRDataFixed {
static var length: Int { return 1 }

var wrapped: Data

init() {
self.wrapped = Data()
}
}
XCTAssertEqual(try! XDRDataFixed1(xdrBase64: "AQ=="), try! XDRDataFixed1(data))
}

func testArray() {
// Dinamic size
let data = [Int64(1)]
XCTAssertEqual(try! decodeArrayInt64(xdrBase64: "AAAAAQAAAAAAAAAB"), data)
struct XDRArrayFixed1<WrappedElement: XDRCodable>: XDRArrayFixed {
typealias Element = WrappedElement

static var length: Int { return 1 }

var wrapped: [WrappedElement]

init() {
self.wrapped = [WrappedElement]()
}
}
// Fixed size
XCTAssertEqual(try! XDRArrayFixed1<Int64>(xdrBase64: "AAAAAAAAAAE=").wrapped, try! XDRArrayFixed1(data).wrapped)
}

private func decodeArrayInt64(xdrBase64: String) throws -> [Int64] {
var data = Data(base64Encoded: xdrBase64)!
let length = try Int32(xdrData: &data)
var result = [Int64]()
for _ in 1...length {
result.append(try Int64(xdrData: &data))
}

return result
}

func testDescriminatedUnion() {
enum TestDescriminatedUnion: XDRDiscriminatedUnion, XDRDecodable {
case a(Int64)
case b(Int32)
case c

var discriminant: Int32 {
switch self {
case .a: return 0
case .b: return 1
case .c: return 2
}
}

func toXDR() -> Data {
var xdr = Data()

xdr.append(self.discriminant.toXDR())

switch self {
case .a(let data): xdr.append(data.toXDR())
case .b(let data): xdr.append(data.toXDR())
case .c: xdr.append(Data())
}

return xdr
}

init(xdrData: inout Data) throws {
let discriminant = try Int32(xdrData: &xdrData)

switch discriminant {
case 0:
let data = try Int64(xdrData: &xdrData)
self = .a(data)
case 1:
let data = try Int32(xdrData: &xdrData)
self = .b(data)
case 2:
self = .c
default:
throw XDRErrors.unknownEnumCase
}
}
}

XCTAssertEqual(try! TestDescriminatedUnion(xdrBase64: "AAAAAAAAAAAAAAAB").toXdrBase64String(), TestDescriminatedUnion.a(1).toXdrBase64String())
XCTAssertEqual(try! TestDescriminatedUnion(xdrBase64: "AAAAAQAAAAE=").toXdrBase64String(), TestDescriminatedUnion.b(1).toXdrBase64String())
XCTAssertEqual(try! TestDescriminatedUnion(xdrBase64: "AAAAAg==").toXdrBase64String(), TestDescriminatedUnion.c.toXdrBase64String())
}

func testStruct() {
enum TestEnum: Int32, XDREnum {
case a = 0
case b = 1
case c = -1
}
struct Test: XDRCodable {
var a: Int32
var b: Int32?
var c: Bool
var d: TestEnum

func toXDR() -> Data {
var xdr = Data()

xdr.append(self.a.toXDR())
xdr.append(self.b.toXDR())
xdr.append(self.c.toXDR())
xdr.append(self.d.toXDR())

return xdr
}

init(a: Int32, b: Int32?, c: Bool, d: TestEnum) {
self.a = a
self.b = b
self.c = c
self.d = d
}

init(xdrData: inout Data) throws {
self.a = try Int32(xdrData: &xdrData)
if (try Bool(xdrData: &xdrData)) {
self.b = try Int32(xdrData: &xdrData)
} else {
self.b = nil
}
self.c = try Bool(xdrData: &xdrData)
self.d = try TestEnum(xdrData: &xdrData)
}
}

let test = Test(a: 1, b: nil, c: true, d: TestEnum.a)

XCTAssertEqual(try! Test(xdrBase64: "AAAAAQAAAAAAAAABAAAAAA==").toXdrBase64String(), test.toXdrBase64String())
}
}

// swiftlint:enable identifier_name
19 changes: 15 additions & 4 deletions Example/Tests/XDREncodingTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,9 @@ class XDREncodingTests: XCTestCase {
case c = -1
}

XCTAssertEqual(TestEnum.a.rawValue.toXDR().base64, "AAAAAA==")
XCTAssertEqual(TestEnum.b.rawValue.toXDR().base64, "AAAAAQ==")
XCTAssertEqual(TestEnum.c.rawValue.toXDR().base64, "/////w==")
XCTAssertEqual(TestEnum.a.toXDR().base64, "AAAAAA==")
XCTAssertEqual(TestEnum.b.toXDR().base64, "AAAAAQ==")
XCTAssertEqual(TestEnum.c.toXDR().base64, "/////w==")
}

func testOptional() {
Expand Down Expand Up @@ -62,8 +62,19 @@ class XDREncodingTests: XCTestCase {
// Dinamic size
let data = [Int64(1)]
XCTAssertEqual(data.toXDR().base64, "AAAAAQAAAAAAAAAB")
struct XDRArrayFixed1<WrappedElement: XDRCodable>: XDRArrayFixed {
typealias Element = WrappedElement

static var length: Int { return 1 }

var wrapped: [WrappedElement]

init() {
self.wrapped = [WrappedElement]()
}
}
// Fixed size
XCTAssertEqual(XDRArrayFixed(data).toXDR().base64, "AAAAAAAAAAE=")
XCTAssertEqual(try! XDRArrayFixed1(data).toXDR().base64, "AAAAAAAAAAE=")
}

func testDescriminatedUnion() {
Expand Down
4 changes: 4 additions & 0 deletions Example/TokenDWallet.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
7D8C0B06FEDBFDD4F6A860AA /* libPods-TokenDWallet_Tests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 46DC2F103B0418D6E33CA14A /* libPods-TokenDWallet_Tests.a */; };
7FABEA6F20FF4EE30005E751 /* ECDSASignDecoratedTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7FABEA6E20FF4EE30005E751 /* ECDSASignDecoratedTests.swift */; };
7FABEA7120FF54E60005E751 /* TransactionModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7FABEA7020FF54E60005E751 /* TransactionModelTests.swift */; };
C47C788D240D75900068C152 /* XDRDecodingTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C47C788C240D75900068C152 /* XDRDecodingTests.swift */; };
C4C0EF6B2094B57700DAC6C4 /* XDREncodingTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4C0EF6A2094B57700DAC6C4 /* XDREncodingTests.swift */; };
C4C0EF7F2097053200DAC6C4 /* Base32CheckTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4C0EF7D209704D300DAC6C4 /* Base32CheckTests.swift */; };
C4C0EFAC20971CDC00DAC6C4 /* XDRTypesTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4C0EFAA20971CB400DAC6C4 /* XDRTypesTests.swift */; };
Expand Down Expand Up @@ -47,6 +48,7 @@
7FABEA6E20FF4EE30005E751 /* ECDSASignDecoratedTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ECDSASignDecoratedTests.swift; sourceTree = "<group>"; };
7FABEA7020FF54E60005E751 /* TransactionModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TransactionModelTests.swift; sourceTree = "<group>"; };
9A7D0DDACE2712C49B8FB4B1 /* Pods-TokenDWallet_Tests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-TokenDWallet_Tests.release.xcconfig"; path = "Pods/Target Support Files/Pods-TokenDWallet_Tests/Pods-TokenDWallet_Tests.release.xcconfig"; sourceTree = "<group>"; };
C47C788C240D75900068C152 /* XDRDecodingTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = XDRDecodingTests.swift; sourceTree = "<group>"; };
C4C0EF6A2094B57700DAC6C4 /* XDREncodingTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = XDREncodingTests.swift; sourceTree = "<group>"; };
C4C0EF7D209704D300DAC6C4 /* Base32CheckTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Base32CheckTests.swift; sourceTree = "<group>"; };
C4C0EFAA20971CB400DAC6C4 /* XDRTypesTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = XDRTypesTests.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -121,6 +123,7 @@
7FABEA6E20FF4EE30005E751 /* ECDSASignDecoratedTests.swift */,
7FABEA7020FF54E60005E751 /* TransactionModelTests.swift */,
C4C0EF6A2094B57700DAC6C4 /* XDREncodingTests.swift */,
C47C788C240D75900068C152 /* XDRDecodingTests.swift */,
C4C0EFAA20971CB400DAC6C4 /* XDRTypesTests.swift */,
607FACE91AFB9204008FA782 /* Supporting Files */,
);
Expand Down Expand Up @@ -364,6 +367,7 @@
buildActionMask = 2147483647;
files = (
7FABEA7120FF54E60005E751 /* TransactionModelTests.swift in Sources */,
C47C788D240D75900068C152 /* XDRDecodingTests.swift in Sources */,
C4C0EF7F2097053200DAC6C4 /* Base32CheckTests.swift in Sources */,
C4C0EFAC20971CDC00DAC6C4 /* XDRTypesTests.swift in Sources */,
C4C0EF6B2094B57700DAC6C4 /* XDREncodingTests.swift in Sources */,
Expand Down
8 changes: 4 additions & 4 deletions Sources/TokenDWallet/Xdr/LedgerHeader.swift
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ public struct LedgerHeader: XDREncodable {
public var baseReserve: Uint32
public var maxTxSetSize: Uint32
public var txExpirationPeriod: Int64
public var skipList: XDRArrayFixed<Hash>
// public var skipList: XDRArrayFixed<Hash>
public var ext: LedgerHeaderExt

public init(
Expand All @@ -67,7 +67,7 @@ public struct LedgerHeader: XDREncodable {
baseReserve: Uint32,
maxTxSetSize: Uint32,
txExpirationPeriod: Int64,
skipList: XDRArrayFixed<Hash>,
// skipList: XDRArrayFixed<Hash>,
ext: LedgerHeaderExt) {

self.ledgerVersion = ledgerVersion
Expand All @@ -81,7 +81,7 @@ public struct LedgerHeader: XDREncodable {
self.baseReserve = baseReserve
self.maxTxSetSize = maxTxSetSize
self.txExpirationPeriod = txExpirationPeriod
self.skipList = skipList
// self.skipList = skipList
self.ext = ext
}

Expand All @@ -99,7 +99,7 @@ public struct LedgerHeader: XDREncodable {
xdr.append(self.baseReserve.toXDR())
xdr.append(self.maxTxSetSize.toXDR())
xdr.append(self.txExpirationPeriod.toXDR())
xdr.append(self.skipList.toXDR())
// xdr.append(self.skipList.toXDR())
xdr.append(self.ext.toXDR())

return xdr
Expand Down
2 changes: 2 additions & 0 deletions Sources/TokenDWallet/Xdr/Lib/Errors/XDRErrors.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,6 @@ import Foundation
public enum XDRErrors: Swift.Error {
case wrongDataLength
case decodingError
case base64DecodeError
case unknownEnumCase
}
51 changes: 34 additions & 17 deletions Sources/TokenDWallet/Xdr/Lib/XDRArrayFixed.swift
Original file line number Diff line number Diff line change
@@ -1,40 +1,57 @@
import Foundation

public struct XDRArrayFixed<T: XDREncodable>: Sequence {
public private(set) var list: [T]
public protocol XDRArrayFixed: XDRCodable, Sequence where Element: XDRCodable {
static var length: Int { get }
var wrapped: [Element] { get set }

public init(_ array: [T]) {
self.list = array
init()
init(_ array: [Element]) throws
}

extension XDRArrayFixed {
public init(_ array: [Element]) throws {
self.init()

if array.count > Self.length {
throw XDRErrors.wrongDataLength
}

self.wrapped = array
}

public subscript(_ index: Int) -> T {
return list[index]
public init(xdrData: inout Data) throws {
self.init()
for _ in 1...Self.length {
self.wrapped.append(try Element(xdrData: &xdrData))
}
}

public subscript(_ index: Int) -> Element {
return wrapped[index]
}

public func makeIterator() -> AnyIterator<T> {
public func makeIterator() -> AnyIterator<Element> {
var index = 0

return AnyIterator {
let element: T? = index < self.list.count ? self[index] : nil
let element: Element? = index < self.wrapped.count ? self[index] : nil
index += 1

return element
}
}
}

extension XDRArrayFixed: XDREncodable, CustomDebugStringConvertible {

public func toXDR() -> Data {
var xdr = Data()

forEach {
xdr.append($0.toXDR())
}

return xdr
}

public var debugDescription: String {
return list.debugDescription
return wrapped.debugDescription
}
}
Loading

0 comments on commit ea7c33f

Please sign in to comment.