diff --git a/CBORCoding.podspec b/CBORCoding.podspec index 80c4011..30e5c88 100644 --- a/CBORCoding.podspec +++ b/CBORCoding.podspec @@ -1,7 +1,7 @@ Pod::Spec.new do |s| s.name = "CBORCoding" - s.version = "1.3.0" + s.version = "1.3.1" s.summary = "A CBOR Encoder and Decoder" s.description = <<-DESC A lightweight framework containing a coder pair for encoding and decoding `Codable` conforming types to and from CBOR document format for iOS, macOS, tvOS, and watchOS. diff --git a/Sources/CBORCoding/CBOR.swift b/Sources/CBORCoding/CBOR.swift index 0294c28..ec21690 100644 --- a/Sources/CBORCoding/CBOR.swift +++ b/Sources/CBORCoding/CBOR.swift @@ -139,9 +139,10 @@ public struct CBOR { chunks.reserveCapacity(numberOfChunks) for i in 0 ..< numberOfChunks { - let range = ((i * chunkSize) ..< ((i + 1) * chunkSize)).clamped(to: 0 ..< numberOfBytes) + let lowerBound = data.index(data.startIndex, offsetBy: i * chunkSize) + let upperBound = data.index(data.startIndex, offsetBy: (i + 1) * chunkSize, limitedBy: data.endIndex) ?? data.endIndex - chunks.append(Data(data[range])) + chunks.append(Data(data[lowerBound ..< upperBound])) } self.chunks = chunks @@ -184,9 +185,10 @@ public struct CBOR { chunks.reserveCapacity(numberOfChunks) for i in 0 ..< numberOfChunks { - let range = ((i * chunkSize) ..< ((i + 1) * chunkSize)).clamped(to: 0 ..< numberOfBytes) + let lowerBound = data.index(data.startIndex, offsetBy: i * chunkSize) + let upperBound = data.index(data.startIndex, offsetBy: (i + 1) * chunkSize, limitedBy: data.endIndex) ?? data.endIndex - chunks.append(Data(data[range])) + chunks.append(Data(data[lowerBound ..< upperBound])) } self.chunks = chunks @@ -291,9 +293,9 @@ extension CBOR { init?(bits: Data) { guard !bits.isEmpty else { return nil } - guard CBOR.majorType(for: bits[0]) == .tag else { return nil } + guard CBOR.majorType(for: bits[bits.startIndex]) == .tag else { return nil } - let additonalInfo = CBOR.additionalInfo(for: bits[0]) + let additonalInfo = CBOR.additionalInfo(for: bits[bits.startIndex]) switch additonalInfo { case 0: self = .standardDateTime case 1: self = .epochDateTime @@ -307,7 +309,7 @@ extension CBOR { case 24: guard bits.count >= 2 else { return nil } - switch bits[1] { + switch bits[bits.index(after: bits.startIndex)] { case 24: self = .encodedCBORData case 32: self = .uri case 33: self = .base64URL @@ -320,7 +322,7 @@ extension CBOR { case 25: guard bits.count >= 3 else { return nil } - switch (bits[1], bits[2]) { + switch (bits[bits.index(bits.startIndex, offsetBy: 1)], bits[bits.index(bits.startIndex, offsetBy: 2)]) { case (0xD9, 0xF7): self = .selfDescribedCBOR default: return nil } @@ -387,12 +389,12 @@ extension CBOR { internal var stringValue: String internal var intValue: Int? - internal init?(stringValue: String) { + internal init(stringValue: String) { self.stringValue = stringValue self.intValue = nil } - internal init?(intValue: Int) { + internal init(intValue: Int) { self.stringValue = "\(intValue)" self.intValue = intValue } @@ -406,9 +408,7 @@ extension CBOR { // MARK: Constants - // swiftlint:disable force_unwrapping - internal static let `super` = CodingKey(stringValue: "super")! - // swiftlint:enable force_unwrapping + internal static let `super` = CodingKey(stringValue: "super") } // MARK: Internal Methods @@ -459,16 +459,16 @@ extension DecodingError { let expectedTypes: String if expected.count > 2 { var types = expected.map { "\($0)" } - types[types.endIndex - 1] = "or " + types[types.endIndex - 1] + types[types.index(before: types.endIndex)] = "or " + types[types.index(before: types.endIndex)] expectedTypes = types.joined(separator: ", ") } else if expected.count > 1 { expectedTypes = expected.map({ "\($0)" }).joined(separator: " or ") } else { - expectedTypes = "\(expected[0])" + expectedTypes = "\(expected[expected.startIndex])" } - self = .typeMismatch(expected[0], Context(codingPath: path, debugDescription: "Expected to decode \(expectedTypes) but found \(actual) instead.")) + self = .typeMismatch(expected[expected.startIndex], Context(codingPath: path, debugDescription: "Expected to decode \(expectedTypes) but found \(actual) instead.")) case let .dataCorrupted(description): self = .dataCorrupted(Context(codingPath: path, debugDescription: description)) diff --git a/Sources/CBORCoding/CBOREncoder.swift b/Sources/CBORCoding/CBOREncoder.swift index 851bfd2..603fa8a 100644 --- a/Sources/CBORCoding/CBOREncoder.swift +++ b/Sources/CBORCoding/CBOREncoder.swift @@ -589,9 +589,7 @@ internal class __CBOREncoder: CBOREncoderProtocol, SingleValueEncodingContainer do { for (key, value) in dictionary { - // swiftlint:disable force_unwrapping - let codingKey = CBOR.CodingKey(stringValue: key)! - // swiftlint:enable force_unwrapping + let codingKey = CBOR.CodingKey(stringValue: key) codingPath.append(codingKey) defer { codingPath.removeLast() } @@ -616,9 +614,7 @@ internal class __CBOREncoder: CBOREncoderProtocol, SingleValueEncodingContainer do { for (key, value) in dictionary { - // swiftlint:disable force_unwrapping - let codingKey = CBOR.CodingKey(intValue: key)! - // swiftlint:enable force_unwrapping + let codingKey = CBOR.CodingKey(intValue: key) codingPath.append(codingKey) defer { codingPath.removeLast() } @@ -1120,9 +1116,7 @@ private class __CBORReferencingEncoder: __CBOREncoder { array.insert(value, at: index) case let .dictionary(dictionary, key): - // swiftlint:disable force_unwrapping - dictionary[CBOR.CodingKey(stringValue: key)!] = value - // swiftlint:enable force_unwrapping + dictionary[CBOR.CodingKey(stringValue: key)] = value } } diff --git a/Sources/CBORCoding/CBORParser.swift b/Sources/CBORCoding/CBORParser.swift index b111d15..ac51518 100644 --- a/Sources/CBORCoding/CBORParser.swift +++ b/Sources/CBORCoding/CBORParser.swift @@ -19,15 +19,15 @@ internal class CBORParser { guard !data.isEmpty else { return nil } var storage = Storage() - var index: Int = 0 + var index = data.startIndex do { - while index < data.count { + while index < data.endIndex { let majorType = CBOR.majorType(for: data[index]) switch majorType { case .unsigned: - let unsigned = try decode(UInt64.self, from: Data(data[index...])) + let unsigned = try decode(UInt64.self, from: data[index...]) try storage.append(unsigned.value) index += unsigned.decodedBytes @@ -36,11 +36,11 @@ internal class CBORParser { let signed: (value: Any, decodedBytes: Int) do { - let result = try decode(Int64.self, from: Data(data[index...])) + let result = try decode(Int64.self, from: data[index...]) signed = (result.value, result.decodedBytes) } catch let firstError { do { - let result = try decode(CBOR.NegativeUInt64.self, from: Data(data[index...])) + let result = try decode(CBOR.NegativeUInt64.self, from: data[index...]) signed = (result.value, result.decodedBytes) } catch { throw firstError @@ -51,13 +51,13 @@ internal class CBORParser { index += signed.decodedBytes case .bytes: - let bytes = try decode(Data.self, from: Data(data[index...])) + let bytes = try decode(Data.self, from: data[index...]) try storage.append(bytes.value) index += bytes.decodedBytes case .string: - let string = try decode(String.self, from: Data(data[index...])) + let string = try decode(String.self, from: data[index...]) try storage.append(string.value) index += string.decodedBytes @@ -69,7 +69,7 @@ internal class CBORParser { index += 1 } else { - let unsigned = try decode(UInt64.self, from: Data(data[index...]), knownMajorType: majorType) + let unsigned = try decode(UInt64.self, from: data[index...], knownMajorType: majorType) try storage.startUnkeyedContainer(ofLength: unsigned.value) index += unsigned.decodedBytes @@ -82,50 +82,50 @@ internal class CBORParser { index += 1 } else { - let unsigned = try decode(UInt64.self, from: Data(data[index...]), knownMajorType: majorType) + let unsigned = try decode(UInt64.self, from: data[index...], knownMajorType: majorType) try storage.startKeyedContainer(ofLength: unsigned.value) index += unsigned.decodedBytes } case .tag: - if let tag = CBOR.Tag(bits: Data(data[index...])) { + if let tag = CBOR.Tag(bits: data[index...]) { index += tag.bits.count switch tag { case .standardDateTime, .epochDateTime: - let date = try decode(Date.self, tag: tag, from: Data(data[index...])) + let date = try decode(Date.self, tag: tag, from: data[index...]) try storage.append(date.value) index += date.decodedBytes case .positiveBignum, .negativeBignum: - let bignum = try decode(CBOR.Bignum.self, tag: tag, from: Data(data[index...])) + let bignum = try decode(CBOR.Bignum.self, tag: tag, from: data[index...]) try storage.append(bignum.value) index += bignum.decodedBytes case .decimalFraction: - let decimal = try decode(CBOR.DecimalFraction.self, from: Data(data[index...])) + let decimal = try decode(CBOR.DecimalFraction.self, from: data[index...]) try storage.append(decimal.value) index += decimal.decodedBytes case .bigfloat: - let bigfloat = try decode(CBOR.Bigfloat.self, from: Data(data[index...])) + let bigfloat = try decode(CBOR.Bigfloat.self, from: data[index...]) try storage.append(bigfloat.value) index += bigfloat.decodedBytes case .base64URLConversion, .base64Conversion, .base16Conversion: do { - let string = try decode(String.self, from: Data(data[index...])) + let string = try decode(String.self, from: data[index...]) try storage.append(string.value) index += string.decodedBytes } catch { do { - let bytes = try decode(Data.self, from: Data(data[index...])) + let bytes = try decode(Data.self, from: data[index...]) try storage.append(bytes.value) index += bytes.decodedBytes @@ -135,19 +135,19 @@ internal class CBORParser { } case .encodedCBORData: - let bytes = try decode(Data.self, from: Data(data[index...])) + let bytes = try decode(Data.self, from: data[index...]) try storage.append(bytes.value) index += bytes.decodedBytes case .uri: - let url = try decode(URL.self, from: Data(data[index...])) + let url = try decode(URL.self, from: data[index...]) try storage.append(url.value) index += url.decodedBytes case .base64URL, .base64, .regularExpression: - let string = try decode(String.self, from: Data(data[index...])) + let string = try decode(String.self, from: data[index...]) let decodedString = try string.value.decodedStringValue() if tag == .base64URL { @@ -177,7 +177,7 @@ internal class CBORParser { index += string.decodedBytes case .mimeMessage: - let string = try decode(String.self, from: Data(data[index...])) + let string = try decode(String.self, from: data[index...]) try storage.append(string.value) index += string.decodedBytes @@ -188,7 +188,7 @@ internal class CBORParser { } else { let unsigned: UInt64 do { - unsigned = try decode(UInt64.self, from: Data(data[index...]), knownMajorType: .tag).value + unsigned = try decode(UInt64.self, from: data[index...], knownMajorType: .tag).value } catch { throw CBOR.DecodingError.dataCorrupted(description: "Invalid CBOR tag") } @@ -220,25 +220,25 @@ internal class CBORParser { index += 1 case 24: - let simple = try decode(CBOR.SimpleValue.self, from: Data(data[index...])) + let simple = try decode(CBOR.SimpleValue.self, from: data[index...]) try storage.append(simple.value) index += simple.decodedBytes case 25: - let half = try decode(Half.self, from: Data(data[index...])) + let half = try decode(Half.self, from: data[index...]) try storage.append(half.value) index += half.decodedBytes case 26: - let float = try decode(Float.self, from: Data(data[index...])) + let float = try decode(Float.self, from: data[index...]) try storage.append(float.value) index += float.decodedBytes case 27: - let double = try decode(Double.self, from: Data(data[index...])) + let double = try decode(Double.self, from: data[index...]) try storage.append(double.value) index += double.decodedBytes @@ -259,15 +259,15 @@ internal class CBORParser { return try storage.finalize() } - internal static func type(for bytes: Data) throws -> Any.Type { + internal class func type(for bytes: Data) throws -> Any.Type { do { guard !bytes.isEmpty else { throw CBOR.DecodingError.insufficientEncodedBytes(expected: nil) } let type: Any.Type - let majorType = CBOR.majorType(for: bytes[0]) - let additionalInfo = CBOR.additionalInfo(for: bytes[0]) + let majorType = CBOR.majorType(for: bytes[bytes.startIndex]) + let additionalInfo = CBOR.additionalInfo(for: bytes[bytes.startIndex]) switch majorType { case .unsigned: @@ -323,7 +323,7 @@ internal class CBORParser { throw CBOR.DecodingError.insufficientEncodedBytes(expected: nil) } - switch bytes[1] { + switch bytes[bytes.index(after: bytes.startIndex)] { case 24: type = Data.self case 32...36: type = String.self default: throw CBOR.DecodingError.dataCorrupted(description: "Invalid encoded tag") @@ -334,7 +334,7 @@ internal class CBORParser { throw CBOR.DecodingError.insufficientEncodedBytes(expected: nil) } - switch (bytes[1], bytes[2]) { + switch (bytes[bytes.index(bytes.startIndex, offsetBy: 1)], bytes[bytes.index(bytes.startIndex, offsetBy: 2)]) { case (0xD9, 0xF7): type = Data.self default: throw CBOR.DecodingError.dataCorrupted(description: "Invalid encoded tag") } @@ -367,17 +367,17 @@ internal class CBORParser { // MARK: Private Methods // swiftlint:disable function_body_length - private static func decode(_ type: String.Type, from data: Data) throws -> (value: CBORDecodedString, decodedBytes: Int) { + private class func decode(_ type: String.Type, from data: Data) throws -> (value: CBORDecodedString, decodedBytes: Int) { guard !data.isEmpty else { throw CBOR.DecodingError.insufficientEncodedBytes(expected: type) } - let majorType = CBOR.majorType(for: data[0]) + let majorType = CBOR.majorType(for: data[data.startIndex]) guard majorType == .string else { throw CBOR.DecodingError.typeMismatch(expected: [type], actual: try self.type(for: data)) } - let additionalInfo = CBOR.additionalInfo(for: data[0]) + let additionalInfo = CBOR.additionalInfo(for: data[data.startIndex]) let result: (value: CBORDecodedString, decodedBytes: Int) if additionalInfo == 31 { @@ -387,15 +387,15 @@ internal class CBORParser { throw CBOR.DecodingError.insufficientEncodedBytes(expected: type) } - var index = 1 + var index = data.index(after: data.startIndex) var resultString = CBOR.IndefiniteLengthString() while true { - guard index < data.count else { + guard index < data.endIndex else { throw CBOR.DecodingError.insufficientEncodedBytes(expected: type) } guard data[index] != CBOR.Bits.break.rawValue else { - index += 1 // for the `break` byte + index = data.index(after: index) // for the `break` byte break } @@ -404,18 +404,18 @@ internal class CBORParser { resultString.chunks.append(Data()) index += count.decodedBytes } else { - guard data.count >= index + Int(count.value + UInt64(count.decodedBytes)) else { + guard let nextIndex = data.index(index, offsetBy: count.decodedBytes + Int(count.value), limitedBy: data.endIndex), data.endIndex > nextIndex else { throw CBOR.DecodingError.insufficientEncodedBytes(expected: type) } - let utf8Data = Data(data[index + count.decodedBytes ..< (index + count.decodedBytes + Int(count.value))]) + let utf8Data = Data(data[data.index(index, offsetBy: count.decodedBytes) ..< nextIndex]) resultString.chunks.append(utf8Data) - index += Int(count.value) + count.decodedBytes + index = nextIndex } } - result = (resultString, index) + result = (resultString, data.distance(from: data.startIndex, to: index)) } else { // Definite length string @@ -423,11 +423,11 @@ internal class CBORParser { if count.value == 0 { result = ("", count.decodedBytes) } else { - guard data.count >= Int(count.value + UInt64(count.decodedBytes)) else { + guard let nextIndex = data.index(data.startIndex, offsetBy: Int(count.value + UInt64(count.decodedBytes)), limitedBy: data.endIndex), data.endIndex >= nextIndex else { throw CBOR.DecodingError.insufficientEncodedBytes(expected: type) } - let utf8Data = Data(data[count.decodedBytes ..< (count.decodedBytes + Int(count.value))]) + let utf8Data = Data(data[data.index(data.startIndex, offsetBy: count.decodedBytes) ..< nextIndex]) guard let string = String(data: utf8Data, encoding: .utf8) else { throw CBOR.DecodingError.invalidUTF8String } @@ -440,17 +440,17 @@ internal class CBORParser { } // swiftlint:enable function_body_length - private static func decode(_ type: Data.Type, from data: Data) throws -> (value: CBORDecodedData, decodedBytes: Int) { + private class func decode(_ type: Data.Type, from data: Data) throws -> (value: CBORDecodedData, decodedBytes: Int) { guard !data.isEmpty else { throw CBOR.DecodingError.insufficientEncodedBytes(expected: type) } - let majorType = CBOR.majorType(for: data[0]) + let majorType = CBOR.majorType(for: data[data.startIndex]) guard majorType == .bytes else { throw CBOR.DecodingError.typeMismatch(expected: [type], actual: try self.type(for: data)) } - let additionalInfo = CBOR.additionalInfo(for: data[0]) + let additionalInfo = CBOR.additionalInfo(for: data[data.startIndex]) let result: (value: CBORDecodedData, decodedBytes: Int) if additionalInfo == 31 { @@ -460,25 +460,25 @@ internal class CBORParser { throw CBOR.DecodingError.insufficientEncodedBytes(expected: type) } - var index = 1 + var index = data.index(after: data.startIndex) var resultData = CBOR.IndefiniteLengthData() repeat { - guard index < data.count else { + guard index < data.endIndex else { throw CBOR.DecodingError.insufficientEncodedBytes(expected: type) } guard data[index] != CBOR.Bits.break.rawValue else { - index += 1 // for the `break` byte + index = data.index(after: index) // for the `break` byte break } let decoded = try decode(type, from: Data(data[index...])) resultData.chunks.append(decoded.value.decodedDataValue()) - index += decoded.decodedBytes + index = data.index(index, offsetBy: decoded.decodedBytes) } while true - result = (resultData, index) + result = (resultData, data.distance(from: data.startIndex, to: index)) } else { // Definite length byte data @@ -486,18 +486,18 @@ internal class CBORParser { if count.value == 0 { result = (Data(), count.decodedBytes) } else { - if data.count < Int(count.value + UInt64(count.decodedBytes)) { + guard let nextIndex = data.index(data.startIndex, offsetBy: count.decodedBytes + Int(count.value), limitedBy: data.endIndex), data.endIndex >= nextIndex else { throw CBOR.DecodingError.insufficientEncodedBytes(expected: type) } - result = (data[count.decodedBytes ..< (count.decodedBytes + Int(count.value))], count.decodedBytes + Int(count.value)) + result = (data[data.index(data.startIndex, offsetBy: count.decodedBytes) ..< nextIndex], count.decodedBytes + Int(count.value)) } } return result } - private static func decode(_ type: Date.Type, tag: CBOR.Tag, from data: Data) throws -> (value: Date, decodedBytes: Int) { + private class func decode(_ type: Date.Type, tag: CBOR.Tag, from data: Data) throws -> (value: Date, decodedBytes: Int) { precondition(tag == .standardDateTime || tag == .epochDateTime) guard !data.isEmpty else { @@ -540,12 +540,12 @@ internal class CBORParser { return result } - private static func decode(_ type: URL.Type, from data: Data) throws -> (value: URL, decodedBytes: Int) { + private class func decode(_ type: URL.Type, from data: Data) throws -> (value: URL, decodedBytes: Int) { guard !data.isEmpty else { throw CBOR.DecodingError.insufficientEncodedBytes(expected: type) } - let majorType = CBOR.majorType(for: data[0]) + let majorType = CBOR.majorType(for: data[data.startIndex]) guard majorType == .string else { throw CBOR.DecodingError.typeMismatch(expected: [type], actual: try self.type(for: data)) } @@ -559,12 +559,12 @@ internal class CBORParser { return (url, string.decodedBytes) } - private static func decode(_ type: CBOR.NegativeUInt64.Type, from data: Data) throws -> (value: CBOR.NegativeUInt64, decodedBytes: Int) { + private class func decode(_ type: CBOR.NegativeUInt64.Type, from data: Data) throws -> (value: CBOR.NegativeUInt64, decodedBytes: Int) { guard !data.isEmpty else { throw CBOR.DecodingError.insufficientEncodedBytes(expected: type) } - let majorType = CBOR.majorType(for: data[0]) + let majorType = CBOR.majorType(for: data[data.startIndex]) guard majorType == .negative else { throw CBOR.DecodingError.typeMismatch(expected: [type], actual: try self.type(for: data)) } @@ -574,17 +574,17 @@ internal class CBORParser { return (CBOR.NegativeUInt64(rawValue: unsigned.value == .max ? .min : (unsigned.value + 1)), unsigned.decodedBytes) } - private static func decode(_ type: CBOR.SimpleValue.Type, from data: Data) throws -> (value: CBOR.SimpleValue, decodedBytes: Int) { + private class func decode(_ type: CBOR.SimpleValue.Type, from data: Data) throws -> (value: CBOR.SimpleValue, decodedBytes: Int) { guard !data.isEmpty else { throw CBOR.DecodingError.insufficientEncodedBytes(expected: type) } - let majorType = CBOR.majorType(for: data[0]) + let majorType = CBOR.majorType(for: data[data.startIndex]) guard majorType == .additonal else { throw CBOR.DecodingError.typeMismatch(expected: [type], actual: try self.type(for: data)) } - let additionalInfo = CBOR.additionalInfo(for: data[0]) + let additionalInfo = CBOR.additionalInfo(for: data[data.startIndex]) let result: (value: CBOR.SimpleValue, decodedBytes: Int) switch additionalInfo { @@ -593,7 +593,7 @@ internal class CBORParser { throw CBOR.DecodingError.insufficientEncodedBytes(expected: type) } - result = (CBOR.SimpleValue(rawValue: data[1]), 2) + result = (CBOR.SimpleValue(rawValue: data[data.index(after: data.startIndex)]), 2) default: throw CBOR.DecodingError.typeMismatch(expected: [type], actual: try self.type(for: data)) @@ -602,7 +602,7 @@ internal class CBORParser { return result } - private static func decode(_ type: CBOR.Bignum.Type, tag: CBOR.Tag, from data: Data) throws -> (value: CBOR.Bignum, decodedBytes: Int) { + private class func decode(_ type: CBOR.Bignum.Type, tag: CBOR.Tag, from data: Data) throws -> (value: CBOR.Bignum, decodedBytes: Int) { precondition(tag == .positiveBignum || tag == .negativeBignum) guard !data.isEmpty else { @@ -615,13 +615,13 @@ internal class CBORParser { } // swiftlint:disable function_body_length - private static func decode(_ type: T.Type, from data: Data) throws -> (value: T, decodedBytes: Int) where T: BinaryFloatingPoint, T.RawExponent: FixedWidthInteger, T.RawSignificand: FixedWidthInteger { + private class func decode(_ type: T.Type, from data: Data) throws -> (value: T, decodedBytes: Int) where T: BinaryFloatingPoint, T.RawExponent: FixedWidthInteger, T.RawSignificand: FixedWidthInteger { guard !data.isEmpty else { throw CBOR.DecodingError.insufficientEncodedBytes(expected: type) } - let header = data[0] - let majorType = CBOR.majorType(for: data[0]) + let header = data[data.startIndex] + let majorType = CBOR.majorType(for: data[data.startIndex]) guard majorType == .additonal else { throw CBOR.DecodingError.typeMismatch(expected: [type], actual: try self.type(for: data)) } @@ -630,7 +630,7 @@ internal class CBORParser { if header == CBOR.Bits.half.rawValue { // Half if data.count >= 3 { // swiftlint:disable force_unwrapping - let half = data[1 ..< 3].reversed().withUnsafeBytes { $0.bindMemory(to: Half.self).baseAddress!.pointee } + let half = data[data.index(data.startIndex, offsetBy: 1) ..< data.index(data.startIndex, offsetBy: 3)].reversed().withUnsafeBytes { $0.bindMemory(to: Half.self).baseAddress!.pointee } // swiftlint:enable force_unwrapping if half.isNaN { @@ -650,7 +650,7 @@ internal class CBORParser { } else if header == CBOR.Bits.float.rawValue { // Single if data.count >= 5 { // swiftlint:disable force_unwrapping - let float = data[1 ..< 5].reversed().withUnsafeBytes { $0.bindMemory(to: Float.self).baseAddress!.pointee } + let float = data[data.index(data.startIndex, offsetBy: 1) ..< data.index(data.startIndex, offsetBy: 5)].reversed().withUnsafeBytes { $0.bindMemory(to: Float.self).baseAddress!.pointee } // swiftlint:enable force_unwrapping if float.isNaN { @@ -670,7 +670,7 @@ internal class CBORParser { } else if header == CBOR.Bits.double.rawValue { // Double if data.count >= 9 { // swiftlint:disable force_unwrapping - let double = data[1 ..< 9].reversed().withUnsafeBytes { $0.bindMemory(to: Double.self).baseAddress!.pointee } + let double = data[data.index(data.startIndex, offsetBy: 1) ..< data.index(data.startIndex, offsetBy: 9)].reversed().withUnsafeBytes { $0.bindMemory(to: Double.self).baseAddress!.pointee } // swiftlint:enable force_unwrapping if double.isNaN { @@ -694,53 +694,64 @@ internal class CBORParser { return result } - private static func decode(_ type: T.Type, from data: Data, knownMajorType: CBOR.MajorType = .unsigned) throws -> (value: T, decodedBytes: Int) where T: UnsignedInteger & FixedWidthInteger { + private class func decode(_ type: T.Type, from data: Data, knownMajorType: CBOR.MajorType = .unsigned) throws -> (value: T, decodedBytes: Int) where T: UnsignedInteger & FixedWidthInteger { guard !data.isEmpty else { throw CBOR.DecodingError.insufficientEncodedBytes(expected: type) } - let majorType = CBOR.majorType(for: data[0]) + let majorType = CBOR.majorType(for: data[data.startIndex]) guard majorType == knownMajorType else { throw CBOR.DecodingError.typeMismatch(expected: [type], actual: try self.type(for: data)) } - let additionalInfo = CBOR.additionalInfo(for: data[0]) + let additionalInfo = CBOR.additionalInfo(for: data[data.startIndex]) let result: (value: T?, decodedBytes: Int) if additionalInfo <= 23 { result = (T(exactly: additionalInfo), 1) } else if additionalInfo == 24 { if data.count >= 2 { - result = (T(exactly: data[1]), 2) + result = (T(exactly: data[data.index(data.startIndex, offsetBy: 1)]), 2) } else { throw CBOR.DecodingError.insufficientEncodedBytes(expected: type) } } else if additionalInfo == 25 { if data.count >= 3 { - result = (T(exactly: UInt16(data[1]) << 8 | - UInt16(data[2])), 3) + result = (T(exactly: UInt16(data[data.index(data.startIndex, offsetBy: 1)]) << 8 | + UInt16(data[data.index(data.startIndex, offsetBy: 2)])), 3) } else { throw CBOR.DecodingError.insufficientEncodedBytes(expected: type) } } else if additionalInfo == 26 { if data.count >= 5 { - result = (T(exactly: UInt32(data[1]) << 24 | - UInt32(data[2]) << 16 | - UInt32(data[3]) << 8 | - UInt32(data[4])), 5) + let upper = UInt32(data[data.index(data.startIndex, offsetBy: 1)]) << 24 | + UInt32(data[data.index(data.startIndex, offsetBy: 2)]) << 16 + let lower = UInt32(data[data.index(data.startIndex, offsetBy: 3)]) << 8 | + UInt32(data[data.index(data.startIndex, offsetBy: 4)]) + + result = (T(exactly: upper | lower), 5) } else { throw CBOR.DecodingError.insufficientEncodedBytes(expected: type) } } else if additionalInfo == 27 { if data.count >= 9 { - let upper = UInt64(data[1]) << 56 | - UInt64(data[2]) << 48 | - UInt64(data[3]) << 40 | - UInt64(data[4]) << 32 - let lower = UInt64(data[5]) << 24 | - UInt64(data[6]) << 16 | - UInt64(data[7]) << 8 | - UInt64(data[8]) + let upper: UInt64, lower: UInt64 + do { + let upper1 = UInt64(data[data.index(data.startIndex, offsetBy: 1)]) << 56 | + UInt64(data[data.index(data.startIndex, offsetBy: 2)]) << 48 + let upper2 = UInt64(data[data.index(data.startIndex, offsetBy: 3)]) << 40 | + UInt64(data[data.index(data.startIndex, offsetBy: 4)]) << 32 + + upper = upper1 | upper2 + } + do { + let lower1 = UInt64(data[data.index(data.startIndex, offsetBy: 5)]) << 24 | + UInt64(data[data.index(data.startIndex, offsetBy: 6)]) << 16 + let lower2 = UInt64(data[data.index(data.startIndex, offsetBy: 7)]) << 8 | + UInt64(data[data.index(data.startIndex, offsetBy: 8)]) + + lower = lower1 | lower2 + } result = (T(exactly: upper | lower), 9) } else { @@ -758,12 +769,12 @@ internal class CBORParser { } // swiftlint:enable function_body_length - private static func decode(_ type: T.Type, from data: Data) throws -> (value: T, decodedBytes: Int) where T: SignedInteger & FixedWidthInteger { + private class func decode(_ type: T.Type, from data: Data) throws -> (value: T, decodedBytes: Int) where T: SignedInteger & FixedWidthInteger { guard !data.isEmpty else { throw CBOR.DecodingError.insufficientEncodedBytes(expected: type) } - let majorType = CBOR.majorType(for: data[0]) + let majorType = CBOR.majorType(for: data[data.startIndex]) guard majorType == .negative else { throw CBOR.DecodingError.typeMismatch(expected: [type], actual: try self.type(for: data)) } @@ -792,37 +803,37 @@ internal class CBORParser { } // swiftlint:disable function_body_length - private static func decode(_: CBOR.DecimalFraction.Type, from data: Data) throws -> (value: [Any], decodedBytes: Int) where I1: FixedWidthInteger, I2: FixedWidthInteger { + private class func decode(_: CBOR.DecimalFraction.Type, from data: Data) throws -> (value: [Any], decodedBytes: Int) where I1: FixedWidthInteger, I2: FixedWidthInteger { guard data.count >= 3 else { throw CBOR.DecodingError.insufficientEncodedBytes(expected: Array.self) } - guard CBOR.majorType(for: data[0]) == .array else { + guard CBOR.majorType(for: data[data.startIndex]) == .array else { throw CBOR.DecodingError.typeMismatch(expected: [Array.self], actual: try self.type(for: data)) } - guard CBOR.additionalInfo(for: data[0]) == 2 else { + guard CBOR.additionalInfo(for: data[data.startIndex]) == 2 else { throw CBOR.DecodingError.dataCorrupted(description: "Expected to decode array containing exactly two elements, found array containing \((try? decode(UInt64.self, from: data, knownMajorType: .array))?.value ?? 0) elements") } var result: (value: [Any], decodedBytes: Int) = ([CBOR.Tag.decimalFraction], 1) - var majorType = CBOR.majorType(for: data[1]) + var majorType = CBOR.majorType(for: data[data.index(after: data.startIndex)]) switch majorType { case .unsigned: - let unsigned = try decode(UInt64.self, from: Data(data[result.decodedBytes...])) + let unsigned = try decode(UInt64.self, from: Data(data[data.index(data.startIndex, offsetBy: result.decodedBytes)...])) result.value.append(unsigned.value) result.decodedBytes += unsigned.decodedBytes case .negative: do { - let signed = try decode(Int64.self, from: Data(data[result.decodedBytes...])) + let signed = try decode(Int64.self, from: Data(data[data.index(data.startIndex, offsetBy: result.decodedBytes)...])) result.value.append(signed.value) result.decodedBytes += signed.decodedBytes } catch let int64Error { do { - let signed = try decode(CBOR.NegativeUInt64.self, from: Data(data[result.decodedBytes...])) + let signed = try decode(CBOR.NegativeUInt64.self, from: Data(data[data.index(data.startIndex, offsetBy: result.decodedBytes)...])) result.value.append(signed.value) result.decodedBytes += signed.decodedBytes @@ -832,31 +843,31 @@ internal class CBORParser { } default: - throw CBOR.DecodingError.typeMismatch(expected: [UInt64.self, Int64.self], actual: try self.type(for: Data(data[result.decodedBytes...]))) + throw CBOR.DecodingError.typeMismatch(expected: [UInt64.self, Int64.self], actual: try self.type(for: Data(data[data.index(data.startIndex, offsetBy: result.decodedBytes)...]))) } guard data.count > result.decodedBytes else { throw CBOR.DecodingError.insufficientEncodedBytes(expected: Array.self) } - majorType = CBOR.majorType(for: data[result.decodedBytes]) + majorType = CBOR.majorType(for: data[data.index(data.startIndex, offsetBy: result.decodedBytes)]) switch majorType { case .unsigned: - let unsigned = try decode(UInt64.self, from: Data(data[result.decodedBytes...])) + let unsigned = try decode(UInt64.self, from: Data(data[data.index(data.startIndex, offsetBy: result.decodedBytes)...])) result.value.append(unsigned.value) result.decodedBytes += unsigned.decodedBytes case .negative: do { - let signed = try decode(Int64.self, from: Data(data[result.decodedBytes...])) + let signed = try decode(Int64.self, from: Data(data[data.index(data.startIndex, offsetBy: result.decodedBytes)...])) result.value.append(signed.value) result.decodedBytes += signed.decodedBytes } catch let int64Error { do { - let signed = try decode(CBOR.NegativeUInt64.self, from: Data(data[result.decodedBytes...])) + let signed = try decode(CBOR.NegativeUInt64.self, from: Data(data[data.index(data.startIndex, offsetBy: result.decodedBytes)...])) result.value.append(signed.value) result.decodedBytes += signed.decodedBytes @@ -866,7 +877,7 @@ internal class CBORParser { } case .tag: - guard let tag = CBOR.Tag(bits: Data(data[result.decodedBytes...])) else { + guard let tag = CBOR.Tag(bits: Data(data[data.index(data.startIndex, offsetBy: result.decodedBytes)...])) else { throw CBOR.DecodingError.dataCorrupted(description: "Invalid CBOR tag") } @@ -878,24 +889,24 @@ internal class CBORParser { result.decodedBytes += tag.bits.count - let bignum = try decode(CBOR.Bignum.self, tag: tag, from: Data(data[result.decodedBytes...])) + let bignum = try decode(CBOR.Bignum.self, tag: tag, from: Data(data[data.index(data.startIndex, offsetBy: result.decodedBytes)...])) result.value.append(bignum.value) result.decodedBytes += bignum.decodedBytes default: - throw CBOR.DecodingError.typeMismatch(expected: [UInt64.self, Int64.self, CBOR.Bignum.self], actual: try self.type(for: Data(data[result.decodedBytes...]))) + throw CBOR.DecodingError.typeMismatch(expected: [UInt64.self, Int64.self, CBOR.Bignum.self], actual: try self.type(for: Data(data[data.index(data.startIndex, offsetBy: result.decodedBytes)...]))) } default: - throw CBOR.DecodingError.typeMismatch(expected: [UInt64.self, Int64.self, CBOR.Bignum.self], actual: try self.type(for: Data(data[result.decodedBytes...]))) + throw CBOR.DecodingError.typeMismatch(expected: [UInt64.self, Int64.self, CBOR.Bignum.self], actual: try self.type(for: Data(data[data.index(data.startIndex, offsetBy: result.decodedBytes)...]))) } return result } // swiftlint:enable function_body_length - private static func decode(_: CBOR.Bigfloat.Type, from data: Data) throws -> (value: [Any], decodedBytes: Int) where I1: FixedWidthInteger, I2: FixedWidthInteger { + private class func decode(_: CBOR.Bigfloat.Type, from data: Data) throws -> (value: [Any], decodedBytes: Int) where I1: FixedWidthInteger, I2: FixedWidthInteger { var result = try decode(CBOR.DecimalFraction.self, from: data) result.value[0] = CBOR.Tag.bigfloat @@ -910,55 +921,55 @@ internal class CBORParser { // These proxies will allow us to directly test edge cases inside of the private // methods without exposing the private methods to any consumer of the class - internal static func testDecode(_ type: String.Type, from data: Data) throws -> (value: CBORDecodedString, decodedBytes: Int) { + internal class func testDecode(_ type: String.Type, from data: Data) throws -> (value: CBORDecodedString, decodedBytes: Int) { return try decode(type, from: data) } - internal static func testDecode(_ type: Data.Type, from data: Data) throws -> (value: CBORDecodedData, decodedBytes: Int) { + internal class func testDecode(_ type: Data.Type, from data: Data) throws -> (value: CBORDecodedData, decodedBytes: Int) { return try decode(type, from: data) } - internal static func testDecode(_ type: Date.Type, tag: CBOR.Tag, from data: Data) throws -> (value: Date, decodedBytes: Int) { + internal class func testDecode(_ type: Date.Type, tag: CBOR.Tag, from data: Data) throws -> (value: Date, decodedBytes: Int) { return try decode(type, tag: tag, from: data) } - internal static func testDecode(_ type: URL.Type, from data: Data) throws -> (value: URL, decodedBytes: Int) { + internal class func testDecode(_ type: URL.Type, from data: Data) throws -> (value: URL, decodedBytes: Int) { return try decode(type, from: data) } - internal static func testDecode(_ type: CBOR.NegativeUInt64.Type, from data: Data) throws -> (value: CBOR.NegativeUInt64, decodedBytes: Int) { + internal class func testDecode(_ type: CBOR.NegativeUInt64.Type, from data: Data) throws -> (value: CBOR.NegativeUInt64, decodedBytes: Int) { return try decode(type, from: data) } - internal static func testDecode(_ type: CBOR.SimpleValue.Type, from data: Data) throws -> (value: CBOR.SimpleValue, decodedBytes: Int) { + internal class func testDecode(_ type: CBOR.SimpleValue.Type, from data: Data) throws -> (value: CBOR.SimpleValue, decodedBytes: Int) { return try decode(type, from: data) } - internal static func testDecode(_ type: CBOR.Bignum.Type, tag: CBOR.Tag, from data: Data) throws -> (value: CBOR.Bignum, decodedBytes: Int) { + internal class func testDecode(_ type: CBOR.Bignum.Type, tag: CBOR.Tag, from data: Data) throws -> (value: CBOR.Bignum, decodedBytes: Int) { return try decode(type, tag: tag, from: data) } - internal static func testDecode(_ type: T.Type, from data: Data) throws -> (value: T, decodedBytes: Int) where T: BinaryFloatingPoint, T.RawExponent: FixedWidthInteger, T.RawSignificand: FixedWidthInteger { + internal class func testDecode(_ type: T.Type, from data: Data) throws -> (value: T, decodedBytes: Int) where T: BinaryFloatingPoint, T.RawExponent: FixedWidthInteger, T.RawSignificand: FixedWidthInteger { return try decode(type, from: data) } - internal static func testDecode(_ type: T.Type, from data: Data, knownMajorType: CBOR.MajorType = .unsigned) throws -> (value: T, decodedBytes: Int) where T: UnsignedInteger & FixedWidthInteger { + internal class func testDecode(_ type: T.Type, from data: Data, knownMajorType: CBOR.MajorType = .unsigned) throws -> (value: T, decodedBytes: Int) where T: UnsignedInteger & FixedWidthInteger { return try decode(type, from: data, knownMajorType: knownMajorType) } - internal static func testDecode(_ type: T.Type, from data: Data) throws -> (value: T, decodedBytes: Int) where T: SignedInteger & FixedWidthInteger { + internal class func testDecode(_ type: T.Type, from data: Data) throws -> (value: T, decodedBytes: Int) where T: SignedInteger & FixedWidthInteger { return try decode(type, from: data) } - internal static func testDecode(_ type: CBOR.DecimalFraction.Type, from data: Data) throws -> (value: [Any], decodedBytes: Int) where I1: FixedWidthInteger, I2: FixedWidthInteger { + internal class func testDecode(_ type: CBOR.DecimalFraction.Type, from data: Data) throws -> (value: [Any], decodedBytes: Int) where I1: FixedWidthInteger, I2: FixedWidthInteger { return try decode(type, from: data) } - internal static func testDecode(_ type: CBOR.Bigfloat.Type, from data: Data) throws -> (value: [Any], decodedBytes: Int) where I1: FixedWidthInteger, I2: FixedWidthInteger { + internal class func testDecode(_ type: CBOR.Bigfloat.Type, from data: Data) throws -> (value: [Any], decodedBytes: Int) where I1: FixedWidthInteger, I2: FixedWidthInteger { return try decode(type, from: data) } - internal static func testCreateCodingKey(from value: Any) throws -> Swift.CodingKey { + internal class func testCreateCodingKey(from value: Any) throws -> Swift.CodingKey { var storage = Storage() try storage.startKeyedContainer() @@ -969,7 +980,7 @@ internal class CBORParser { // swiftlint:disable force_cast force_unwrapping let dictionary = try storage.finalize()! as! CodingKeyDictionary // swiftlint:enable force_cast force_unwrapping - return dictionary.keys[0] + return dictionary.keys[dictionary.keys.startIndex] } #endif // #if DEBUG @@ -1062,7 +1073,7 @@ internal class CBORParser { throw CBOR.DecodingError.dataCorrupted(description: "Cannot decode multiple objects outside of the context of a container") } - let index = containers.count - 1 + let index = containers.index(before: containers.endIndex) if let array = containers[index] as? (container: ArrayWrapper, length: UInt64?) { array.container.append(value) diff --git a/Tests/CBORCodingTests/CBORParserTests.swift b/Tests/CBORCodingTests/CBORParserTests.swift index 35c2978..74332fe 100644 --- a/Tests/CBORCodingTests/CBORParserTests.swift +++ b/Tests/CBORCodingTests/CBORParserTests.swift @@ -15,264 +15,277 @@ import XCTest class CBORParserTests: XCTestCase { + // MARK: Private Constants + + private let prefixLengths = [0, 2, 4] + private let suffixLengths = [0, 2, 4] + // MARK: Test Methods func testAppendixASimpleExamples() { // Test Examples taken from Appendix A of RFC 7049 - var value: Any! + for prefixLength in prefixLengths { + func prefix() -> String { return randomHexString(ofLength: prefixLength) } + + for suffixLength in suffixLengths { + func suffix() -> String { return randomHexString(ofLength: suffixLength) } - XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString("0x00"))) - XCTAssertTrue(value is UInt64) - XCTAssertEqual(value as! UInt64, 0) + var value: Any! - XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString("0x01"))) - XCTAssertTrue(value is UInt64) - XCTAssertEqual(value as! UInt64, 1) + XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString("0x\(prefix())00\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength))) + XCTAssertTrue(value is UInt64) + XCTAssertEqual(value as! UInt64, 0) - XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString("0x0A"))) - XCTAssertTrue(value is UInt64) - XCTAssertEqual(value as! UInt64, 10) + XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString("0x\(prefix())01\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength))) + XCTAssertTrue(value is UInt64) + XCTAssertEqual(value as! UInt64, 1) - XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString("0x17"))) - XCTAssertTrue(value is UInt64) - XCTAssertEqual(value as! UInt64, 23) + XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString("0x\(prefix())0A\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength))) + XCTAssertTrue(value is UInt64) + XCTAssertEqual(value as! UInt64, 10) - XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString("0x1818"))) - XCTAssertTrue(value is UInt64) - XCTAssertEqual(value as! UInt64, 24) + XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString("0x\(prefix())17\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength))) + XCTAssertTrue(value is UInt64) + XCTAssertEqual(value as! UInt64, 23) - XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString("0x1819"))) - XCTAssertTrue(value is UInt64) - XCTAssertEqual(value as! UInt64, 25) + XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString("0x\(prefix())1818\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength))) + XCTAssertTrue(value is UInt64) + XCTAssertEqual(value as! UInt64, 24) - XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString("0x1864"))) - XCTAssertTrue(value is UInt64) - XCTAssertEqual(value as! UInt64, 100) + XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString("0x\(prefix())1819\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength))) + XCTAssertTrue(value is UInt64) + XCTAssertEqual(value as! UInt64, 25) - XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString("0x1903E8"))) - XCTAssertTrue(value is UInt64) - XCTAssertEqual(value as! UInt64, 1000) + XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString("0x\(prefix())1864\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength))) + XCTAssertTrue(value is UInt64) + XCTAssertEqual(value as! UInt64, 100) - XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString("0x1A000F4240"))) - XCTAssertTrue(value is UInt64) - XCTAssertEqual(value as! UInt64, 1000000) + XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString("0x\(prefix())1903E8\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength))) + XCTAssertTrue(value is UInt64) + XCTAssertEqual(value as! UInt64, 1000) - XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString("0x1B000000E8D4A51000"))) - XCTAssertTrue(value is UInt64) - XCTAssertEqual(value as! UInt64, 1000000000000) + XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString("0x\(prefix())1A000F4240\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength))) + XCTAssertTrue(value is UInt64) + XCTAssertEqual(value as! UInt64, 1000000) - XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString("0x1BFFFFFFFFFFFFFFFF"))) - XCTAssertTrue(value is UInt64) - XCTAssertEqual(value as! UInt64, 18446744073709551615) + XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString("0x\(prefix())1B000000E8D4A51000\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength))) + XCTAssertTrue(value is UInt64) + XCTAssertEqual(value as! UInt64, 1000000000000) - XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString("0xC249010000000000000000"))) // 18446744073709551616 - XCTAssertTrue(value is CBOR.Bignum) - XCTAssertTrue((value as! CBOR.Bignum).isPositive) - XCTAssertEqual((value as! CBOR.Bignum).content, convertFromHexString("0x010000000000000000")) + XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString("0x\(prefix())1BFFFFFFFFFFFFFFFF\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength))) + XCTAssertTrue(value is UInt64) + XCTAssertEqual(value as! UInt64, 18446744073709551615) - XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString("0x3BFFFFFFFFFFFFFFFF"))) // -18446744073709551616 - XCTAssertTrue(value is CBOR.NegativeUInt64) - XCTAssertEqual((value as! CBOR.NegativeUInt64).rawValue, .min) + XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString("0x\(prefix())C249010000000000000000\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength))) // 18446744073709551616 + XCTAssertTrue(value is CBOR.Bignum) + XCTAssertTrue((value as! CBOR.Bignum).isPositive) + XCTAssertEqual((value as! CBOR.Bignum).content, convertFromHexString("0x010000000000000000")) - XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString("0xC349010000000000000000"))) // -18446744073709551617 - XCTAssertTrue(value is CBOR.Bignum) - XCTAssertFalse((value as! CBOR.Bignum).isPositive) - XCTAssertEqual((value as! CBOR.Bignum).content, convertFromHexString("0x010000000000000000")) + XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString("0x\(prefix())3BFFFFFFFFFFFFFFFF\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength))) // -18446744073709551616 + XCTAssertTrue(value is CBOR.NegativeUInt64) + XCTAssertEqual((value as! CBOR.NegativeUInt64).rawValue, .min) - XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString("0x20"))) - XCTAssertTrue(value is Int64) - XCTAssertEqual(value as! Int64, -1) + XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString("0x\(prefix())C349010000000000000000\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength))) // -18446744073709551617 + XCTAssertTrue(value is CBOR.Bignum) + XCTAssertFalse((value as! CBOR.Bignum).isPositive) + XCTAssertEqual((value as! CBOR.Bignum).content, convertFromHexString("0x010000000000000000")) - XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString("0x29"))) - XCTAssertTrue(value is Int64) - XCTAssertEqual(value as! Int64, -10) + XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString("0x\(prefix())20\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength))) + XCTAssertTrue(value is Int64) + XCTAssertEqual(value as! Int64, -1) - XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString("0x3863"))) - XCTAssertTrue(value is Int64) - XCTAssertEqual(value as! Int64, -100) + XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString("0x\(prefix())29\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength))) + XCTAssertTrue(value is Int64) + XCTAssertEqual(value as! Int64, -10) - XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString("0x3903E7"))) - XCTAssertTrue(value is Int64) - XCTAssertEqual(value as! Int64, -1000) + XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString("0x\(prefix())3863\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength))) + XCTAssertTrue(value is Int64) + XCTAssertEqual(value as! Int64, -100) - XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString("0x3B7FFFFFFFFFFFFFFF"))) // NOT part of RFC 7049 examples - XCTAssertTrue(value is Int64) - XCTAssertEqual(value as! Int64, .min) + XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString("0x\(prefix())3903E7\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength))) + XCTAssertTrue(value is Int64) + XCTAssertEqual(value as! Int64, -1000) - XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString("0xF90000"))) - XCTAssertTrue(value is Half) - XCTAssertEqual(value as! Half, 0.0) + XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString("0x\(prefix())3B7FFFFFFFFFFFFFFF\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength))) // NOT part of RFC 7049 examples + XCTAssertTrue(value is Int64) + XCTAssertEqual(value as! Int64, .min) - XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString("0xF98000"))) - XCTAssertTrue(value is Half) - XCTAssertEqual(value as! Half, -0.0) + XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString("0x\(prefix())F90000\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength))) + XCTAssertTrue(value is Half) + XCTAssertEqual(value as! Half, 0.0) - XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString("0xF93C00"))) - XCTAssertTrue(value is Half) - XCTAssertEqual(value as! Half, 1.0) + XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString("0x\(prefix())F98000\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength))) + XCTAssertTrue(value is Half) + XCTAssertEqual(value as! Half, -0.0) - XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString("0xFB3FF199999999999A"))) - XCTAssertTrue(value is Double) - XCTAssertEqual(value as! Double, 1.1) + XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString("0x\(prefix())F93C00\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength))) + XCTAssertTrue(value is Half) + XCTAssertEqual(value as! Half, 1.0) - XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString("0xF93E00"))) - XCTAssertTrue(value is Half) - XCTAssertEqual(value as! Half, 1.5) + XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString("0x\(prefix())FB3FF199999999999A\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength))) + XCTAssertTrue(value is Double) + XCTAssertEqual(value as! Double, 1.1) - XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString("0xF97BFF"))) - XCTAssertTrue(value is Half) - XCTAssertEqual(value as! Half, 65504.0) + XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString("0x\(prefix())F93E00\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength))) + XCTAssertTrue(value is Half) + XCTAssertEqual(value as! Half, 1.5) - XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString("0xFA47C35000"))) - XCTAssertTrue(value is Float) - XCTAssertEqual(value as! Float, 100000.0) + XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString("0x\(prefix())F97BFF\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength))) + XCTAssertTrue(value is Half) + XCTAssertEqual(value as! Half, 65504.0) - XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString("0xFA7F7FFFFF"))) - XCTAssertTrue(value is Float) - XCTAssertEqual(value as! Float, 3.4028234663852886e+38) + XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString("0x\(prefix())FA47C35000\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength))) + XCTAssertTrue(value is Float) + XCTAssertEqual(value as! Float, 100000.0) - XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString("0xFB7E37E43C8800759C"))) - XCTAssertTrue(value is Double) - XCTAssertEqual(value as! Double, 1.0e+300) + XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString("0x\(prefix())FA7F7FFFFF\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength))) + XCTAssertTrue(value is Float) + XCTAssertEqual(value as! Float, 3.4028234663852886e+38) - XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString("0xF90001"))) - XCTAssertTrue(value is Half) - XCTAssertEqual(value as! Half, 5.960464477539063e-8) + XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString("0x\(prefix())FB7E37E43C8800759C\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength))) + XCTAssertTrue(value is Double) + XCTAssertEqual(value as! Double, 1.0e+300) - XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString("0xF90400"))) - XCTAssertTrue(value is Half) - XCTAssertEqual(value as! Half, 0.00006103515625) + XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString("0x\(prefix())F90001\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength))) + XCTAssertTrue(value is Half) + XCTAssertEqual(value as! Half, 5.960464477539063e-8) - XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString("0xF9C400"))) - XCTAssertTrue(value is Half) - XCTAssertEqual(value as! Half, -4.0) + XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString("0x\(prefix())F90400\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength))) + XCTAssertTrue(value is Half) + XCTAssertEqual(value as! Half, 0.00006103515625) - XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString("0xFBC010666666666666"))) - XCTAssertTrue(value is Double) - XCTAssertEqual(value as! Double, -4.1) + XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString("0x\(prefix())F9C400\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength))) + XCTAssertTrue(value is Half) + XCTAssertEqual(value as! Half, -4.0) - XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString("0xF97C00"))) - XCTAssertTrue(value is Half) - XCTAssertEqual(value as! Half, .infinity) + XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString("0x\(prefix())FBC010666666666666\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength))) + XCTAssertTrue(value is Double) + XCTAssertEqual(value as! Double, -4.1) - XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString("0xF97E00"))) - XCTAssertTrue(value is Half) - XCTAssertTrue((value as! Half).isNaN) + XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString("0x\(prefix())F97C00\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength))) + XCTAssertTrue(value is Half) + XCTAssertEqual(value as! Half, .infinity) - XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString("0xF9FC00"))) - XCTAssertTrue(value is Half) - XCTAssertEqual(value as! Half, -.infinity) + XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString("0x\(prefix())F97E00\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength))) + XCTAssertTrue(value is Half) + XCTAssertTrue((value as! Half).isNaN) - XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString("0xFA7F800000"))) - XCTAssertTrue(value is Float) - XCTAssertEqual(value as! Float, .infinity) + XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString("0x\(prefix())F9FC00\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength))) + XCTAssertTrue(value is Half) + XCTAssertEqual(value as! Half, -.infinity) - XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString("0xFA7FC00000"))) - XCTAssertTrue(value is Float) - XCTAssertTrue((value as! Float).isNaN) + XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString("0x\(prefix())FA7F800000\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength))) + XCTAssertTrue(value is Float) + XCTAssertEqual(value as! Float, .infinity) - XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString("0xFAFF800000"))) - XCTAssertTrue(value is Float) - XCTAssertEqual(value as! Float, -.infinity) + XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString("0x\(prefix())FA7FC00000\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength))) + XCTAssertTrue(value is Float) + XCTAssertTrue((value as! Float).isNaN) - XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString("0xFB7FF0000000000000"))) - XCTAssertTrue(value is Double) - XCTAssertEqual(value as! Double, .infinity) + XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString("0x\(prefix())FAFF800000\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength))) + XCTAssertTrue(value is Float) + XCTAssertEqual(value as! Float, -.infinity) - XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString("0xFB7FF8000000000000"))) - XCTAssertTrue(value is Double) - XCTAssertTrue((value as! Double).isNaN) + XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString("0x\(prefix())FB7FF0000000000000\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength))) + XCTAssertTrue(value is Double) + XCTAssertEqual(value as! Double, .infinity) - XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString("0xFBFFF0000000000000"))) - XCTAssertTrue(value is Double) - XCTAssertEqual(value as! Double, -.infinity) + XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString("0x\(prefix())FB7FF8000000000000\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength))) + XCTAssertTrue(value is Double) + XCTAssertTrue((value as! Double).isNaN) - XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString("0xF4"))) - XCTAssertTrue(value is Bool) - XCTAssertFalse(value as! Bool) + XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString("0x\(prefix())FBFFF0000000000000\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength))) + XCTAssertTrue(value is Double) + XCTAssertEqual(value as! Double, -.infinity) - XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString("0xF5"))) - XCTAssertTrue(value is Bool) - XCTAssertTrue(value as! Bool) + XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString("0x\(prefix())F4\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength))) + XCTAssertTrue(value is Bool) + XCTAssertFalse(value as! Bool) - XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString("0xF6"))) - XCTAssertTrue(value is CBOR.Null) + XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString("0x\(prefix())F5\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength))) + XCTAssertTrue(value is Bool) + XCTAssertTrue(value as! Bool) - XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString("0xF7"))) - XCTAssertTrue(value is CBOR.Undefined) + XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString("0x\(prefix())F6\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength))) + XCTAssertTrue(value is CBOR.Null) - XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString("0xF0"))) - XCTAssertTrue(value is CBOR.SimpleValue) - XCTAssertEqual((value as! CBOR.SimpleValue).rawValue, 16) + XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString("0x\(prefix())F7\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength))) + XCTAssertTrue(value is CBOR.Undefined) - XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString("0xF818"))) - XCTAssertTrue(value is CBOR.SimpleValue) - XCTAssertEqual((value as! CBOR.SimpleValue).rawValue, 24) + XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString("0x\(prefix())F0\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength))) + XCTAssertTrue(value is CBOR.SimpleValue) + XCTAssertEqual((value as! CBOR.SimpleValue).rawValue, 16) - XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString("0xF8FF"))) - XCTAssertTrue(value is CBOR.SimpleValue) - XCTAssertEqual((value as! CBOR.SimpleValue).rawValue, 255) + XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString("0x\(prefix())F818\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength))) + XCTAssertTrue(value is CBOR.SimpleValue) + XCTAssertEqual((value as! CBOR.SimpleValue).rawValue, 24) - XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString("0xC074323031332D30332D32315432303A30343A30305A"))) - XCTAssertTrue(value is Date) - XCTAssertEqual(value as! Date, rfc3339Date()) + XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString("0x\(prefix())F8FF\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength))) + XCTAssertTrue(value is CBOR.SimpleValue) + XCTAssertEqual((value as! CBOR.SimpleValue).rawValue, 255) - XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString("0xC11A514B67B0"))) - XCTAssertTrue(value is Date) - XCTAssertEqual(value as! Date, Date(timeIntervalSince1970: 1363896240)) + XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString("0x\(prefix())C074323031332D30332D32315432303A30343A30305A\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength))) + XCTAssertTrue(value is Date) + XCTAssertEqual(value as! Date, rfc3339Date()) - XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString("0xC1FB41D452D9EC200000"))) - XCTAssertTrue(value is Date) - XCTAssertEqual(value as! Date, Date(timeIntervalSince1970: 1363896240.5)) + XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString("0x\(prefix())C11A514B67B0\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength))) + XCTAssertTrue(value is Date) + XCTAssertEqual(value as! Date, Date(timeIntervalSince1970: 1363896240)) - XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString("0xD74401020304"))) - XCTAssertTrue(value is Data) - XCTAssertEqual(value as! Data, convertFromHexString("0x01020304")) + XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString("0x\(prefix())C1FB41D452D9EC200000\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength))) + XCTAssertTrue(value is Date) + XCTAssertEqual(value as! Date, Date(timeIntervalSince1970: 1363896240.5)) - XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString("0xD818456449455446"))) - XCTAssertTrue(value is Data) - XCTAssertEqual(value as! Data, convertFromHexString("0x6449455446")) + XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString("0x\(prefix())D74401020304\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength))) + XCTAssertTrue(value is Data) + XCTAssertEqual(value as! Data, convertFromHexString("0x01020304")) - XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString("0xD82076687474703A2F2F7777772E6578616D706C652E636F6D"))) - XCTAssertTrue(value is URL) - XCTAssertEqual(value as! URL, URL(string: "http://www.example.com")!) + XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString("0x\(prefix())D818456449455446\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength))) + XCTAssertTrue(value is Data) + XCTAssertEqual(value as! Data, convertFromHexString("0x6449455446")) - XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString("0x40"))) - XCTAssertTrue(value is Data) - XCTAssertEqual(value as! Data, Data()) + XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString("0x\(prefix())D82076687474703A2F2F7777772E6578616D706C652E636F6D\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength))) + XCTAssertTrue(value is URL) + XCTAssertEqual(value as! URL, URL(string: "http://www.example.com")!) - XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString("0x4401020304"))) - XCTAssertTrue(value is Data) - XCTAssertEqual(value as! Data, convertFromHexString("0x01020304")) + XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString("0x\(prefix())40\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength))) + XCTAssertTrue(value is Data) + XCTAssertEqual(value as! Data, Data()) - XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString("0x60"))) - XCTAssertTrue(value is String) - XCTAssertEqual(value as! String, "") + XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString("0x\(prefix())4401020304\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength))) + XCTAssertTrue(value is Data) + XCTAssertEqual(value as! Data, convertFromHexString("0x\(prefix())01020304\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength)) - XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString("0x6161"))) - XCTAssertTrue(value is String) - XCTAssertEqual(value as! String, "a") + XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString("0x\(prefix())60\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength))) + XCTAssertTrue(value is String) + XCTAssertEqual(value as! String, "") - XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString("0x6449455446"))) - XCTAssertTrue(value is String) - XCTAssertEqual(value as! String, "IETF") + XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString("0x\(prefix())6161\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength))) + XCTAssertTrue(value is String) + XCTAssertEqual(value as! String, "a") - XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString("0x62225C"))) - XCTAssertTrue(value is String) - XCTAssertEqual(value as! String, "\"\\") + XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString("0x\(prefix())6449455446\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength))) + XCTAssertTrue(value is String) + XCTAssertEqual(value as! String, "IETF") - XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString("0x62C3BC"))) - XCTAssertTrue(value is String) - XCTAssertEqual(value as! String, "\u{00FC}") + XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString("0x\(prefix())62225C\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength))) + XCTAssertTrue(value is String) + XCTAssertEqual(value as! String, "\"\\") - XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString("0x63E6B0B4"))) - XCTAssertTrue(value is String) - XCTAssertEqual(value as! String, "\u{6C34}") + XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString("0x\(prefix())62C3BC\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength))) + XCTAssertTrue(value is String) + XCTAssertEqual(value as! String, "\u{00FC}") - XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString("0x64F0908591"))) - XCTAssertTrue(value is String) - XCTAssertEqual(value as! String, "\u{10151}") + XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString("0x\(prefix())63E6B0B4\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength))) + XCTAssertTrue(value is String) + XCTAssertEqual(value as! String, "\u{6C34}") + + XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString("0x\(prefix())64F0908591\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength))) + XCTAssertTrue(value is String) + XCTAssertEqual(value as! String, "\u{10151}") + } + } } func testAppendixAComplexExamples1() { @@ -287,31 +300,39 @@ class CBORParserTests: XCTestCase { // 15, 16, 17, 18, 19, 20, 21, // 22, 23, 24, 25] - var value: Any! - let dataStrings = [ - ("0x80", "0x83010203", "0x98190102030405060708090A0B0C0D0E0F101112131415161718181819"), // Definite Length Arrays - ("0x9FFF", "0x9F010203FF", "0x9F0102030405060708090A0B0C0D0E0F101112131415161718181819FF") // Indefinite Length Arrays - ] - - for dataString in dataStrings { - XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString(dataString.0))) - XCTAssertTrue(value is ArrayWrapper) - XCTAssertTrue((value as! ArrayWrapper).isEmpty) - - XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString(dataString.1))) - XCTAssertTrue(value is ArrayWrapper) - XCTAssertEqual((value as! ArrayWrapper).count, 3) - XCTAssertTrue((value as! ArrayWrapper).array is [UInt64]) - XCTAssertEqual((value as! ArrayWrapper).array as! [UInt64], [1, 2, 3]) - - XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString(dataString.2))) - XCTAssertTrue(value is ArrayWrapper) - XCTAssertEqual((value as! ArrayWrapper).count, 25) - XCTAssertTrue((value as! ArrayWrapper).array is [UInt64]) - XCTAssertEqual((value as! ArrayWrapper).array as! [UInt64], [1, 2, 3, 4, 5, 6, 7, - 8, 9, 10, 11, 12, 13, 14, - 15, 16, 17, 18, 19, 20, 21, - 22, 23, 24, 25]) + for prefixLength in prefixLengths { + func prefix() -> String { return randomHexString(ofLength: prefixLength) } + + for suffixLength in suffixLengths { + func suffix() -> String { return randomHexString(ofLength: suffixLength) } + + var value: Any! + let dataStrings = [ + ("0x\(prefix())80\(suffix())", "0x\(prefix())83010203\(suffix())", "0x\(prefix())98190102030405060708090A0B0C0D0E0F101112131415161718181819\(suffix())"), // Definite Length Arrays + ("0x\(prefix())9FFF\(suffix())", "0x\(prefix())9F010203FF\(suffix())", "0x\(prefix())9F0102030405060708090A0B0C0D0E0F101112131415161718181819FF\(suffix())") // Indefinite Length Arrays + ] + + for dataString in dataStrings { + XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString(dataString.0, prefixLength: prefixLength, suffixLength: suffixLength))) + XCTAssertTrue(value is ArrayWrapper) + XCTAssertTrue((value as! ArrayWrapper).isEmpty) + + XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString(dataString.1, prefixLength: prefixLength, suffixLength: suffixLength))) + XCTAssertTrue(value is ArrayWrapper) + XCTAssertEqual((value as! ArrayWrapper).count, 3) + XCTAssertTrue((value as! ArrayWrapper).array is [UInt64]) + XCTAssertEqual((value as! ArrayWrapper).array as! [UInt64], [1, 2, 3]) + + XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString(dataString.2, prefixLength: prefixLength, suffixLength: suffixLength))) + XCTAssertTrue(value is ArrayWrapper) + XCTAssertEqual((value as! ArrayWrapper).count, 25) + XCTAssertTrue((value as! ArrayWrapper).array is [UInt64]) + XCTAssertEqual((value as! ArrayWrapper).array as! [UInt64], [1, 2, 3, 4, 5, 6, 7, + 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, + 22, 23, 24, 25]) + } + } } } @@ -320,33 +341,41 @@ class CBORParserTests: XCTestCase { // // [1, [2, 3], [4, 5]] - var value: Any! - let dataStrings: [String] = [ - "0x8301820203820405", // Definite/Definite/Definite Length Arrays - "0x83018202039F0405FF", // Definite/Definite/Indefinite Length Arrays - "0x83019F0203FF820405", // Definite/Indefinite/Definite Length Arrays - "0x83019F0203FF9F0405FF", // Definite/Indefinite/Indefinite Length Arrays - "0x9F01820203820405FF", // Indefinite/Definite/Definite Length Arrays - "0x9F018202039F0405FFFF", // Indefinite/Definite/Indefinite Length Arrays - "0x9F019F0203FF820405FF", // Indefinite/Indefinite/Definite Length Arrays - "0x9F019F0203FF9F0405FFFF" // Indefinite/Indefinite/Indefinite Length Arrays - ] - - for dataString in dataStrings { - XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString(dataString))) - XCTAssertTrue(value is ArrayWrapper) - XCTAssertEqual((value as! ArrayWrapper).count, 3) - - XCTAssertTrue((value as! ArrayWrapper).array[0] is UInt64) - XCTAssertEqual((value as! ArrayWrapper).array[0] as! UInt64, 1) - - XCTAssertTrue((value as! ArrayWrapper)[1] is ArrayWrapper) - XCTAssertTrue(((value as! ArrayWrapper)[1] as! ArrayWrapper).array is [UInt64]) - XCTAssertEqual(((value as! ArrayWrapper)[1] as! ArrayWrapper).array as! [UInt64], [2, 3]) - - XCTAssertTrue((value as! ArrayWrapper)[2] is ArrayWrapper) - XCTAssertTrue(((value as! ArrayWrapper)[2] as! ArrayWrapper).array is [UInt64]) - XCTAssertEqual(((value as! ArrayWrapper)[2] as! ArrayWrapper).array as! [UInt64], [4, 5]) + for prefixLength in prefixLengths { + func prefix() -> String { return randomHexString(ofLength: prefixLength) } + + for suffixLength in suffixLengths { + func suffix() -> String { return randomHexString(ofLength: suffixLength) } + + var value: Any! + let dataStrings: [String] = [ + "0x\(prefix())8301820203820405\(suffix())", // Definite/Definite/Definite Length Arrays + "0x\(prefix())83018202039F0405FF\(suffix())", // Definite/Definite/Indefinite Length Arrays + "0x\(prefix())83019F0203FF820405\(suffix())", // Definite/Indefinite/Definite Length Arrays + "0x\(prefix())83019F0203FF9F0405FF\(suffix())", // Definite/Indefinite/Indefinite Length Arrays + "0x\(prefix())9F01820203820405FF\(suffix())", // Indefinite/Definite/Definite Length Arrays + "0x\(prefix())9F018202039F0405FFFF\(suffix())", // Indefinite/Definite/Indefinite Length Arrays + "0x\(prefix())9F019F0203FF820405FF\(suffix())", // Indefinite/Indefinite/Definite Length Arrays + "0x\(prefix())9F019F0203FF9F0405FFFF\(suffix())" // Indefinite/Indefinite/Indefinite Length Arrays + ] + + for dataString in dataStrings { + XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString(dataString, prefixLength: prefixLength, suffixLength: suffixLength))) + XCTAssertTrue(value is ArrayWrapper) + XCTAssertEqual((value as! ArrayWrapper).count, 3) + + XCTAssertTrue((value as! ArrayWrapper).array[0] is UInt64) + XCTAssertEqual((value as! ArrayWrapper).array[0] as! UInt64, 1) + + XCTAssertTrue((value as! ArrayWrapper)[1] is ArrayWrapper) + XCTAssertTrue(((value as! ArrayWrapper)[1] as! ArrayWrapper).array is [UInt64]) + XCTAssertEqual(((value as! ArrayWrapper)[1] as! ArrayWrapper).array as! [UInt64], [2, 3]) + + XCTAssertTrue((value as! ArrayWrapper)[2] is ArrayWrapper) + XCTAssertTrue(((value as! ArrayWrapper)[2] as! ArrayWrapper).array is [UInt64]) + XCTAssertEqual(((value as! ArrayWrapper)[2] as! ArrayWrapper).array as! [UInt64], [4, 5]) + } + } } } @@ -357,32 +386,40 @@ class CBORParserTests: XCTestCase { // // [1: "a", 2: "b"] - var value: Any! - let dataStrings = [ - ("0xA201020304", "0xA2016161026162"), // Definite Length Maps - ("0xBF01020304FF", "0xBF016161026162FF") // Indefinite Length Map - ] + for prefixLength in prefixLengths { + func prefix() -> String { return randomHexString(ofLength: prefixLength) } + + for suffixLength in suffixLengths { + func suffix() -> String { return randomHexString(ofLength: suffixLength) } - for dataString in dataStrings { - XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString(dataString.0))) - XCTAssertTrue(value is CodingKeyDictionary) - XCTAssertEqual((value as! CodingKeyDictionary).count, 2) + var value: Any! + let dataStrings = [ + ("0x\(prefix())A201020304\(suffix())", "0x\(prefix())A2016161026162\(suffix())"), // Definite Length Maps + ("0x\(prefix())BF01020304FF\(suffix())", "0x\(prefix())BF016161026162FF\(suffix())") // Indefinite Length Map + ] - XCTAssertTrue((value as! CodingKeyDictionary)[CBOR.CodingKey(intValue: 1)!] is UInt64) - XCTAssertEqual((value as! CodingKeyDictionary)[CBOR.CodingKey(intValue: 1)!] as! UInt64, 2) + for dataString in dataStrings { + XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString(dataString.0, prefixLength: prefixLength, suffixLength: suffixLength))) + XCTAssertTrue(value is CodingKeyDictionary) + XCTAssertEqual((value as? CodingKeyDictionary)?.count, 2) - XCTAssertTrue((value as! CodingKeyDictionary)[CBOR.CodingKey(intValue: 3)!] is UInt64) - XCTAssertEqual((value as! CodingKeyDictionary)[CBOR.CodingKey(intValue: 3)!] as! UInt64, 4) + XCTAssertTrue((value as? CodingKeyDictionary)?[CBOR.CodingKey(intValue: 1)] is UInt64) + XCTAssertEqual((value as? CodingKeyDictionary)?[CBOR.CodingKey(intValue: 1)] as? UInt64, 2) - XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString(dataString.1))) - XCTAssertTrue(value is CodingKeyDictionary) - XCTAssertEqual((value as! CodingKeyDictionary).count, 2) + XCTAssertTrue((value as? CodingKeyDictionary)?[CBOR.CodingKey(intValue: 3)] is UInt64) + XCTAssertEqual((value as? CodingKeyDictionary)?[CBOR.CodingKey(intValue: 3)] as? UInt64, 4) - XCTAssertTrue((value as! CodingKeyDictionary)[CBOR.CodingKey(intValue: 1)!] is String) - XCTAssertEqual((value as! CodingKeyDictionary)[CBOR.CodingKey(intValue: 1)!] as! String, "a") + XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString(dataString.1, prefixLength: prefixLength, suffixLength: suffixLength))) + XCTAssertTrue(value is CodingKeyDictionary) + XCTAssertEqual((value as? CodingKeyDictionary)?.count, 2) - XCTAssertTrue((value as! CodingKeyDictionary)[CBOR.CodingKey(intValue: 2)!] is String) - XCTAssertEqual((value as! CodingKeyDictionary)[CBOR.CodingKey(intValue: 2)!] as! String, "b") + XCTAssertTrue((value as? CodingKeyDictionary)?[CBOR.CodingKey(intValue: 1)] is String) + XCTAssertEqual((value as? CodingKeyDictionary)?[CBOR.CodingKey(intValue: 1)] as? String, "a") + + XCTAssertTrue((value as? CodingKeyDictionary)?[CBOR.CodingKey(intValue: 2)] is String) + XCTAssertEqual((value as? CodingKeyDictionary)?[CBOR.CodingKey(intValue: 2)] as? String, "b") + } + } } } @@ -391,25 +428,33 @@ class CBORParserTests: XCTestCase { // // ["a": 1, "b": [2, 3]] - var value: Any! - let dataStrings = [ - "0xA26161016162820203", // Definite/Definite Length Containers - "0xA261610161629F0203FF", // Definite/Indefinite Length Containers - "0xBF6161016162820203FF", // Indefinite/Definite Length Containers - "0xBF61610161629F0203FFFF" // Indefinite/Indefinite Length Containers - ] - - for dataString in dataStrings { - XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString(dataString))) - XCTAssertTrue(value is CodingKeyDictionary) - XCTAssertEqual((value as! CodingKeyDictionary).count, 2) - - XCTAssertTrue((value as! CodingKeyDictionary)[CBOR.CodingKey(stringValue: "a")!] is UInt64) - XCTAssertEqual((value as! CodingKeyDictionary)[CBOR.CodingKey(stringValue: "a")!] as! UInt64, 1) - - XCTAssertTrue((value as! CodingKeyDictionary)[CBOR.CodingKey(stringValue: "b")!] is ArrayWrapper) - XCTAssertTrue(((value as! CodingKeyDictionary)[CBOR.CodingKey(stringValue: "b")!] as! ArrayWrapper).array is [UInt64]) - XCTAssertEqual(((value as! CodingKeyDictionary)[CBOR.CodingKey(stringValue: "b")!] as! ArrayWrapper).array as! [UInt64], [2 ,3]) + for prefixLength in prefixLengths { + func prefix() -> String { return randomHexString(ofLength: prefixLength) } + + for suffixLength in suffixLengths { + func suffix() -> String { return randomHexString(ofLength: suffixLength) } + + var value: Any! + let dataStrings = [ + "0x\(prefix())A26161016162820203\(suffix())", // Definite/Definite Length Containers + "0x\(prefix())A261610161629F0203FF\(suffix())", // Definite/Indefinite Length Containers + "0x\(prefix())BF6161016162820203FF\(suffix())", // Indefinite/Definite Length Containers + "0x\(prefix())BF61610161629F0203FFFF\(suffix())" // Indefinite/Indefinite Length Containers + ] + + for dataString in dataStrings { + XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString(dataString, prefixLength: prefixLength, suffixLength: suffixLength))) + XCTAssertTrue(value is CodingKeyDictionary) + XCTAssertEqual((value as? CodingKeyDictionary)?.count, 2) + + XCTAssertTrue((value as? CodingKeyDictionary)?[CBOR.CodingKey(stringValue: "a")] is UInt64) + XCTAssertEqual((value as? CodingKeyDictionary)?[CBOR.CodingKey(stringValue: "a")] as? UInt64, 1) + + XCTAssertTrue((value as? CodingKeyDictionary)?[CBOR.CodingKey(stringValue: "b")] is ArrayWrapper) + XCTAssertTrue(((value as? CodingKeyDictionary)?[CBOR.CodingKey(stringValue: "b")] as? ArrayWrapper)?.array is [UInt64]) + XCTAssertEqual(((value as? CodingKeyDictionary)?[CBOR.CodingKey(stringValue: "b")] as? ArrayWrapper)?.array as? [UInt64], [2 ,3]) + } + } } } @@ -418,25 +463,33 @@ class CBORParserTests: XCTestCase { // // ["a", ["b": "c"]] - var value: Any! - let dataStrings = [ - "0x826161A161626163", // Definite/Definite Length Containers - "0x826161BF61626163FF", // Definite/Indefinite Length Containers - "0x9F6161A161626163FF", // Indefinite/Definite Length Containers - "0x9F6161BF61626163FFFF" // Indefinite/Indefinite Length Containers - ] - - for dataString in dataStrings { - XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString(dataString))) - XCTAssertTrue(value is ArrayWrapper) - XCTAssertEqual((value as! ArrayWrapper).count, 2) - - XCTAssertTrue((value as! ArrayWrapper).array[0] is String) - XCTAssertEqual((value as! ArrayWrapper).array[0] as! String, "a") - - XCTAssertTrue((value as! ArrayWrapper)[1] is CodingKeyDictionary) - XCTAssertTrue(((value as! ArrayWrapper)[1] as! CodingKeyDictionary)[CBOR.CodingKey(stringValue: "b")!] is String) - XCTAssertEqual(((value as! ArrayWrapper)[1] as! CodingKeyDictionary)[CBOR.CodingKey(stringValue: "b")!] as! String, "c") + for prefixLength in prefixLengths { + func prefix() -> String { return randomHexString(ofLength: prefixLength) } + + for suffixLength in suffixLengths { + func suffix() -> String { return randomHexString(ofLength: suffixLength) } + + var value: Any! + let dataStrings = [ + "0x\(prefix())826161A161626163\(suffix())", // Definite/Definite Length Containers + "0x\(prefix())826161BF61626163FF\(suffix())", // Definite/Indefinite Length Containers + "0x\(prefix())9F6161A161626163FF\(suffix())", // Indefinite/Definite Length Containers + "0x\(prefix())9F6161BF61626163FFFF\(suffix())" // Indefinite/Indefinite Length Containers + ] + + for dataString in dataStrings { + XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString(dataString, prefixLength: prefixLength, suffixLength: suffixLength))) + XCTAssertTrue(value is ArrayWrapper) + XCTAssertEqual((value as? ArrayWrapper)?.count, 2) + + XCTAssertTrue((value as? ArrayWrapper)?.array[0] is String) + XCTAssertEqual((value as? ArrayWrapper)?.array[0] as? String, "a") + + XCTAssertTrue((value as? ArrayWrapper)?[1] is CodingKeyDictionary) + XCTAssertTrue(((value as? ArrayWrapper)?[1] as? CodingKeyDictionary)?[CBOR.CodingKey(stringValue: "b")] is String) + XCTAssertEqual(((value as? ArrayWrapper)?[1] as? CodingKeyDictionary)?[CBOR.CodingKey(stringValue: "b")] as? String, "c") + } + } } } @@ -445,62 +498,78 @@ class CBORParserTests: XCTestCase { // // ["a": "A", "b": "B", "c": "C", "d": "D", "e": "E"] - var value: Any! - let dataStrings = [ - "0xA56161614161626142616361436164614461656145", // Definite Length Map - "0xBF6161614161626142616361436164614461656145FF" // Indefinite Length Map - ] + for prefixLength in prefixLengths { + func prefix() -> String { return randomHexString(ofLength: prefixLength) } + + for suffixLength in suffixLengths { + func suffix() -> String { return randomHexString(ofLength: suffixLength) } - for dataString in dataStrings { - XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString(dataString))) - XCTAssertTrue(value is CodingKeyDictionary) - XCTAssertEqual((value as! CodingKeyDictionary).count, 5) + var value: Any! + let dataStrings = [ + "0x\(prefix())A56161614161626142616361436164614461656145\(suffix())", // Definite Length Map + "0x\(prefix())BF6161614161626142616361436164614461656145FF\(suffix())" // Indefinite Length Map + ] - XCTAssertTrue((value as! CodingKeyDictionary)[CBOR.CodingKey(stringValue: "a")!] is String) - XCTAssertEqual((value as! CodingKeyDictionary)[CBOR.CodingKey(stringValue: "a")!] as! String, "A") + for dataString in dataStrings { + XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString(dataString, prefixLength: prefixLength, suffixLength: suffixLength))) + XCTAssertTrue(value is CodingKeyDictionary) + XCTAssertEqual((value as? CodingKeyDictionary)?.count, 5) - XCTAssertTrue((value as! CodingKeyDictionary)[CBOR.CodingKey(stringValue: "b")!] is String) - XCTAssertEqual((value as! CodingKeyDictionary)[CBOR.CodingKey(stringValue: "b")!] as! String, "B") + XCTAssertTrue((value as? CodingKeyDictionary)?[CBOR.CodingKey(stringValue: "a")] is String) + XCTAssertEqual((value as? CodingKeyDictionary)?[CBOR.CodingKey(stringValue: "a")] as? String, "A") - XCTAssertTrue((value as! CodingKeyDictionary)[CBOR.CodingKey(stringValue: "c")!] is String) - XCTAssertEqual((value as! CodingKeyDictionary)[CBOR.CodingKey(stringValue: "c")!] as! String, "C") + XCTAssertTrue((value as? CodingKeyDictionary)?[CBOR.CodingKey(stringValue: "b")] is String) + XCTAssertEqual((value as? CodingKeyDictionary)?[CBOR.CodingKey(stringValue: "b")] as? String, "B") - XCTAssertTrue((value as! CodingKeyDictionary)[CBOR.CodingKey(stringValue: "d")!] is String) - XCTAssertEqual((value as! CodingKeyDictionary)[CBOR.CodingKey(stringValue: "d")!] as! String, "D") + XCTAssertTrue((value as? CodingKeyDictionary)?[CBOR.CodingKey(stringValue: "c")] is String) + XCTAssertEqual((value as? CodingKeyDictionary)?[CBOR.CodingKey(stringValue: "c")] as? String, "C") - XCTAssertTrue((value as! CodingKeyDictionary)[CBOR.CodingKey(stringValue: "e")!] is String) - XCTAssertEqual((value as! CodingKeyDictionary)[CBOR.CodingKey(stringValue: "e")!] as! String, "E") + XCTAssertTrue((value as? CodingKeyDictionary)?[CBOR.CodingKey(stringValue: "d")] is String) + XCTAssertEqual((value as? CodingKeyDictionary)?[CBOR.CodingKey(stringValue: "d")] as? String, "D") + + XCTAssertTrue((value as? CodingKeyDictionary)?[CBOR.CodingKey(stringValue: "e")] is String) + XCTAssertEqual((value as? CodingKeyDictionary)?[CBOR.CodingKey(stringValue: "e")] as? String, "E") + } + } } } func testAppendixAComplexExamples7() { // [1: "A", 2: "B", 3: "C", 4: "D", 5: "E"] - var value: Any! - let dataStrings = [ - "0xA5016141026142036143046144056145", // Definite Length Map - "0xBF016141026142036143046144056145FF" // Indefinite Length Map - ] + for prefixLength in prefixLengths { + func prefix() -> String { return randomHexString(ofLength: prefixLength) } + + for suffixLength in suffixLengths { + func suffix() -> String { return randomHexString(ofLength: suffixLength) } + + var value: Any! + let dataStrings = [ + "0x\(prefix())A5016141026142036143046144056145\(suffix())", // Definite Length Map + "0x\(prefix())BF016141026142036143046144056145FF\(suffix())" // Indefinite Length Map + ] - for dataString in dataStrings { - XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString(dataString))) - XCTAssertTrue(value is CodingKeyDictionary) - XCTAssertEqual((value as! CodingKeyDictionary).count, 5) + for dataString in dataStrings { + XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString(dataString, prefixLength: prefixLength, suffixLength: suffixLength))) + XCTAssertTrue(value is CodingKeyDictionary) + XCTAssertEqual((value as? CodingKeyDictionary)?.count, 5) - XCTAssertTrue((value as! CodingKeyDictionary)[CBOR.CodingKey(intValue: 1)!] is String) - XCTAssertEqual((value as! CodingKeyDictionary)[CBOR.CodingKey(intValue: 1)!] as! String, "A") + XCTAssertTrue((value as? CodingKeyDictionary)?[CBOR.CodingKey(intValue: 1)] is String) + XCTAssertEqual((value as? CodingKeyDictionary)?[CBOR.CodingKey(intValue: 1)] as? String, "A") - XCTAssertTrue((value as! CodingKeyDictionary)[CBOR.CodingKey(intValue: 2)!] is String) - XCTAssertEqual((value as! CodingKeyDictionary)[CBOR.CodingKey(intValue: 2)!] as! String, "B") + XCTAssertTrue((value as? CodingKeyDictionary)?[CBOR.CodingKey(intValue: 2)] is String) + XCTAssertEqual((value as? CodingKeyDictionary)?[CBOR.CodingKey(intValue: 2)] as? String, "B") - XCTAssertTrue((value as! CodingKeyDictionary)[CBOR.CodingKey(intValue: 3)!] is String) - XCTAssertEqual((value as! CodingKeyDictionary)[CBOR.CodingKey(intValue: 3)!] as! String, "C") + XCTAssertTrue((value as? CodingKeyDictionary)?[CBOR.CodingKey(intValue: 3)] is String) + XCTAssertEqual((value as? CodingKeyDictionary)?[CBOR.CodingKey(intValue: 3)] as? String, "C") - XCTAssertTrue((value as! CodingKeyDictionary)[CBOR.CodingKey(intValue: 4)!] is String) - XCTAssertEqual((value as! CodingKeyDictionary)[CBOR.CodingKey(intValue: 4)!] as! String, "D") + XCTAssertTrue((value as? CodingKeyDictionary)?[CBOR.CodingKey(intValue: 4)] is String) + XCTAssertEqual((value as? CodingKeyDictionary)?[CBOR.CodingKey(intValue: 4)] as? String, "D") - XCTAssertTrue((value as! CodingKeyDictionary)[CBOR.CodingKey(intValue: 5)!] is String) - XCTAssertEqual((value as! CodingKeyDictionary)[CBOR.CodingKey(intValue: 5)!] as! String, "E") + XCTAssertTrue((value as? CodingKeyDictionary)?[CBOR.CodingKey(intValue: 5)] is String) + XCTAssertEqual((value as? CodingKeyDictionary)?[CBOR.CodingKey(intValue: 5)] as? String, "E") + } + } } } @@ -509,14 +578,22 @@ class CBORParserTests: XCTestCase { // // (_ h'0102', h'030405') - var value: Any! + for prefixLength in prefixLengths { + func prefix() -> String { return randomHexString(ofLength: prefixLength) } - XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString("0x5F42010243030405FF"))) - XCTAssertTrue(value is CBOR.IndefiniteLengthData) + for suffixLength in suffixLengths { + func suffix() -> String { return randomHexString(ofLength: suffixLength) } - XCTAssertEqual((value as! CBOR.IndefiniteLengthData).chunks.count, 2) - XCTAssertEqual((value as! CBOR.IndefiniteLengthData).chunks[0], convertFromHexString("0x0102")) - XCTAssertEqual((value as! CBOR.IndefiniteLengthData).chunks[1], convertFromHexString("0x030405")) + var value: Any! + + XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString("0x\(prefix())5F42010243030405FF\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength))) + XCTAssertTrue(value is CBOR.IndefiniteLengthData) + + XCTAssertEqual((value as! CBOR.IndefiniteLengthData).chunks.count, 2) + XCTAssertEqual((value as! CBOR.IndefiniteLengthData).chunks[0], convertFromHexString("0x0102")) + XCTAssertEqual((value as! CBOR.IndefiniteLengthData).chunks[1], convertFromHexString("0x030405")) + } + } } func testAppendixAComplexExamples9() { @@ -524,15 +601,23 @@ class CBORParserTests: XCTestCase { // // (_ "strea", "ming") - var value: Any! + for prefixLength in prefixLengths { + func prefix() -> String { return randomHexString(ofLength: prefixLength) } + + for suffixLength in suffixLengths { + func suffix() -> String { return randomHexString(ofLength: suffixLength) } - XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString("0x7F657374726561646D696E67FF"))) - XCTAssertTrue(value is CBOR.IndefiniteLengthString) + var value: Any! - XCTAssertEqual((value as! CBOR.IndefiniteLengthString).chunks.count, 2) - XCTAssertEqual((value as! CBOR.IndefiniteLengthString).stringValue, "streaming") - XCTAssertEqual((value as! CBOR.IndefiniteLengthString).chunks[0], Data("strea".utf8)) - XCTAssertEqual((value as! CBOR.IndefiniteLengthString).chunks[1], Data("ming".utf8)) + XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString("0x\(prefix())7F657374726561646D696E67FF\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength))) + XCTAssertTrue(value is CBOR.IndefiniteLengthString) + + XCTAssertEqual((value as! CBOR.IndefiniteLengthString).chunks.count, 2) + XCTAssertEqual((value as! CBOR.IndefiniteLengthString).stringValue, "streaming") + XCTAssertEqual((value as! CBOR.IndefiniteLengthString).chunks[0], Data("strea".utf8)) + XCTAssertEqual((value as! CBOR.IndefiniteLengthString).chunks[1], Data("ming".utf8)) + } + } } func testAppendixAComplexExamples10() { @@ -540,325 +625,359 @@ class CBORParserTests: XCTestCase { // // ["Fun": true, "Amt": -2] - var value: Any! - let dataStrings = [ - "0xBF6346756EF563416D7421FF", // Definite Length Map - "0xA26346756EF563416D7421" // Indefinite Length Map - ] + for prefixLength in prefixLengths { + func prefix() -> String { return randomHexString(ofLength: prefixLength) } - for dataString in dataStrings { - XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString(dataString))) - XCTAssertTrue(value is CodingKeyDictionary) - XCTAssertEqual((value as! CodingKeyDictionary).count, 2) + for suffixLength in suffixLengths { + func suffix() -> String { return randomHexString(ofLength: suffixLength) } - XCTAssertTrue((value as! CodingKeyDictionary)[CBOR.CodingKey(stringValue: "Fun")!] is Bool) - XCTAssertEqual((value as! CodingKeyDictionary)[CBOR.CodingKey(stringValue: "Fun")!] as! Bool, true) + var value: Any! + let dataStrings = [ + "0x\(prefix())BF6346756EF563416D7421FF\(suffix())", // Definite Length Map + "0x\(prefix())A26346756EF563416D7421\(suffix())" // Indefinite Length Map + ] - XCTAssertTrue((value as! CodingKeyDictionary)[CBOR.CodingKey(stringValue: "Amt")!] is Int64) - XCTAssertEqual((value as! CodingKeyDictionary)[CBOR.CodingKey(stringValue: "Amt")!] as! Int64, -2) + for dataString in dataStrings { + XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString(dataString, prefixLength: prefixLength, suffixLength: suffixLength))) + XCTAssertTrue(value is CodingKeyDictionary) + XCTAssertEqual((value as? CodingKeyDictionary)?.count, 2) + + XCTAssertTrue((value as? CodingKeyDictionary)?[CBOR.CodingKey(stringValue: "Fun")] is Bool) + XCTAssertEqual((value as? CodingKeyDictionary)?[CBOR.CodingKey(stringValue: "Fun")] as? Bool, true) + + XCTAssertTrue((value as? CodingKeyDictionary)?[CBOR.CodingKey(stringValue: "Amt")] is Int64) + XCTAssertEqual((value as? CodingKeyDictionary)?[CBOR.CodingKey(stringValue: "Amt")] as? Int64, -2) + } + } } } func testTaggedValues() { - var value: Any! - - XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString("0xC074323031332D30332D32315432303A30343A30305A"))) - XCTAssertTrue(value is Date) - XCTAssertEqual((value as! Date), rfc3339Date()) - - XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString("0xC101"))) - XCTAssertTrue(value is Date) - XCTAssertEqual((value as! Date), Date(timeIntervalSince1970: 1)) - - XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString("0xC1FB41D452D9EC200000"))) - XCTAssertTrue(value is Date) - XCTAssertEqual((value as! Date), Date(timeIntervalSince1970: 1363896240.5)) - - XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString("0xC24100"))) - XCTAssertTrue(value is CBOR.Bignum) - XCTAssertTrue((value as! CBOR.Bignum).isPositive) - XCTAssertEqual((value as! CBOR.Bignum).content, convertFromHexString("0x00")) - - XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString("0xC25F420001420203FF"))) // Indefinite length data as Bignum content - XCTAssertTrue(value is CBOR.Bignum) - XCTAssertTrue((value as! CBOR.Bignum).isPositive) - XCTAssertEqual((value as! CBOR.Bignum).content, convertFromHexString("0x00010203")) - - XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString("0xC34100"))) - XCTAssertTrue(value is CBOR.Bignum) - XCTAssertFalse((value as! CBOR.Bignum).isPositive) - XCTAssertEqual((value as! CBOR.Bignum).content, convertFromHexString("0x00")) - - XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString("0xC482010F"))) // Decimal Fraction - XCTAssertTrue(value is [Any]) - XCTAssertEqual((value as! [Any]).count, 3) - - XCTAssertTrue((value as! [Any])[0] is CBOR.Tag) - XCTAssertEqual((value as! [Any])[0] as! CBOR.Tag, .decimalFraction) - XCTAssertTrue((value as! [Any])[1] is UInt64) - XCTAssertEqual((value as! [Any])[1] as! UInt64, 1) - XCTAssertTrue((value as! [Any])[2] is UInt64) - XCTAssertEqual((value as! [Any])[2] as! UInt64, 15) - - XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString("0xC482202E"))) // Decimal Fraction - XCTAssertTrue(value is [Any]) - XCTAssertEqual((value as! [Any]).count, 3) - - XCTAssertTrue((value as! [Any])[0] is CBOR.Tag) - XCTAssertEqual((value as! [Any])[0] as! CBOR.Tag, .decimalFraction) - XCTAssertTrue((value as! [Any])[1] is Int64) - XCTAssertEqual((value as! [Any])[1] as! Int64, -1) - XCTAssertTrue((value as! [Any])[2] is Int64) - XCTAssertEqual((value as! [Any])[2] as! Int64, -15) - - XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString("0xC4823B80000000000000003B8FFFFFFFFFFFFFFF"))) // Decimal Fraction - XCTAssertTrue(value is [Any]) - XCTAssertEqual((value as! [Any]).count, 3) - - XCTAssertTrue((value as! [Any])[0] is CBOR.Tag) - XCTAssertEqual((value as! [Any])[0] as! CBOR.Tag, .decimalFraction) - XCTAssertTrue((value as! [Any])[1] is CBOR.NegativeUInt64) - XCTAssertEqual(((value as! [Any])[1] as! CBOR.NegativeUInt64).rawValue, 0x8000000000000001) - XCTAssertTrue((value as! [Any])[2] is CBOR.NegativeUInt64) - XCTAssertEqual(((value as! [Any])[2] as! CBOR.NegativeUInt64).rawValue, 0x9000000000000000) - - XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString("0xC582010F"))) // Bigfloat - XCTAssertTrue(value is [Any]) - XCTAssertEqual((value as! [Any]).count, 3) - - XCTAssertTrue((value as! [Any])[0] is CBOR.Tag) - XCTAssertEqual((value as! [Any])[0] as! CBOR.Tag, .bigfloat) - XCTAssertTrue((value as! [Any])[1] is UInt64) - XCTAssertEqual((value as! [Any])[1] as! UInt64, 1) - XCTAssertTrue((value as! [Any])[2] is UInt64) - XCTAssertEqual((value as! [Any])[2] as! UInt64, 15) - - XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString("0xC58201C2410F"))) // Bigfloat - XCTAssertTrue(value is [Any]) - XCTAssertEqual((value as! [Any]).count, 3) - - XCTAssertTrue((value as! [Any])[0] is CBOR.Tag) - XCTAssertEqual((value as! [Any])[0] as! CBOR.Tag, .bigfloat) - XCTAssertTrue((value as! [Any])[1] is UInt64) - XCTAssertEqual((value as! [Any])[1] as! UInt64, 1) - XCTAssertTrue((value as! [Any])[2] is CBOR.Bignum) - XCTAssertTrue(((value as! [Any])[2] as! CBOR.Bignum).isPositive) - XCTAssertEqual(((value as! [Any])[2] as! CBOR.Bignum).content, convertFromHexString("0x0F")) - - XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString("0xC5823B80000000000000003B8FFFFFFFFFFFFFFF"))) // Bigfloat - XCTAssertTrue(value is [Any]) - XCTAssertEqual((value as! [Any]).count, 3) - - XCTAssertTrue((value as! [Any])[0] is CBOR.Tag) - XCTAssertEqual((value as! [Any])[0] as! CBOR.Tag, .bigfloat) - XCTAssertTrue((value as! [Any])[1] is CBOR.NegativeUInt64) - XCTAssertEqual(((value as! [Any])[1] as! CBOR.NegativeUInt64).rawValue, 0x8000000000000001) - XCTAssertTrue((value as! [Any])[2] is CBOR.NegativeUInt64) - XCTAssertEqual(((value as! [Any])[2] as! CBOR.NegativeUInt64).rawValue, 0x9000000000000000) - - XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString("0xD54101"))) - XCTAssertTrue(value is Data) - XCTAssertEqual(value as! Data, convertFromHexString("0x01")) - - XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString("0xD64101"))) - XCTAssertTrue(value is Data) - XCTAssertEqual(value as! Data, convertFromHexString("0x01")) - - XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString("0xD74101"))) - XCTAssertTrue(value is Data) - XCTAssertEqual(value as! Data, convertFromHexString("0x01")) - - XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString("0xD56161"))) - XCTAssertTrue(value is String) - XCTAssertEqual(value as! String, "a") - - XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString("0xD66161"))) - XCTAssertTrue(value is String) - XCTAssertEqual(value as! String, "a") - - XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString("0xD76161"))) - XCTAssertTrue(value is String) - XCTAssertEqual(value as! String, "a") - - XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString("0xD82076687474703A2F2F7777772E6578616D706C652E636F6D"))) - XCTAssertTrue(value is URL) - XCTAssertEqual(value as! URL, URL(string: "http://www.example.com")!) - - XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString("0xD820") + (try! CBOREncoder().encode(CBOR.IndefiniteLengthString(wrapping: ["http://www.", "example.com"]))))) - XCTAssertTrue(value is URL) - XCTAssertEqual(value as! URL, URL(string: "http://www.example.com")!) - - XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString("0xD8226851304A5055673D3D"))) - XCTAssertTrue(value is Data) - XCTAssertEqual(value as! Data, Data("CBOR".utf8)) - - XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString("0xD8216651304A505567"))) - XCTAssertTrue(value is Data) - XCTAssertEqual(value as! Data, Data("CBOR".utf8)) - - XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString("0xD8246443424F52"))) - XCTAssertTrue(value is String) - XCTAssertEqual(value as! String, "CBOR") - - XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString("0xD8236573616C3F74"))) - XCTAssertTrue(value is String) - XCTAssertEqual(value as! String, "sal?t") - - XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString("0xD9D9F74443424F52"))) - XCTAssertTrue(value is Data) - XCTAssertEqual(value as! Data, Data("CBOR".utf8)) + for prefixLength in prefixLengths { + func prefix() -> String { return randomHexString(ofLength: prefixLength) } + + for suffixLength in suffixLengths { + func suffix() -> String { return randomHexString(ofLength: suffixLength) } + + var value: Any! + + XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString("0x\(prefix())C074323031332D30332D32315432303A30343A30305A\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength))) + XCTAssertTrue(value is Date) + XCTAssertEqual((value as! Date), rfc3339Date()) + + XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString("0x\(prefix())C101\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength))) + XCTAssertTrue(value is Date) + XCTAssertEqual((value as! Date), Date(timeIntervalSince1970: 1)) + + XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString("0x\(prefix())C1FB41D452D9EC200000\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength))) + XCTAssertTrue(value is Date) + XCTAssertEqual((value as! Date), Date(timeIntervalSince1970: 1363896240.5)) + + XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString("0x\(prefix())C24100\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength))) + XCTAssertTrue(value is CBOR.Bignum) + XCTAssertTrue((value as! CBOR.Bignum).isPositive) + XCTAssertEqual((value as! CBOR.Bignum).content, convertFromHexString("0x00")) + + XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString("0x\(prefix())C25F420001420203FF\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength))) // Indefinite length data as Bignum content + XCTAssertTrue(value is CBOR.Bignum) + XCTAssertTrue((value as! CBOR.Bignum).isPositive) + XCTAssertEqual((value as! CBOR.Bignum).content, convertFromHexString("0x00010203")) + + XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString("0x\(prefix())C34100\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength))) + XCTAssertTrue(value is CBOR.Bignum) + XCTAssertFalse((value as! CBOR.Bignum).isPositive) + XCTAssertEqual((value as! CBOR.Bignum).content, convertFromHexString("0x00")) + + XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString("0x\(prefix())C482010F\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength))) // Decimal Fraction + XCTAssertTrue(value is [Any]) + XCTAssertEqual((value as! [Any]).count, 3) + + XCTAssertTrue((value as! [Any])[0] is CBOR.Tag) + XCTAssertEqual((value as! [Any])[0] as! CBOR.Tag, .decimalFraction) + XCTAssertTrue((value as! [Any])[1] is UInt64) + XCTAssertEqual((value as! [Any])[1] as! UInt64, 1) + XCTAssertTrue((value as! [Any])[2] is UInt64) + XCTAssertEqual((value as! [Any])[2] as! UInt64, 15) + + XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString("0x\(prefix())C482202E\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength))) // Decimal Fraction + XCTAssertTrue(value is [Any]) + XCTAssertEqual((value as! [Any]).count, 3) + + XCTAssertTrue((value as! [Any])[0] is CBOR.Tag) + XCTAssertEqual((value as! [Any])[0] as! CBOR.Tag, .decimalFraction) + XCTAssertTrue((value as! [Any])[1] is Int64) + XCTAssertEqual((value as! [Any])[1] as! Int64, -1) + XCTAssertTrue((value as! [Any])[2] is Int64) + XCTAssertEqual((value as! [Any])[2] as! Int64, -15) + + XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString("0x\(prefix())C4823B80000000000000003B8FFFFFFFFFFFFFFF\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength))) // Decimal Fraction + XCTAssertTrue(value is [Any]) + XCTAssertEqual((value as! [Any]).count, 3) + + XCTAssertTrue((value as! [Any])[0] is CBOR.Tag) + XCTAssertEqual((value as! [Any])[0] as! CBOR.Tag, .decimalFraction) + XCTAssertTrue((value as! [Any])[1] is CBOR.NegativeUInt64) + XCTAssertEqual(((value as! [Any])[1] as! CBOR.NegativeUInt64).rawValue, 0x8000000000000001) + XCTAssertTrue((value as! [Any])[2] is CBOR.NegativeUInt64) + XCTAssertEqual(((value as! [Any])[2] as! CBOR.NegativeUInt64).rawValue, 0x9000000000000000) + + XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString("0x\(prefix())C582010F\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength))) // Bigfloat + XCTAssertTrue(value is [Any]) + XCTAssertEqual((value as! [Any]).count, 3) + + XCTAssertTrue((value as! [Any])[0] is CBOR.Tag) + XCTAssertEqual((value as! [Any])[0] as! CBOR.Tag, .bigfloat) + XCTAssertTrue((value as! [Any])[1] is UInt64) + XCTAssertEqual((value as! [Any])[1] as! UInt64, 1) + XCTAssertTrue((value as! [Any])[2] is UInt64) + XCTAssertEqual((value as! [Any])[2] as! UInt64, 15) + + XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString("0x\(prefix())C58201C2410F\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength))) // Bigfloat + XCTAssertTrue(value is [Any]) + XCTAssertEqual((value as! [Any]).count, 3) + + XCTAssertTrue((value as! [Any])[0] is CBOR.Tag) + XCTAssertEqual((value as! [Any])[0] as! CBOR.Tag, .bigfloat) + XCTAssertTrue((value as! [Any])[1] is UInt64) + XCTAssertEqual((value as! [Any])[1] as! UInt64, 1) + XCTAssertTrue((value as! [Any])[2] is CBOR.Bignum) + XCTAssertTrue(((value as! [Any])[2] as! CBOR.Bignum).isPositive) + XCTAssertEqual(((value as! [Any])[2] as! CBOR.Bignum).content, convertFromHexString("0x0F")) + + XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString("0x\(prefix())C5823B80000000000000003B8FFFFFFFFFFFFFFF\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength))) // Bigfloat + XCTAssertTrue(value is [Any]) + XCTAssertEqual((value as! [Any]).count, 3) + + XCTAssertTrue((value as! [Any])[0] is CBOR.Tag) + XCTAssertEqual((value as! [Any])[0] as! CBOR.Tag, .bigfloat) + XCTAssertTrue((value as! [Any])[1] is CBOR.NegativeUInt64) + XCTAssertEqual(((value as! [Any])[1] as! CBOR.NegativeUInt64).rawValue, 0x8000000000000001) + XCTAssertTrue((value as! [Any])[2] is CBOR.NegativeUInt64) + XCTAssertEqual(((value as! [Any])[2] as! CBOR.NegativeUInt64).rawValue, 0x9000000000000000) + + XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString("0x\(prefix())D54101\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength))) + XCTAssertTrue(value is Data) + XCTAssertEqual(value as! Data, convertFromHexString("0x01")) + + XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString("0x\(prefix())D64101\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength))) + XCTAssertTrue(value is Data) + XCTAssertEqual(value as! Data, convertFromHexString("0x01")) + + XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString("0x\(prefix())D74101\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength))) + XCTAssertTrue(value is Data) + XCTAssertEqual(value as! Data, convertFromHexString("0x01")) + + XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString("0x\(prefix())D56161\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength))) + XCTAssertTrue(value is String) + XCTAssertEqual(value as! String, "a") + + XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString("0x\(prefix())D66161\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength))) + XCTAssertTrue(value is String) + XCTAssertEqual(value as! String, "a") + + XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString("0x\(prefix())D76161\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength))) + XCTAssertTrue(value is String) + XCTAssertEqual(value as! String, "a") + + XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString("0x\(prefix())D82076687474703A2F2F7777772E6578616D706C652E636F6D\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength))) + XCTAssertTrue(value is URL) + XCTAssertEqual(value as! URL, URL(string: "http://www.example.com")!) + + do { + let hexString = "0x\(prefix())D820" + (try! CBOREncoder().encode(CBOR.IndefiniteLengthString(wrapping: ["http://www.", "example.com"]))).map { String(format: "%02X", $0) }.joined() + suffix() + + XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString(hexString, prefixLength: prefixLength, suffixLength: suffixLength))) + XCTAssertTrue(value is URL) + XCTAssertEqual(value as! URL, URL(string: "http://www.example.com")!) + } + + XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString("0x\(prefix())D8226851304A5055673D3D\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength))) + XCTAssertTrue(value is Data) + XCTAssertEqual(value as! Data, Data("CBOR".utf8)) + + XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString("0x\(prefix())D8216651304A505567\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength))) + XCTAssertTrue(value is Data) + XCTAssertEqual(value as! Data, Data("CBOR".utf8)) + + XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString("0x\(prefix())D8246443424F52\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength))) + XCTAssertTrue(value is String) + XCTAssertEqual(value as! String, "CBOR") + + XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString("0x\(prefix())D8236573616C3F74\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength))) + XCTAssertTrue(value is String) + XCTAssertEqual(value as! String, "sal?t") + + XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString("0x\(prefix())D9D9F74443424F52\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength))) + XCTAssertTrue(value is Data) + XCTAssertEqual(value as! Data, Data("CBOR".utf8)) + } + } } func testFailureCases() { - XCTAssertThrowsError(try CBORParser.parse(convertFromHexString("0x0101"))) // Multiple values outside of a container - - XCTAssertThrowsError(try CBORParser.parse(convertFromHexString("0x18"))) // Unsigned - Missing extra byte - XCTAssertThrowsError(try CBORParser.parse(convertFromHexString("0x19"))) // Unsigned - Missing two extra bytes - XCTAssertThrowsError(try CBORParser.parse(convertFromHexString("0x1A"))) // Unsigned - Missing four extra bytes - XCTAssertThrowsError(try CBORParser.parse(convertFromHexString("0x1B"))) // Unsigned - Missing eight extra bytes - - XCTAssertThrowsError(try CBORParser.parse(convertFromHexString("0x38"))) // Signed - Missing extra byte - XCTAssertThrowsError(try CBORParser.parse(convertFromHexString("0x39"))) // Signed - Missing two extra bytes - XCTAssertThrowsError(try CBORParser.parse(convertFromHexString("0x3A"))) // Signed - Missing four extra bytes - XCTAssertThrowsError(try CBORParser.parse(convertFromHexString("0x3B"))) // Signed - Missing eight extra bytes - - XCTAssertThrowsError(try CBORParser.parse(convertFromHexString("0xF8"))) // Simple - Missing extra byte - XCTAssertThrowsError(try CBORParser.parse(convertFromHexString("0xFE"))) // Major Type 7, Unassigned code - - XCTAssertThrowsError(try CBORParser.parse(convertFromHexString("0xF9"))) // Half - Missing two extra bytes - XCTAssertThrowsError(try CBORParser.parse(convertFromHexString("0xFA"))) // Float - Missing four extra bytes - XCTAssertThrowsError(try CBORParser.parse(convertFromHexString("0xFB"))) // Double - Missing eight extra bytes - - XCTAssertThrowsError(try CBORParser.parse(convertFromHexString("0xC6"))) // Invalid tag - XCTAssertThrowsError(try CBORParser.parse(convertFromHexString("0xDF"))) // Invalid tag - XCTAssertThrowsError(try CBORParser.parse(convertFromHexString("0xC0"))) // Empty Tag - Standard Date - XCTAssertThrowsError(try CBORParser.parse(convertFromHexString("0xC1"))) // Empty Tag - Epoch Date - XCTAssertThrowsError(try CBORParser.parse(convertFromHexString("0xC2"))) // Empty Tag - Positive Bignum - XCTAssertThrowsError(try CBORParser.parse(convertFromHexString("0xC3"))) // Empty Tag - Negative Bignum - XCTAssertThrowsError(try CBORParser.parse(convertFromHexString("0xC4"))) // Empty Tag - Decimal Fraction - XCTAssertThrowsError(try CBORParser.parse(convertFromHexString("0xC5"))) // Empty Tag - Bigfloat - XCTAssertThrowsError(try CBORParser.parse(convertFromHexString("0xD5"))) // Empty Tag - Base64URL Conversion - XCTAssertThrowsError(try CBORParser.parse(convertFromHexString("0xD6"))) // Empty Tag - Base64 Conversion - XCTAssertThrowsError(try CBORParser.parse(convertFromHexString("0xD7"))) // Empty Tag - Base16 Conversion - XCTAssertThrowsError(try CBORParser.parse(convertFromHexString("0xD818"))) // Empty Tag - Encoded CBOR Data - XCTAssertThrowsError(try CBORParser.parse(convertFromHexString("0xD820"))) // Empty Tag - URI - XCTAssertThrowsError(try CBORParser.parse(convertFromHexString("0xD821"))) // Empty Tag - Base64URL - XCTAssertThrowsError(try CBORParser.parse(convertFromHexString("0xD822"))) // Empty Tag - Base64 - XCTAssertThrowsError(try CBORParser.parse(convertFromHexString("0xD823"))) // Empty Tag - Regular Expression - XCTAssertThrowsError(try CBORParser.parse(convertFromHexString("0xD824"))) // Empty Tag - MIME Message - - XCTAssertThrowsError(try CBORParser.parse(convertFromHexString("0xD8216121"))) // Invalid Base64URL Data - XCTAssertThrowsError(try CBORParser.parse(convertFromHexString("0xD8226121"))) // Invalid Base64 Data - XCTAssertThrowsError(try CBORParser.parse(convertFromHexString("0xD8236129"))) // Invalid Regular Expression - - XCTAssertThrowsError(try CBORParser.parse(convertFromHexString("0x7F"))) // Indefinite Length String - No Break - XCTAssertThrowsError(try CBORParser.parse(convertFromHexString("0x7F60"))) // Indefinite Length String - No Break - XCTAssertThrowsError(try CBORParser.parse(convertFromHexString("0x7F61"))) // Indefinite Length String - Chunk of Length 1 - 0 Elements - XCTAssertThrowsError(try CBORParser.parse(convertFromHexString("0x5F"))) // Indefinite Length Data - No Break - XCTAssertThrowsError(try CBORParser.parse(convertFromHexString("0x5F40"))) // Indefinite Length Data - No Break - XCTAssertThrowsError(try CBORParser.parse(convertFromHexString("0x5F41"))) // Indefinite Length Data - Chunk of Length 1 - 0 Elements - XCTAssertThrowsError(try CBORParser.parse(convertFromHexString("0x5F60FF"))) // Indefinite Length Data - String Chunks - XCTAssertThrowsError(try CBORParser.parse(convertFromHexString("0x9F"))) // Indefinite Length Array - No Break - XCTAssertThrowsError(try CBORParser.parse(convertFromHexString("0x9F60"))) // Indefinite Length Array - No Break - XCTAssertThrowsError(try CBORParser.parse(convertFromHexString("0xBF"))) // Indefinite Length Map - No Break - XCTAssertThrowsError(try CBORParser.parse(convertFromHexString("0xBF61616161"))) // Indefinite Length Map - No Break - - XCTAssertThrowsError(try CBORParser.parse(convertFromHexString("0xFF"))) // "Break" Code - No Container - XCTAssertThrowsError(try CBORParser.parse(convertFromHexString("0x820000FF"))) // "Break" Code - Outside of Container - XCTAssertThrowsError(try CBORParser.parse(convertFromHexString("0x82FF"))) // "Break" Code - Inside Definite Length Array - XCTAssertThrowsError(try CBORParser.parse(convertFromHexString("0xA2FF"))) // "Break" Code - Inside Definite Length Map - - XCTAssertThrowsError(try CBORParser.parse(convertFromHexString("0x62"))) // String of Length 2 - 0 Elements - XCTAssertThrowsError(try CBORParser.parse(convertFromHexString("0x6261"))) // String of Length 2 - 1 Element - XCTAssertThrowsError(try CBORParser.parse(convertFromHexString("0x42"))) // Data of Length 2 - 0 Elements - XCTAssertThrowsError(try CBORParser.parse(convertFromHexString("0x4200"))) // Data of Length 2 - 1 Element - XCTAssertThrowsError(try CBORParser.parse(convertFromHexString("0x82"))) // Array of Length 2 - 0 Elements - XCTAssertThrowsError(try CBORParser.parse(convertFromHexString("0x8200"))) // Array of Length 2 - 1 Element - XCTAssertThrowsError(try CBORParser.parse(convertFromHexString("0xA2"))) // Map of Length 2 - 0 Elements - XCTAssertThrowsError(try CBORParser.parse(convertFromHexString("0xA261616161"))) // Map of Length 2 - 1 Element - XCTAssertThrowsError(try CBORParser.parse(convertFromHexString("0xA16161"))) // Map with Key but no Value - - XCTAssertThrowsError(try CBORParser.parse(convertFromHexString("0x64FEFEFFFF"))) // Invalid UTF-8 String - XCTAssertThrowsError(try CBORParser.parse(convertFromHexString("0xD8207F61FE61FE61FF61FFFF"))) // Invalid UTF-8 URL - XCTAssertThrowsError(try CBORParser.parse(convertFromHexString("0xD820682074207420702073203A202F202F206520782061206D2070206C2065202E2063206F206D"))) // Invalid URL ("h t t p s : / / e x a m p l e . c o m") - XCTAssertThrowsError(try CBORParser.parse(convertFromHexString("0xD8204100"))) // Invalid URL (Empty Byte Data) - XCTAssertThrowsError(try CBORParser.parse(convertFromHexString("0xC06443424F52"))) // Invalid RFC3339 Date String ("CBOR") - XCTAssertThrowsError(try CBORParser.parse(convertFromHexString("0xC16443424F52"))) // Invalid Epoch Date ("CBOR") - - XCTAssertThrowsError(try CBORParser.parse(convertFromHexString("0xC4420001"))) // Decimal Fraction Tag - Byte Data - XCTAssertThrowsError(try CBORParser.parse(convertFromHexString("0xC4811818"))) // Decimal Fraction Tag - Array of Length 1 - XCTAssertThrowsError(try CBORParser.parse(convertFromHexString("0xC49F1818"))) // Decimal Fraction Tag - Array of Length 1 - XCTAssertThrowsError(try CBORParser.parse(convertFromHexString("0xC4821818"))) // Decimal Fraction Tag - Array of Length 2 - 1 Element - XCTAssertThrowsError(try CBORParser.parse(convertFromHexString("0xC4823B00"))) // Decimal Fraction Tag - Array of Length 2 - 1 Element - Empty Data - XCTAssertThrowsError(try CBORParser.parse(convertFromHexString("0xC482003B"))) // Decimal Fraction Tag - Array of Length 2 - 2 Elements - 2nd Element Empty Data - XCTAssertThrowsError(try CBORParser.parse(convertFromHexString("0xC48261616162"))) // Decimal Fraction Tag - ["a", "b"] - XCTAssertThrowsError(try CBORParser.parse(convertFromHexString("0xC482016162"))) // Decimal Fraction Tag - [1, "b"] - XCTAssertThrowsError(try CBORParser.parse(convertFromHexString("0xC4821818C6"))) // Decimal Fraction Tag - [24, Invalid Tag] - XCTAssertThrowsError(try CBORParser.parse(convertFromHexString("0xC4821818C0"))) // Decimal Fraction Tag - [24, Date Tag] - XCTAssertThrowsError(try CBORParser.parse(convertFromHexString("0xC4821818C2"))) // Decimal Fraction Tag - [24, Empty Bignum Data] - - do { - var value: Any? - - XCTAssertNoThrow(value = try CBORParser.parse(Data())) - XCTAssertNil(value) - - XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString("0xD9D9F7"))) - XCTAssertNil(value) + for prefixLength in prefixLengths { + func prefix() -> String { return randomHexString(ofLength: prefixLength) } + + for suffixLength in suffixLengths { + func suffix() -> String { return randomHexString(ofLength: suffixLength) } + + XCTAssertThrowsError(try CBORParser.parse(convertFromHexString("0x\(prefix())0101\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength))) // Multiple values outside of a container + + XCTAssertThrowsError(try CBORParser.parse(convertFromHexString("0x\(prefix())18\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength))) // Unsigned - Missing extra byte + XCTAssertThrowsError(try CBORParser.parse(convertFromHexString("0x\(prefix())19\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength))) // Unsigned - Missing two extra bytes + XCTAssertThrowsError(try CBORParser.parse(convertFromHexString("0x\(prefix())1A\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength))) // Unsigned - Missing four extra bytes + XCTAssertThrowsError(try CBORParser.parse(convertFromHexString("0x\(prefix())1B\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength))) // Unsigned - Missing eight extra bytes + + XCTAssertThrowsError(try CBORParser.parse(convertFromHexString("0x\(prefix())38\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength))) // Signed - Missing extra byte + XCTAssertThrowsError(try CBORParser.parse(convertFromHexString("0x\(prefix())39\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength))) // Signed - Missing two extra bytes + XCTAssertThrowsError(try CBORParser.parse(convertFromHexString("0x\(prefix())3A\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength))) // Signed - Missing four extra bytes + XCTAssertThrowsError(try CBORParser.parse(convertFromHexString("0x\(prefix())3B\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength))) // Signed - Missing eight extra bytes + + XCTAssertThrowsError(try CBORParser.parse(convertFromHexString("0x\(prefix())F8\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength))) // Simple - Missing extra byte + XCTAssertThrowsError(try CBORParser.parse(convertFromHexString("0x\(prefix())FE\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength))) // Major Type 7, Unassigned code + + XCTAssertThrowsError(try CBORParser.parse(convertFromHexString("0x\(prefix())F9\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength))) // Half - Missing two extra bytes + XCTAssertThrowsError(try CBORParser.parse(convertFromHexString("0x\(prefix())FA\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength))) // Float - Missing four extra bytes + XCTAssertThrowsError(try CBORParser.parse(convertFromHexString("0x\(prefix())FB\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength))) // Double - Missing eight extra bytes + + XCTAssertThrowsError(try CBORParser.parse(convertFromHexString("0x\(prefix())C6\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength))) // Invalid tag + XCTAssertThrowsError(try CBORParser.parse(convertFromHexString("0x\(prefix())DF\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength))) // Invalid tag + XCTAssertThrowsError(try CBORParser.parse(convertFromHexString("0x\(prefix())C0\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength))) // Empty Tag - Standard Date + XCTAssertThrowsError(try CBORParser.parse(convertFromHexString("0x\(prefix())C1\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength))) // Empty Tag - Epoch Date + XCTAssertThrowsError(try CBORParser.parse(convertFromHexString("0x\(prefix())C2\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength))) // Empty Tag - Positive Bignum + XCTAssertThrowsError(try CBORParser.parse(convertFromHexString("0x\(prefix())C3\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength))) // Empty Tag - Negative Bignum + XCTAssertThrowsError(try CBORParser.parse(convertFromHexString("0x\(prefix())C4\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength))) // Empty Tag - Decimal Fraction + XCTAssertThrowsError(try CBORParser.parse(convertFromHexString("0x\(prefix())C5\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength))) // Empty Tag - Bigfloat + XCTAssertThrowsError(try CBORParser.parse(convertFromHexString("0x\(prefix())D5\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength))) // Empty Tag - Base64URL Conversion + XCTAssertThrowsError(try CBORParser.parse(convertFromHexString("0x\(prefix())D6\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength))) // Empty Tag - Base64 Conversion + XCTAssertThrowsError(try CBORParser.parse(convertFromHexString("0x\(prefix())D7\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength))) // Empty Tag - Base16 Conversion + XCTAssertThrowsError(try CBORParser.parse(convertFromHexString("0x\(prefix())D818\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength))) // Empty Tag - Encoded CBOR Data + XCTAssertThrowsError(try CBORParser.parse(convertFromHexString("0x\(prefix())D820\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength))) // Empty Tag - URI + XCTAssertThrowsError(try CBORParser.parse(convertFromHexString("0x\(prefix())D821\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength))) // Empty Tag - Base64URL + XCTAssertThrowsError(try CBORParser.parse(convertFromHexString("0x\(prefix())D822\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength))) // Empty Tag - Base64 + XCTAssertThrowsError(try CBORParser.parse(convertFromHexString("0x\(prefix())D823\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength))) // Empty Tag - Regular Expression + XCTAssertThrowsError(try CBORParser.parse(convertFromHexString("0x\(prefix())D824\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength))) // Empty Tag - MIME Message + + XCTAssertThrowsError(try CBORParser.parse(convertFromHexString("0x\(prefix())D8216121\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength))) // Invalid Base64URL Data + XCTAssertThrowsError(try CBORParser.parse(convertFromHexString("0x\(prefix())D8226121\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength))) // Invalid Base64 Data + XCTAssertThrowsError(try CBORParser.parse(convertFromHexString("0x\(prefix())D8236129\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength))) // Invalid Regular Expression + + XCTAssertThrowsError(try CBORParser.parse(convertFromHexString("0x\(prefix())7F\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength))) // Indefinite Length String - No Break + XCTAssertThrowsError(try CBORParser.parse(convertFromHexString("0x\(prefix())7F60\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength))) // Indefinite Length String - No Break + XCTAssertThrowsError(try CBORParser.parse(convertFromHexString("0x\(prefix())7F61\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength))) // Indefinite Length String - Chunk of Length 1 - 0 Elements + XCTAssertThrowsError(try CBORParser.parse(convertFromHexString("0x\(prefix())5F\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength))) // Indefinite Length Data - No Break + XCTAssertThrowsError(try CBORParser.parse(convertFromHexString("0x\(prefix())5F40\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength))) // Indefinite Length Data - No Break + XCTAssertThrowsError(try CBORParser.parse(convertFromHexString("0x\(prefix())5F41\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength))) // Indefinite Length Data - Chunk of Length 1 - 0 Elements + XCTAssertThrowsError(try CBORParser.parse(convertFromHexString("0x\(prefix())5F60FF\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength))) // Indefinite Length Data - String Chunks + XCTAssertThrowsError(try CBORParser.parse(convertFromHexString("0x\(prefix())9F\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength))) // Indefinite Length Array - No Break + XCTAssertThrowsError(try CBORParser.parse(convertFromHexString("0x\(prefix())9F60\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength))) // Indefinite Length Array - No Break + XCTAssertThrowsError(try CBORParser.parse(convertFromHexString("0x\(prefix())BF\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength))) // Indefinite Length Map - No Break + XCTAssertThrowsError(try CBORParser.parse(convertFromHexString("0x\(prefix())BF61616161\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength))) // Indefinite Length Map - No Break + + XCTAssertThrowsError(try CBORParser.parse(convertFromHexString("0x\(prefix())FF\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength))) // "Break" Code - No Container + XCTAssertThrowsError(try CBORParser.parse(convertFromHexString("0x\(prefix())820000FF\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength))) // "Break" Code - Outside of Container + XCTAssertThrowsError(try CBORParser.parse(convertFromHexString("0x\(prefix())82FF\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength))) // "Break" Code - Inside Definite Length Array + XCTAssertThrowsError(try CBORParser.parse(convertFromHexString("0x\(prefix())A2FF\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength))) // "Break" Code - Inside Definite Length Map + + XCTAssertThrowsError(try CBORParser.parse(convertFromHexString("0x\(prefix())62\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength))) // String of Length 2 - 0 Elements + XCTAssertThrowsError(try CBORParser.parse(convertFromHexString("0x\(prefix())6261\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength))) // String of Length 2 - 1 Element + XCTAssertThrowsError(try CBORParser.parse(convertFromHexString("0x\(prefix())42\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength))) // Data of Length 2 - 0 Elements + XCTAssertThrowsError(try CBORParser.parse(convertFromHexString("0x\(prefix())4200\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength))) // Data of Length 2 - 1 Element + XCTAssertThrowsError(try CBORParser.parse(convertFromHexString("0x\(prefix())82\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength))) // Array of Length 2 - 0 Elements + XCTAssertThrowsError(try CBORParser.parse(convertFromHexString("0x\(prefix())8200\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength))) // Array of Length 2 - 1 Element + XCTAssertThrowsError(try CBORParser.parse(convertFromHexString("0x\(prefix())A2\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength))) // Map of Length 2 - 0 Elements + XCTAssertThrowsError(try CBORParser.parse(convertFromHexString("0x\(prefix())A261616161\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength))) // Map of Length 2 - 1 Element + XCTAssertThrowsError(try CBORParser.parse(convertFromHexString("0x\(prefix())A16161\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength))) // Map with Key but no Value + + XCTAssertThrowsError(try CBORParser.parse(convertFromHexString("0x\(prefix())64FEFEFFFF\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength))) // Invalid UTF-8 String + XCTAssertThrowsError(try CBORParser.parse(convertFromHexString("0x\(prefix())D8207F61FE61FE61FF61FFFF\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength))) // Invalid UTF-8 URL + XCTAssertThrowsError(try CBORParser.parse(convertFromHexString("0x\(prefix())D820682074207420702073203A202F202F206520782061206D2070206C2065202E2063206F206D\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength))) // Invalid URL ("h t t p s : / / e x a m p l e . c o m") + XCTAssertThrowsError(try CBORParser.parse(convertFromHexString("0x\(prefix())D8204100\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength))) // Invalid URL (Empty Byte Data) + XCTAssertThrowsError(try CBORParser.parse(convertFromHexString("0x\(prefix())C06443424F52\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength))) // Invalid RFC3339 Date String ("CBOR") + XCTAssertThrowsError(try CBORParser.parse(convertFromHexString("0x\(prefix())C16443424F52\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength))) // Invalid Epoch Date ("CBOR") + + XCTAssertThrowsError(try CBORParser.parse(convertFromHexString("0x\(prefix())C4420001\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength))) // Decimal Fraction Tag - Byte Data + XCTAssertThrowsError(try CBORParser.parse(convertFromHexString("0x\(prefix())C4811818\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength))) // Decimal Fraction Tag - Array of Length 1 + XCTAssertThrowsError(try CBORParser.parse(convertFromHexString("0x\(prefix())C49F1818\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength))) // Decimal Fraction Tag - Array of Length 1 + XCTAssertThrowsError(try CBORParser.parse(convertFromHexString("0x\(prefix())C4821818\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength))) // Decimal Fraction Tag - Array of Length 2 - 1 Element + XCTAssertThrowsError(try CBORParser.parse(convertFromHexString("0x\(prefix())C4823B00\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength))) // Decimal Fraction Tag - Array of Length 2 - 1 Element - Empty Data + XCTAssertThrowsError(try CBORParser.parse(convertFromHexString("0x\(prefix())C482003B\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength))) // Decimal Fraction Tag - Array of Length 2 - 2 Elements - 2nd Element Empty Data + XCTAssertThrowsError(try CBORParser.parse(convertFromHexString("0x\(prefix())C48261616162\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength))) // Decimal Fraction Tag - ["a", "b"] + XCTAssertThrowsError(try CBORParser.parse(convertFromHexString("0x\(prefix())C482016162\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength))) // Decimal Fraction Tag - [1, "b"] + XCTAssertThrowsError(try CBORParser.parse(convertFromHexString("0x\(prefix())C4821818C6\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength))) // Decimal Fraction Tag - [24, Invalid Tag] + XCTAssertThrowsError(try CBORParser.parse(convertFromHexString("0x\(prefix())C4821818C0\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength))) // Decimal Fraction Tag - [24, Date Tag] + XCTAssertThrowsError(try CBORParser.parse(convertFromHexString("0x\(prefix())C4821818C2\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength))) // Decimal Fraction Tag - [24, Empty Bignum Data] + + do { + var value: Any? + + XCTAssertNoThrow(value = try CBORParser.parse(Data())) + XCTAssertNil(value) + + XCTAssertNoThrow(value = try CBORParser.parse(convertFromHexString("0x\(prefix())D9D9F7\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength))) + XCTAssertNil(value) + } + } } } func testDecodeMapCodingKeys() { - let encoder = CBOREncoder() - - var nonThrowingCodingKeys = [ - try! encoder.encode(Int8.min), - try! encoder.encode(Int8.max), - try! encoder.encode(Int16.min), - try! encoder.encode(Int16.max), - try! encoder.encode(Int32.min), - try! encoder.encode(Int32.max), - try! encoder.encode(Int.min), - try! encoder.encode(Int.max), - try! encoder.encode(UInt8.max), - try! encoder.encode(UInt16.max), - try! encoder.encode(CBOR.Bignum(isPositive: true, content: convertFromHexString("0xFFFF"))), - try! encoder.encode(CBOR.Bignum(isPositive: false, content: convertFromHexString("0xFFFF"))) - ] - var throwingCodingKeys = [ - try! encoder.encode(UInt64.max), - try! encoder.encode(CBOR.NegativeUInt64(rawValue: 0x8000000000000001)), - try! encoder.encode(CBOR.Bignum(isPositive: true, content: convertFromHexString("0xFFFFFFFFFFFFFFFF"))), - try! encoder.encode(CBOR.Bignum(isPositive: true, content: convertFromHexString("0xFFFFFFFFFFFFFFFFFF"))), - try! encoder.encode(CBOR.Bignum(isPositive: false, content: convertFromHexString("0xFFFFFFFFFFFFFFFFFF"))), - try! encoder.encode(CBOR.Bignum(isPositive: false, content: convertFromHexString("0x8000000000000001"))) - ] - - // Throws on 32-bit architectures but succeeds on 64-bit architectures. - let archEdgeCases = [ - try! encoder.encode(Int64.min), - try! encoder.encode(Int64.max), - try! encoder.encode(UInt32.max), - try! encoder.encode(CBOR.Bignum(isPositive: true, content: convertFromHexString("0x0100010001000100"))), - try! encoder.encode(CBOR.Bignum(isPositive: false, content: convertFromHexString("0x0100010001000100"))), - try! encoder.encode(CBOR.Bignum(isPositive: false, content: convertFromHexString("0x8000000000000000"))) - ] - - #if arch(arm64) || arch(x86_64) - nonThrowingCodingKeys.append(contentsOf: archEdgeCases) - #elseif arch(i386) || arch(arm) - throwingCodingKeys.append(contentsOf: archEdgeCases) - #endif // #if arch(arm64) || arch(x86_64) - - // swiftlint:disable trailing_closure - for key in nonThrowingCodingKeys { - XCTAssertNoThrow(try CBORParser.parse(convertFromHexString("0xA1\(key.map({ String(format: "%02X", $0) }).joined())6161"))) - } + for prefixLength in prefixLengths { + func prefix() -> String { return randomHexString(ofLength: prefixLength) } + + for suffixLength in suffixLengths { + func suffix() -> String { return randomHexString(ofLength: suffixLength) } + + let encoder = CBOREncoder() + + var nonThrowingCodingKeys = [ + try! encoder.encode(Int8.min), + try! encoder.encode(Int8.max), + try! encoder.encode(Int16.min), + try! encoder.encode(Int16.max), + try! encoder.encode(Int32.min), + try! encoder.encode(Int32.max), + try! encoder.encode(Int.min), + try! encoder.encode(Int.max), + try! encoder.encode(UInt8.max), + try! encoder.encode(UInt16.max), + try! encoder.encode(CBOR.Bignum(isPositive: true, content: convertFromHexString("0x\(prefix())FFFF\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength))), + try! encoder.encode(CBOR.Bignum(isPositive: false, content: convertFromHexString("0x\(prefix())FFFF\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength))) + ] + var throwingCodingKeys = [ + try! encoder.encode(UInt64.max), + try! encoder.encode(CBOR.NegativeUInt64(rawValue: 0x8000000000000001)), + try! encoder.encode(CBOR.Bignum(isPositive: true, content: convertFromHexString("0x\(prefix())FFFFFFFFFFFFFFFF\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength))), + try! encoder.encode(CBOR.Bignum(isPositive: true, content: convertFromHexString("0x\(prefix())FFFFFFFFFFFFFFFFFF\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength))), + try! encoder.encode(CBOR.Bignum(isPositive: false, content: convertFromHexString("0x\(prefix())FFFFFFFFFFFFFFFFFF\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength))), + try! encoder.encode(CBOR.Bignum(isPositive: false, content: convertFromHexString("0x\(prefix())8000000000000001\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength))) + ] + + // Throws on 32-bit architectures but succeeds on 64-bit architectures. + let archEdgeCases = [ + try! encoder.encode(Int64.min), + try! encoder.encode(Int64.max), + try! encoder.encode(UInt32.max), + try! encoder.encode(CBOR.Bignum(isPositive: true, content: convertFromHexString("0x\(prefix())0100010001000100\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength))), + try! encoder.encode(CBOR.Bignum(isPositive: false, content: convertFromHexString("0x\(prefix())0100010001000100\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength))), + try! encoder.encode(CBOR.Bignum(isPositive: false, content: convertFromHexString("0x\(prefix())8000000000000000\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength))) + ] + + #if arch(arm64) || arch(x86_64) + nonThrowingCodingKeys.append(contentsOf: archEdgeCases) + #elseif arch(i386) || arch(arm) + throwingCodingKeys.append(contentsOf: archEdgeCases) + #endif // #if arch(arm64) || arch(x86_64) + + for key in nonThrowingCodingKeys { + XCTAssertNoThrow(try CBORParser.parse(convertFromHexString("0x\(prefix())A1\(key.map { String(format: "%02X", $0) }.joined())6161\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength))) + } - for key in throwingCodingKeys { - XCTAssertThrowsError(try CBORParser.parse(convertFromHexString("0xA1\(key.map({ String(format: "%02X", $0) }).joined())6161"))) + for key in throwingCodingKeys { + XCTAssertThrowsError(try CBORParser.parse(convertFromHexString("0x\(prefix())A1\(key.map { String(format: "%02X", $0) }.joined())6161\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength))) + } + } } - // swiftlint:enable trailing_closure } func testTypeParsing() { @@ -910,103 +1029,111 @@ class CBORParserTests: XCTestCase { } func testDirectDecoding() { - var value: Any! - - // Success cases - XCTAssertNoThrow(value = try CBORParser.testDecode(String.self, from: convertFromHexString("0x6443424F52")).value) - XCTAssertTrue(value is CBORDecodedString) - XCTAssertNoThrow(value = try (value as! CBORDecodedString).decodedStringValue()) - XCTAssertEqual(value as! String?, "CBOR") - - XCTAssertNoThrow(value = try CBORParser.testDecode(String.self, from: convertFromHexString("0x7F624342624F52FF")).value) - XCTAssertTrue(value is CBORDecodedString) - XCTAssertNoThrow(value = try (value as! CBORDecodedString).decodedStringValue()) - XCTAssertEqual(value as! String?, "CBOR") - - XCTAssertNoThrow(value = try CBORParser.testDecode(Data.self, from: convertFromHexString("0x4443424F52")).value) - XCTAssertTrue(value is CBORDecodedData) - XCTAssertEqual((value as! CBORDecodedData).decodedDataValue(), Data("CBOR".utf8)) - - XCTAssertNoThrow(value = try CBORParser.testDecode(Data.self, from: convertFromHexString("0x5F424342424F52FF")).value) - XCTAssertTrue(value is CBORDecodedData) - XCTAssertEqual((value as! CBORDecodedData).decodedDataValue(), Data("CBOR".utf8)) - - XCTAssertNoThrow(value = try CBORParser.testDecode(URL.self, from: convertFromHexString("0x76687474703A2F2F7777772E6578616D706C652E636F6D")).value) - XCTAssertTrue(value is URL) - XCTAssertEqual(value as! URL, URL(string: "http://www.example.com")!) - - XCTAssertNoThrow(value = try CBORParser.testDecode(Date.self, tag: .standardDateTime, from: convertFromHexString("0x74323031332D30332D32315432303A30343A30305A")).value) - XCTAssertTrue(value is Date) - XCTAssertEqual(value as! Date, rfc3339Date()) - - XCTAssertNoThrow(value = try CBORParser.testDecode(CBOR.NegativeUInt64.self, from: convertFromHexString("0x3B7FFFFFFFFFFFFFFF")).value) - XCTAssertTrue(value is CBOR.NegativeUInt64) - XCTAssertEqual((value as! CBOR.NegativeUInt64).rawValue, 0x8000000000000000) - - XCTAssertNoThrow(value = try CBORParser.testDecode(CBOR.SimpleValue.self, from: convertFromHexString("0xF8FF")).value) - XCTAssertTrue(value is CBOR.SimpleValue) - XCTAssertEqual((value as! CBOR.SimpleValue).rawValue, 255) - - XCTAssertNoThrow(value = try CBORParser.testDecode(CBOR.Bignum.self, tag: .positiveBignum, from: convertFromHexString("0x42FFFF")).value) - XCTAssertTrue(value is CBOR.Bignum) - XCTAssertTrue((value as! CBOR.Bignum).isPositive) - XCTAssertEqual((value as! CBOR.Bignum).content, convertFromHexString("0xFFFF")) - - XCTAssertNoThrow(value = try CBORParser.testDecode(CBOR.Bignum.self, tag: .negativeBignum, from: convertFromHexString("0x42FFFF")).value) - XCTAssertTrue(value is CBOR.Bignum) - XCTAssertFalse((value as! CBOR.Bignum).isPositive) - XCTAssertEqual((value as! CBOR.Bignum).content, convertFromHexString("0xFFFF")) - - XCTAssertNoThrow(value = try CBORParser.testDecode(Float.self, from: convertFromHexString("0xF97C00")).value) - XCTAssertTrue(value is Float) - XCTAssertEqual(value as! Float, .infinity) - - XCTAssertNoThrow(value = try CBORParser.testDecode(UInt64.self, from: convertFromHexString("0x1903E8")).value) - XCTAssertTrue(value is UInt64) - XCTAssertEqual(value as! UInt64, 1000) - - XCTAssertNoThrow(value = try CBORParser.testDecode(Int64.self, from: convertFromHexString("0x3903E7")).value) - XCTAssertTrue(value is Int64) - XCTAssertEqual(value as! Int64, -1000) - - XCTAssertNoThrow(value = try CBORParser.testDecode(CBOR.DecimalFraction.self, from: convertFromHexString("0x82202E")).value) // Decimal Fraction - XCTAssertTrue(value is [Any]) - XCTAssertEqual((value as! [Any]).count, 3) - - XCTAssertTrue((value as! [Any])[0] is CBOR.Tag) - XCTAssertEqual((value as! [Any])[0] as! CBOR.Tag, .decimalFraction) - XCTAssertTrue((value as! [Any])[1] is Int64) - XCTAssertEqual((value as! [Any])[1] as! Int64, -1) - XCTAssertTrue((value as! [Any])[2] is Int64) - XCTAssertEqual((value as! [Any])[2] as! Int64, -15) - - XCTAssertNoThrow(value = try CBORParser.testDecode(CBOR.Bigfloat.self, from: convertFromHexString("0x82010F")).value) // Bigfloat - XCTAssertTrue(value is [Any]) - XCTAssertEqual((value as! [Any]).count, 3) - - XCTAssertTrue((value as! [Any])[0] is CBOR.Tag) - XCTAssertEqual((value as! [Any])[0] as! CBOR.Tag, .bigfloat) - XCTAssertTrue((value as! [Any])[1] is UInt64) - XCTAssertEqual((value as! [Any])[1] as! UInt64, 1) - XCTAssertTrue((value as! [Any])[2] is UInt64) - XCTAssertEqual((value as! [Any])[2] as! UInt64, 15) - - // Failure cases - XCTAssertThrowsError(try CBORParser.testDecode(CBOR.NegativeUInt64.self, from: Data())) - XCTAssertThrowsError(try CBORParser.testDecode(CBOR.NegativeUInt64.self, from: Data([CBOR.MajorType.unsigned.rawValue]))) - - XCTAssertThrowsError(try CBORParser.testDecode(CBOR.SimpleValue.self, from: Data())) - XCTAssertThrowsError(try CBORParser.testDecode(CBOR.SimpleValue.self, from: Data([CBOR.MajorType.unsigned.rawValue]))) - XCTAssertThrowsError(try CBORParser.testDecode(CBOR.SimpleValue.self, from: Data([CBOR.MajorType.additonal.rawValue | 25]))) - - XCTAssertThrowsError(try CBORParser.testDecode(Float.self, from: Data())) - XCTAssertThrowsError(try CBORParser.testDecode(Double.self, from: Data())) - - XCTAssertThrowsError(try CBORParser.testDecode(UInt64.self, from: Data())) - XCTAssertThrowsError(try CBORParser.testDecode(Int64.self, from: Data())) - - XCTAssertThrowsError(try CBORParser.testDecode(UInt8.self, from: convertFromHexString("0x1903E8"))) - XCTAssertThrowsError(try CBORParser.testDecode(Int8.self, from: convertFromHexString("0x3903E7"))) + for prefixLength in prefixLengths { + func prefix() -> String { return randomHexString(ofLength: prefixLength) } + + for suffixLength in suffixLengths { + func suffix() -> String { return randomHexString(ofLength: suffixLength) } + + var value: Any! + + // Success cases + XCTAssertNoThrow(value = try CBORParser.testDecode(String.self, from: convertFromHexString("0x\(prefix())6443424F52\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength)).value) + XCTAssertTrue(value is CBORDecodedString) + XCTAssertNoThrow(value = try (value as! CBORDecodedString).decodedStringValue()) + XCTAssertEqual(value as! String?, "CBOR") + + XCTAssertNoThrow(value = try CBORParser.testDecode(String.self, from: convertFromHexString("0x\(prefix())7F624342624F52FF\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength)).value) + XCTAssertTrue(value is CBORDecodedString) + XCTAssertNoThrow(value = try (value as! CBORDecodedString).decodedStringValue()) + XCTAssertEqual(value as! String?, "CBOR") + + XCTAssertNoThrow(value = try CBORParser.testDecode(Data.self, from: convertFromHexString("0x\(prefix())4443424F52\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength)).value) + XCTAssertTrue(value is CBORDecodedData) + XCTAssertEqual((value as! CBORDecodedData).decodedDataValue(), Data("CBOR".utf8)) + + XCTAssertNoThrow(value = try CBORParser.testDecode(Data.self, from: convertFromHexString("0x\(prefix())5F424342424F52FF\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength)).value) + XCTAssertTrue(value is CBORDecodedData) + XCTAssertEqual((value as! CBORDecodedData).decodedDataValue(), Data("CBOR".utf8)) + + XCTAssertNoThrow(value = try CBORParser.testDecode(URL.self, from: convertFromHexString("0x\(prefix())76687474703A2F2F7777772E6578616D706C652E636F6D\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength)).value) + XCTAssertTrue(value is URL) + XCTAssertEqual(value as! URL, URL(string: "http://www.example.com")!) + + XCTAssertNoThrow(value = try CBORParser.testDecode(Date.self, tag: .standardDateTime, from: convertFromHexString("0x\(prefix())74323031332D30332D32315432303A30343A30305A\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength)).value) + XCTAssertTrue(value is Date) + XCTAssertEqual(value as! Date, rfc3339Date()) + + XCTAssertNoThrow(value = try CBORParser.testDecode(CBOR.NegativeUInt64.self, from: convertFromHexString("0x\(prefix())3B7FFFFFFFFFFFFFFF\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength)).value) + XCTAssertTrue(value is CBOR.NegativeUInt64) + XCTAssertEqual((value as! CBOR.NegativeUInt64).rawValue, 0x8000000000000000) + + XCTAssertNoThrow(value = try CBORParser.testDecode(CBOR.SimpleValue.self, from: convertFromHexString("0x\(prefix())F8FF\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength)).value) + XCTAssertTrue(value is CBOR.SimpleValue) + XCTAssertEqual((value as! CBOR.SimpleValue).rawValue, 255) + + XCTAssertNoThrow(value = try CBORParser.testDecode(CBOR.Bignum.self, tag: .positiveBignum, from: convertFromHexString("0x\(prefix())42FFFF\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength)).value) + XCTAssertTrue(value is CBOR.Bignum) + XCTAssertTrue((value as! CBOR.Bignum).isPositive) + XCTAssertEqual((value as! CBOR.Bignum).content, convertFromHexString("0xFFFF")) + + XCTAssertNoThrow(value = try CBORParser.testDecode(CBOR.Bignum.self, tag: .negativeBignum, from: convertFromHexString("0x\(prefix())42FFFF\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength)).value) + XCTAssertTrue(value is CBOR.Bignum) + XCTAssertFalse((value as! CBOR.Bignum).isPositive) + XCTAssertEqual((value as! CBOR.Bignum).content, convertFromHexString("0xFFFF")) + + XCTAssertNoThrow(value = try CBORParser.testDecode(Float.self, from: convertFromHexString("0x\(prefix())F97C00\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength)).value) + XCTAssertTrue(value is Float) + XCTAssertEqual(value as! Float, .infinity) + + XCTAssertNoThrow(value = try CBORParser.testDecode(UInt64.self, from: convertFromHexString("0x\(prefix())1903E8\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength)).value) + XCTAssertTrue(value is UInt64) + XCTAssertEqual(value as! UInt64, 1000) + + XCTAssertNoThrow(value = try CBORParser.testDecode(Int64.self, from: convertFromHexString("0x\(prefix())3903E7\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength)).value) + XCTAssertTrue(value is Int64) + XCTAssertEqual(value as! Int64, -1000) + + XCTAssertNoThrow(value = try CBORParser.testDecode(CBOR.DecimalFraction.self, from: convertFromHexString("0x\(prefix())82202E\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength)).value) // Decimal Fraction + XCTAssertTrue(value is [Any]) + XCTAssertEqual((value as! [Any]).count, 3) + + XCTAssertTrue((value as! [Any])[0] is CBOR.Tag) + XCTAssertEqual((value as! [Any])[0] as! CBOR.Tag, .decimalFraction) + XCTAssertTrue((value as! [Any])[1] is Int64) + XCTAssertEqual((value as! [Any])[1] as! Int64, -1) + XCTAssertTrue((value as! [Any])[2] is Int64) + XCTAssertEqual((value as! [Any])[2] as! Int64, -15) + + XCTAssertNoThrow(value = try CBORParser.testDecode(CBOR.Bigfloat.self, from: convertFromHexString("0x\(prefix())82010F\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength)).value) // Bigfloat + XCTAssertTrue(value is [Any]) + XCTAssertEqual((value as! [Any]).count, 3) + + XCTAssertTrue((value as! [Any])[0] is CBOR.Tag) + XCTAssertEqual((value as! [Any])[0] as! CBOR.Tag, .bigfloat) + XCTAssertTrue((value as! [Any])[1] is UInt64) + XCTAssertEqual((value as! [Any])[1] as! UInt64, 1) + XCTAssertTrue((value as! [Any])[2] is UInt64) + XCTAssertEqual((value as! [Any])[2] as! UInt64, 15) + + // Failure cases + XCTAssertThrowsError(try CBORParser.testDecode(CBOR.NegativeUInt64.self, from: Data())) + XCTAssertThrowsError(try CBORParser.testDecode(CBOR.NegativeUInt64.self, from: Data([CBOR.MajorType.unsigned.rawValue]))) + + XCTAssertThrowsError(try CBORParser.testDecode(CBOR.SimpleValue.self, from: Data())) + XCTAssertThrowsError(try CBORParser.testDecode(CBOR.SimpleValue.self, from: Data([CBOR.MajorType.unsigned.rawValue]))) + XCTAssertThrowsError(try CBORParser.testDecode(CBOR.SimpleValue.self, from: Data([CBOR.MajorType.additonal.rawValue | 25]))) + + XCTAssertThrowsError(try CBORParser.testDecode(Float.self, from: Data())) + XCTAssertThrowsError(try CBORParser.testDecode(Double.self, from: Data())) + + XCTAssertThrowsError(try CBORParser.testDecode(UInt64.self, from: Data())) + XCTAssertThrowsError(try CBORParser.testDecode(Int64.self, from: Data())) + + XCTAssertThrowsError(try CBORParser.testDecode(UInt8.self, from: convertFromHexString("0x\(prefix())1903E8\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength))) + XCTAssertThrowsError(try CBORParser.testDecode(Int8.self, from: convertFromHexString("0x\(prefix())3903E7\(suffix())", prefixLength: prefixLength, suffixLength: suffixLength))) + } + } } func testCreateCodingKeys() { @@ -1075,9 +1202,19 @@ class CBORParserTests: XCTestCase { XCTAssertThrowsError(try CBORParser.testCreateCodingKey(from: UInt64.max)) } + func testConvertFromHexStringWithPrefixesAndSuffixes() { + let hex = randomHexString(ofLength: 16) + let prefix = randomHexString(ofLength: 2) + let suffix = randomHexString(ofLength: 2) + + XCTAssertEqual(convertFromHexString(hex), convertFromHexString(prefix + hex, prefixLength: prefix.count / 2)) + XCTAssertEqual(convertFromHexString(hex), convertFromHexString(hex + suffix, suffixLength: suffix.count / 2)) + XCTAssertEqual(convertFromHexString(hex), convertFromHexString(prefix + hex + suffix, prefixLength: prefix.count / 2, suffixLength: suffix.count / 2)) + } + // MARK: Private Methods - private func convertFromHexString(_ string: String) -> Data { + private func convertFromHexString(_ string: String, prefixLength: Int = 0, suffixLength: Int = 0) -> Data { var hex = string.starts(with: "0x") ? String(string.dropFirst(2)) : string if (hex.count % 2) == 1 { // odd number of hex characters @@ -1112,9 +1249,24 @@ class CBORParserTests: XCTestCase { map(hex[hex.index(hex.startIndex, offsetBy: i + 1)])) } + if prefixLength > 0 { + if suffixLength > 0 { + data = data[prefixLength ..< (data.count - suffixLength)] + } else { + data = data[prefixLength...] + } + } else if suffixLength > 0 { + data = data[..<(data.count - suffixLength)] + } + return data } + private func randomHexString(ofLength length: Int = 8) -> String { + guard length > 0 else { return "" } + return String((0 ..< (length * 2)).map { _ in "0123456789ABCDEF".shuffled()[0] }) + } + private func rfc3339Date() -> Date { // 2013-03-21T20:04:00Z var components = DateComponents()