A fast, safe, and efficient CBOR serialization library for Swift on any platform. swiftpackageindex.com/thecoolwinter/CBOR/1.1.1/documentation/cbor
atproto swift cbor

Finally...

+554 -4515
-68
Old/AnyCodingKey.swift
··· 1 - struct AnyCodingKey: CodingKey, Equatable { 2 - var stringValue: String { 3 - get { self._stringValue ?? "_do_not_use_this_string_value_use_the_int_value_instead_" } 4 - } 5 - 6 - var _stringValue: String? 7 - var intValue: Int? 8 - 9 - init(stringValue: String) { 10 - self._stringValue = stringValue 11 - self.intValue = nil 12 - } 13 - 14 - init(intValue: Int) { 15 - self.intValue = intValue 16 - self._stringValue = nil 17 - } 18 - 19 - init<Key: CodingKey>(_ base: Key, useStringKey: Bool = false) { 20 - if !useStringKey, let intValue = base.intValue { 21 - self.init(intValue: intValue) 22 - } else { 23 - self.init(stringValue: base.stringValue) 24 - } 25 - } 26 - 27 - func key<K: CodingKey>() -> K { 28 - if let intValue = self.intValue { 29 - return K(intValue: intValue)! 30 - } else if let stringValue = self._stringValue { 31 - return K(stringValue: stringValue)! 32 - } else { 33 - fatalError("AnyCodingKey created without a string or int value") 34 - } 35 - } 36 - } 37 - 38 - extension AnyCodingKey: Hashable { 39 - public func hash(into hasher: inout Hasher) { 40 - self.intValue?.hash(into: &hasher) ?? self._stringValue?.hash(into: &hasher) 41 - } 42 - } 43 - 44 - extension AnyCodingKey: Encodable { 45 - func encode(to encoder: Encoder) throws { 46 - var container = encoder.singleValueContainer() 47 - if let intValue = self.intValue { 48 - try container.encode(intValue) 49 - } else if let stringValue = self._stringValue { 50 - try container.encode(stringValue) 51 - } else { 52 - fatalError("AnyCodingKey created without a string or int value") 53 - } 54 - } 55 - } 56 - 57 - extension AnyCodingKey: Decodable { 58 - init(from decoder: Decoder) throws { 59 - let value = try decoder.singleValueContainer() 60 - if let intValue = try? value.decode(Int.self) { 61 - self._stringValue = nil 62 - self.intValue = intValue 63 - } else { 64 - self._stringValue = try! value.decode(String.self) 65 - self.intValue = nil 66 - } 67 - } 68 - }
-179
Old/CBOR.swift
··· 1 - #if canImport(Foundation) 2 - import Foundation 3 - #endif 4 - 5 - public indirect enum CBOR : Equatable, Hashable, 6 - ExpressibleByNilLiteral, ExpressibleByIntegerLiteral, ExpressibleByStringLiteral, 7 - ExpressibleByArrayLiteral, ExpressibleByDictionaryLiteral, ExpressibleByBooleanLiteral, 8 - ExpressibleByFloatLiteral { 9 - 10 - case unsignedInt(UInt64) 11 - case negativeInt(UInt64) 12 - case byteString([UInt8]) 13 - case utf8String(String) 14 - case array([CBOR]) 15 - case map([CBOR : CBOR]) 16 - case tagged(Tag, CBOR) 17 - case simple(UInt8) 18 - case boolean(Bool) 19 - case null 20 - case undefined 21 - case half(Float32) 22 - case float(Float32) 23 - case double(Float64) 24 - case `break` 25 - #if canImport(Foundation) 26 - case date(Date) 27 - #endif 28 - 29 - public func hash(into hasher: inout Hasher) { 30 - switch self { 31 - case let .unsignedInt(l): l.hash(into: &hasher) 32 - case let .negativeInt(l): l.hash(into: &hasher) 33 - case let .byteString(l): Util.djb2Hash(l.map { Int($0) }).hash(into: &hasher) 34 - case let .utf8String(l): l.hash(into: &hasher) 35 - case let .array(l): Util.djb2Hash(l.map { $0.hashValue }).hash(into: &hasher) 36 - case let .map(l): Util.djb2Hash(l.map { $0.hashValue &+ $1.hashValue }).hash(into: &hasher) 37 - case let .tagged(t, l): t.hash(into: &hasher) 38 - l.hash(into: &hasher) 39 - case let .simple(l): l.hash(into: &hasher) 40 - case let .boolean(l): l.hash(into: &hasher) 41 - case .null: (-1).hash(into: &hasher) 42 - case .undefined: (-2).hash(into: &hasher) 43 - case let .half(l): l.hash(into: &hasher) 44 - case let .float(l): l.hash(into: &hasher) 45 - case let .double(l): l.hash(into: &hasher) 46 - #if canImport(Foundation) 47 - case let .date(l): l.hash(into: &hasher) 48 - #endif 49 - case .break: Int.min.hash(into: &hasher) 50 - } 51 - } 52 - 53 - public subscript(position: CBOR) -> CBOR? { 54 - get { 55 - switch (self, position) { 56 - case (let .array(l), let .unsignedInt(i)): return l[Int(i)] 57 - case (let .map(l), let i): return l[i] 58 - default: return nil 59 - } 60 - } 61 - set(x) { 62 - switch (self, position) { 63 - case (var .array(l), let .unsignedInt(i)): 64 - l[Int(i)] = x! 65 - self = .array(l) 66 - case (var .map(l), let i): 67 - l[i] = x! 68 - self = .map(l) 69 - default: break 70 - } 71 - } 72 - } 73 - 74 - public init(nilLiteral: ()) { self = .null } 75 - public init(integerLiteral value: Int) { 76 - if value < 0 { 77 - self = .negativeInt(~UInt64(bitPattern: Int64(value))) 78 - } else { 79 - self = .unsignedInt(UInt64(value)) 80 - } 81 - } 82 - public init(extendedGraphemeClusterLiteral value: String) { self = .utf8String(value) } 83 - public init(unicodeScalarLiteral value: String) { self = .utf8String(value) } 84 - public init(stringLiteral value: String) { self = .utf8String(value) } 85 - public init(arrayLiteral elements: CBOR...) { self = .array(elements) } 86 - public init(dictionaryLiteral elements: (CBOR, CBOR)...) { 87 - var result = [CBOR : CBOR]() 88 - for (key, value) in elements { 89 - result[key] = value 90 - } 91 - self = .map(result) 92 - } 93 - public init(booleanLiteral value: Bool) { self = .boolean(value) } 94 - public init(floatLiteral value: Float32) { self = .float(value) } 95 - 96 - public static func ==(lhs: CBOR, rhs: CBOR) -> Bool { 97 - switch (lhs, rhs) { 98 - case (let .unsignedInt(l), let .unsignedInt(r)): return l == r 99 - case (let .negativeInt(l), let .negativeInt(r)): return l == r 100 - case (let .byteString(l), let .byteString(r)): return l == r 101 - case (let .utf8String(l), let .utf8String(r)): return l == r 102 - case (let .array(l), let .array(r)): return l == r 103 - case (let .map(l), let .map(r)): return l == r 104 - case (let .tagged(tl, l), let .tagged(tr, r)): return tl == tr && l == r 105 - case (let .simple(l), let .simple(r)): return l == r 106 - case (let .boolean(l), let .boolean(r)): return l == r 107 - case (.null, .null): return true 108 - case (.undefined, .undefined): return true 109 - case (let .half(l), let .half(r)): return l == r 110 - case (let .float(l), let .float(r)): return l == r 111 - case (let .double(l), let .double(r)): return l == r 112 - #if canImport(Foundation) 113 - case (let .date(l), let .date(r)): return l == r 114 - #endif 115 - case (.break, .break): return true 116 - case (.unsignedInt, _): return false 117 - case (.negativeInt, _): return false 118 - case (.byteString, _): return false 119 - case (.utf8String, _): return false 120 - case (.array, _): return false 121 - case (.map, _): return false 122 - case (.tagged, _): return false 123 - case (.simple, _): return false 124 - case (.boolean, _): return false 125 - case (.null, _): return false 126 - case (.undefined, _): return false 127 - case (.half, _): return false 128 - case (.float, _): return false 129 - case (.double, _): return false 130 - case (.break, _): return false 131 - default: return false 132 - } 133 - } 134 - 135 - public struct Tag: RawRepresentable, Hashable, Sendable { 136 - public let rawValue: UInt64 137 - 138 - public init(rawValue: UInt64) { 139 - self.rawValue = rawValue 140 - } 141 - 142 - public var hashValue : Int { 143 - return rawValue.hashValue 144 - } 145 - } 146 - } 147 - 148 - extension CBOR.Tag { 149 - public static let standardDateTimeString = CBOR.Tag(rawValue: 0) 150 - public static let epochBasedDateTime = CBOR.Tag(rawValue: 1) 151 - public static let positiveBignum = CBOR.Tag(rawValue: 2) 152 - public static let negativeBignum = CBOR.Tag(rawValue: 3) 153 - public static let decimalFraction = CBOR.Tag(rawValue: 4) 154 - public static let bigfloat = CBOR.Tag(rawValue: 5) 155 - 156 - // 6...20 unassigned 157 - 158 - public static let expectedConversionToBase64URLEncoding = CBOR.Tag(rawValue: 21) 159 - public static let expectedConversionToBase64Encoding = CBOR.Tag(rawValue: 22) 160 - public static let expectedConversionToBase16Encoding = CBOR.Tag(rawValue: 23) 161 - public static let encodedCBORDataItem = CBOR.Tag(rawValue: 24) 162 - 163 - // 25...31 unassigned 164 - 165 - public static let uri = CBOR.Tag(rawValue: 32) 166 - public static let base64Url = CBOR.Tag(rawValue: 33) 167 - public static let base64 = CBOR.Tag(rawValue: 34) 168 - public static let regularExpression = CBOR.Tag(rawValue: 35) 169 - public static let mimeMessage = CBOR.Tag(rawValue: 36) 170 - public static let uuid = CBOR.Tag(rawValue: 37) 171 - 172 - // 38...55798 unassigned 173 - 174 - public static let selfDescribeCBOR = CBOR.Tag(rawValue: 55799) 175 - } 176 - 177 - #if os(Linux) || os(Windows) || os(Android) 178 - let NSEC_PER_SEC: UInt64 = 1_000_000_000 179 - #endif
-235
Old/CBORDecoder.swift
··· 1 - #if canImport(Foundation) 2 - import Foundation 3 - #endif 4 - 5 - public enum CBORError : Error { 6 - case unfinishedSequence 7 - case wrongTypeInsideSequence 8 - case tooLongSequence 9 - case incorrectUTF8String 10 - case maximumDepthExceeded 11 - } 12 - 13 - extension CBOR { 14 - static public func decode(_ input: [UInt8], options: CBOROptions = CBOROptions()) throws -> CBOR? { 15 - return try CBORDecoder(input: input, options: options).decodeItem() 16 - } 17 - } 18 - 19 - public class CBORDecoder { 20 - private var istream : CBORInputStream 21 - public var options: CBOROptions 22 - private var currentDepth = 0 23 - 24 - public init(stream: CBORInputStream, options: CBOROptions = CBOROptions()) { 25 - self.istream = stream 26 - self.options = options 27 - } 28 - 29 - public init(input: ArraySlice<UInt8>, options: CBOROptions = CBOROptions()) { 30 - self.istream = ArraySliceUInt8(slice: input) 31 - self.options = options 32 - } 33 - 34 - public init(input: [UInt8], options: CBOROptions = CBOROptions()) { 35 - self.istream = ArrayUInt8(array: ArraySlice(input)) 36 - self.options = options 37 - } 38 - 39 - func readBinaryNumber<T>(_ type: T.Type) throws -> T { 40 - Array(try self.istream.popBytes(MemoryLayout<T>.size).reversed()).withUnsafeBytes { ptr in 41 - return ptr.load(as: T.self) 42 - } 43 - } 44 - 45 - func readVarUInt(_ v: UInt8, base: UInt8) throws -> UInt64 { 46 - guard v > base + 0x17 else { return UInt64(v - base) } 47 - 48 - switch VarUIntSize(rawValue: v) { 49 - case .uint8: return UInt64(try readBinaryNumber(UInt8.self)) 50 - case .uint16: return UInt64(try readBinaryNumber(UInt16.self)) 51 - case .uint32: return UInt64(try readBinaryNumber(UInt32.self)) 52 - case .uint64: return UInt64(try readBinaryNumber(UInt64.self)) 53 - } 54 - } 55 - 56 - func readLength(_ v: UInt8, base: UInt8) throws -> Int { 57 - let n = try readVarUInt(v, base: base) 58 - 59 - guard n <= Int.max else { 60 - throw CBORError.tooLongSequence 61 - } 62 - 63 - return Int(n) 64 - } 65 - 66 - private func readN(_ n: Int) throws -> [CBOR] { 67 - return try (0..<n).map { _ in 68 - guard let r = try decodeItem() else { throw CBORError.unfinishedSequence } 69 - return r 70 - } 71 - } 72 - 73 - func readUntilBreak() throws -> [CBOR] { 74 - var result: [CBOR] = [] 75 - var cur = try decodeItem() 76 - while cur != CBOR.break { 77 - guard let curr = cur else { throw CBORError.unfinishedSequence } 78 - result.append(curr) 79 - cur = try decodeItem() 80 - } 81 - return result 82 - } 83 - 84 - private func readNPairs(_ n: Int) throws -> [CBOR : CBOR] { 85 - var result: [CBOR: CBOR] = [:] 86 - for _ in (0..<n) { 87 - guard let key = try decodeItem() else { throw CBORError.unfinishedSequence } 88 - guard let val = try decodeItem() else { throw CBORError.unfinishedSequence } 89 - result[key] = val 90 - } 91 - return result 92 - } 93 - 94 - func readPairsUntilBreak() throws -> [CBOR : CBOR] { 95 - var result: [CBOR: CBOR] = [:] 96 - var key = try decodeItem() 97 - if key == CBOR.break { 98 - return result 99 - } 100 - var val = try decodeItem() 101 - while key != CBOR.break { 102 - guard let okey = key else { throw CBORError.unfinishedSequence } 103 - guard let oval = val else { throw CBORError.unfinishedSequence } 104 - result[okey] = oval 105 - do { key = try decodeItem() } catch CBORError.unfinishedSequence { key = nil } 106 - guard (key != CBOR.break) else { break } // don't eat the val after the break! 107 - do { val = try decodeItem() } catch CBORError.unfinishedSequence { val = nil } 108 - } 109 - return result 110 - } 111 - 112 - public func decodeItem() throws -> CBOR? { 113 - guard currentDepth <= options.maximumDepth 114 - else { throw CBORError.maximumDepthExceeded } 115 - 116 - currentDepth += 1 117 - defer { currentDepth -= 1 } 118 - let b = try istream.popByte() 119 - 120 - switch b { 121 - // positive integers 122 - case 0x00...0x1b: 123 - return CBOR.unsignedInt(try readVarUInt(b, base: 0x00)) 124 - 125 - // negative integers 126 - case 0x20...0x3b: 127 - return CBOR.negativeInt(try readVarUInt(b, base: 0x20)) 128 - 129 - // byte strings 130 - case 0x40...0x5b: 131 - let numBytes = try readLength(b, base: 0x40) 132 - return CBOR.byteString(Array(try istream.popBytes(numBytes))) 133 - case 0x5f: 134 - return CBOR.byteString(try readUntilBreak().flatMap { x -> [UInt8] in 135 - guard case .byteString(let r) = x else { throw CBORError.wrongTypeInsideSequence } 136 - return r 137 - }) 138 - 139 - // utf-8 strings 140 - case 0x60...0x7b: 141 - let numBytes = try readLength(b, base: 0x60) 142 - return CBOR.utf8String(try Util.decodeUtf8(try istream.popBytes(numBytes))) 143 - case 0x7f: 144 - return CBOR.utf8String(try readUntilBreak().map { x -> String in 145 - guard case .utf8String(let r) = x else { throw CBORError.wrongTypeInsideSequence } 146 - return r 147 - }.joined(separator: "")) 148 - 149 - // arrays 150 - case 0x80...0x9b: 151 - let numBytes = try readLength(b, base: 0x80) 152 - return CBOR.array(try readN(numBytes)) 153 - case 0x9f: 154 - return CBOR.array(try readUntilBreak()) 155 - 156 - // pairs 157 - case 0xa0...0xbb: 158 - let numBytes = try readLength(b, base: 0xa0) 159 - let pairs = try readNPairs(numBytes) 160 - if self.options.dateStrategy == .annotatedMap { 161 - if let annotatedType = pairs[CBOR.utf8String(AnnotatedMapDateStrategy.typeKey)], 162 - annotatedType == CBOR.utf8String(AnnotatedMapDateStrategy.typeValue), 163 - let dateEpochTimestampCBOR = pairs[CBOR.utf8String(AnnotatedMapDateStrategy.valueKey)], 164 - let date = try? getDateFromTimestamp(dateEpochTimestampCBOR) 165 - { 166 - return CBOR.date(date) 167 - } 168 - } 169 - return CBOR.map(pairs) 170 - case 0xbf: 171 - return CBOR.map(try readPairsUntilBreak()) 172 - 173 - // tagged values 174 - case 0xc0...0xdb: 175 - let tag = try readVarUInt(b, base: 0xc0) 176 - guard let item = try decodeItem() else { throw CBORError.unfinishedSequence } 177 - #if canImport(Foundation) 178 - if tag == 1 { 179 - let date = try getDateFromTimestamp(item) 180 - return CBOR.date(date) 181 - } 182 - #endif 183 - return CBOR.tagged(CBOR.Tag(rawValue: tag), item) 184 - 185 - case 0xe0...0xf3: return CBOR.simple(b - 0xe0) 186 - case 0xf4: return CBOR.boolean(false) 187 - case 0xf5: return CBOR.boolean(true) 188 - case 0xf6: return CBOR.null 189 - case 0xf7: return CBOR.undefined 190 - case 0xf8: return CBOR.simple(try istream.popByte()) 191 - 192 - case 0xf9: 193 - return CBOR.half(Util.readFloat16(x: try readBinaryNumber(UInt16.self))) 194 - case 0xfa: 195 - return CBOR.float(try readBinaryNumber(Float32.self)) 196 - case 0xfb: 197 - return CBOR.double(try readBinaryNumber(Float64.self)) 198 - 199 - case 0xff: return CBOR.break 200 - default: return nil 201 - } 202 - } 203 - } 204 - 205 - func getDateFromTimestamp(_ item: CBOR) throws -> Date { 206 - switch item { 207 - case .double(let d): 208 - return Date(timeIntervalSince1970: TimeInterval(d)) 209 - case .negativeInt(let n): 210 - return Date(timeIntervalSince1970: TimeInterval(-1 - Double(n))) 211 - case .float(let f): 212 - return Date(timeIntervalSince1970: TimeInterval(f)) 213 - case .unsignedInt(let u): 214 - return Date(timeIntervalSince1970: TimeInterval(u)) 215 - default: 216 - throw CBORError.wrongTypeInsideSequence 217 - } 218 - } 219 - 220 - private enum VarUIntSize: UInt8 { 221 - case uint8 = 0 222 - case uint16 = 1 223 - case uint32 = 2 224 - case uint64 = 3 225 - 226 - init(rawValue: UInt8) { 227 - switch rawValue & 0b11 { 228 - case 0: self = .uint8 229 - case 1: self = .uint16 230 - case 2: self = .uint32 231 - case 3: self = .uint64 232 - default: fatalError() // mask only allows values from 0-3 233 - } 234 - } 235 - }
-263
Old/CBOREncodable.swift
··· 1 - #if canImport(Foundation) 2 - import Foundation 3 - #endif 4 - 5 - public protocol CBOREncodable { 6 - /// Optional function that can potentially serve as an opportunity to optimize encoding. 7 - func encode(options: CBOROptions) -> [UInt8] 8 - 9 - /// Required function that returns the appropriate `CBOR` variant for a `CBOREncodable`-conforming value. 10 - func toCBOR(options: CBOROptions) -> CBOR 11 - } 12 - 13 - extension CBOREncodable { 14 - func encode(options: CBOROptions) -> [UInt8] { 15 - self.toCBOR(options: options).encode(options: options) 16 - } 17 - } 18 - 19 - extension CBOR: CBOREncodable { 20 - /// Encodes a wrapped CBOR value. CBOR.half (Float16) is not supported and encodes as `undefined`. 21 - public func encode(options: CBOROptions = CBOROptions()) -> [UInt8] { 22 - switch self { 23 - case let .unsignedInt(ui): return CBOR.encodeVarUInt(ui) 24 - case let .negativeInt(ni): return CBOR.encodeNegativeInt(~Int64(bitPattern: ni)) 25 - case let .byteString(bs): return CBOR.encodeByteString(bs, options: options) 26 - case let .utf8String(str): return str.encode(options: options) 27 - case let .array(a): return CBOR.encodeArray(a, options: options) 28 - case let .map(m): return CBOR.encodeMap(m, options: options) 29 - #if canImport(Foundation) 30 - case let .date(d): return CBOR.encodeDate(d, options: options) 31 - #endif 32 - case let .tagged(t, l): return CBOR.encodeTagged(tag: t, value: l, options: options) 33 - case let .simple(s): return CBOR.encodeSimpleValue(s) 34 - case let .boolean(b): return b.encode(options: options) 35 - case .null: return CBOR.encodeNull() 36 - case .undefined: return CBOR.encodeUndefined() 37 - case .half(_): return CBOR.undefined.encode(options: options) 38 - case let .float(f): return f.encode() 39 - case let .double(d): return d.encode() 40 - case .break: return CBOR.encodeBreak() 41 - } 42 - } 43 - 44 - public func toCBOR(options: CBOROptions = CBOROptions()) -> CBOR { 45 - return self 46 - } 47 - } 48 - 49 - extension Int: CBOREncodable { 50 - public func encode(options: CBOROptions = CBOROptions()) -> [UInt8] { 51 - return Int64(self).encode(options: options) 52 - } 53 - 54 - public func toCBOR(options: CBOROptions = CBOROptions()) -> CBOR { 55 - return Int64(self).toCBOR(options: options) 56 - } 57 - } 58 - 59 - extension Int8: CBOREncodable { 60 - public func encode(options: CBOROptions = CBOROptions()) -> [UInt8] { 61 - return Int64(self).encode(options: options) 62 - } 63 - 64 - public func toCBOR(options: CBOROptions = CBOROptions()) -> CBOR { 65 - return Int64(self).toCBOR(options: options) 66 - } 67 - } 68 - 69 - extension Int16: CBOREncodable { 70 - public func encode(options: CBOROptions = CBOROptions()) -> [UInt8] { 71 - return Int64(self).encode(options: options) 72 - } 73 - 74 - public func toCBOR(options: CBOROptions = CBOROptions()) -> CBOR { 75 - return Int64(self).toCBOR(options: options) 76 - } 77 - } 78 - 79 - extension Int32: CBOREncodable { 80 - public func encode(options: CBOROptions = CBOROptions()) -> [UInt8] { 81 - return Int64(self).encode(options: options) 82 - } 83 - 84 - public func toCBOR(options: CBOROptions = CBOROptions()) -> CBOR { 85 - return Int64(self).toCBOR(options: options) 86 - } 87 - } 88 - 89 - extension Int64: CBOREncodable { 90 - public func encode(options: CBOROptions = CBOROptions()) -> [UInt8] { 91 - if (self < 0) { 92 - return CBOR.encodeNegativeInt(self) 93 - } else { 94 - return CBOR.encodeVarUInt(UInt64(self)) 95 - } 96 - } 97 - 98 - public func toCBOR(options: CBOROptions = CBOROptions()) -> CBOR { 99 - if self < 0 { 100 - return CBOR.negativeInt(~UInt64(bitPattern: self)) 101 - } else { 102 - return CBOR.unsignedInt(UInt64(self)) 103 - } 104 - } 105 - } 106 - 107 - extension UInt: CBOREncodable { 108 - public func encode(options: CBOROptions = CBOROptions()) -> [UInt8] { 109 - return CBOR.encodeVarUInt(UInt64(self)) 110 - } 111 - 112 - public func toCBOR(options: CBOROptions = CBOROptions()) -> CBOR { 113 - return UInt64(self).toCBOR(options: options) 114 - } 115 - } 116 - 117 - extension UInt8: CBOREncodable { 118 - public func encode(options: CBOROptions = CBOROptions()) -> [UInt8] { 119 - return CBOR.encodeUInt8(self) 120 - } 121 - 122 - public func toCBOR(options: CBOROptions = CBOROptions()) -> CBOR { 123 - return UInt64(self).toCBOR(options: options) 124 - } 125 - } 126 - 127 - extension UInt16: CBOREncodable { 128 - public func encode(options: CBOROptions = CBOROptions()) -> [UInt8] { 129 - return CBOR.encodeUInt16(self) 130 - } 131 - 132 - public func toCBOR(options: CBOROptions = CBOROptions()) -> CBOR { 133 - return UInt64(self).toCBOR(options: options) 134 - } 135 - } 136 - 137 - extension UInt32: CBOREncodable { 138 - public func encode(options: CBOROptions = CBOROptions()) -> [UInt8] { 139 - return CBOR.encodeUInt32(self) 140 - } 141 - 142 - public func toCBOR(options: CBOROptions = CBOROptions()) -> CBOR { 143 - return UInt64(self).toCBOR(options: options) 144 - } 145 - } 146 - 147 - extension UInt64: CBOREncodable { 148 - public func encode(options: CBOROptions = CBOROptions()) -> [UInt8] { 149 - return CBOR.encodeUInt64(self) 150 - } 151 - 152 - public func toCBOR(options: CBOROptions = CBOROptions()) -> CBOR { 153 - return CBOR.unsignedInt(self) 154 - } 155 - } 156 - 157 - extension String: CBOREncodable { 158 - public func encode(options: CBOROptions = CBOROptions()) -> [UInt8] { 159 - return CBOR.encodeString(self, options: options) 160 - } 161 - 162 - public func toCBOR(options: CBOROptions = CBOROptions()) -> CBOR { 163 - return CBOR.utf8String(self) 164 - } 165 - } 166 - 167 - extension Float: CBOREncodable { 168 - public func encode(options: CBOROptions = CBOROptions()) -> [UInt8] { 169 - return CBOR.encodeFloat(self) 170 - } 171 - 172 - public func toCBOR(options: CBOROptions = CBOROptions()) -> CBOR { 173 - return CBOR.float(self) 174 - } 175 - } 176 - 177 - extension Double: CBOREncodable { 178 - public func encode(options: CBOROptions = CBOROptions()) -> [UInt8] { 179 - return CBOR.encodeDouble(self) 180 - } 181 - 182 - public func toCBOR(options: CBOROptions = CBOROptions()) -> CBOR { 183 - return CBOR.double(self) 184 - } 185 - } 186 - 187 - extension Bool: CBOREncodable { 188 - public func encode(options: CBOROptions = CBOROptions()) -> [UInt8] { 189 - return CBOR.encodeBool(self) 190 - } 191 - 192 - public func toCBOR(options: CBOROptions = CBOROptions()) -> CBOR { 193 - return CBOR.boolean(self) 194 - } 195 - } 196 - 197 - extension Array where Element: CBOREncodable { 198 - public func encode(options: CBOROptions = CBOROptions()) -> [UInt8] { 199 - return CBOR.encodeArray(self, options: options) 200 - } 201 - 202 - public func toCBOR(options: CBOROptions = CBOROptions()) -> CBOR { 203 - return CBOR.array(self.map { $0.toCBOR(options: options) }) 204 - } 205 - } 206 - 207 - extension Dictionary where Key: CBOREncodable, Value: CBOREncodable { 208 - public func encode(options: CBOROptions = CBOROptions()) -> [UInt8] { 209 - return CBOR.encodeMap(self, options: options) 210 - } 211 - 212 - public func toCBOR(options: CBOROptions = CBOROptions()) -> CBOR { 213 - return CBOR.map(Dictionary<CBOR, CBOR>(uniqueKeysWithValues: self.map { ($0.key.toCBOR(options: options), $0.value.toCBOR(options: options)) })) 214 - } 215 - } 216 - 217 - extension Optional where Wrapped: CBOREncodable { 218 - public func encode(options: CBOROptions = CBOROptions()) -> [UInt8] { 219 - switch self { 220 - case .some(let wrapped): return wrapped.encode(options: options) 221 - case .none: return CBOR.encodeNull() 222 - } 223 - } 224 - 225 - public func toCBOR(options: CBOROptions = CBOROptions()) -> CBOR { 226 - switch self { 227 - case .some(let wrapped): return wrapped.toCBOR(options: options) 228 - case .none: return CBOR.null 229 - } 230 - } 231 - } 232 - 233 - extension NSNull: CBOREncodable { 234 - public func encode(options: CBOROptions = CBOROptions()) -> [UInt8] { 235 - return CBOR.encodeNull() 236 - } 237 - 238 - public func toCBOR(options: CBOROptions = CBOROptions()) -> CBOR { 239 - return CBOR.null 240 - } 241 - } 242 - 243 - #if canImport(Foundation) 244 - extension Date: CBOREncodable { 245 - public func encode(options: CBOROptions = CBOROptions()) -> [UInt8] { 246 - return CBOR.encodeDate(self, options: options) 247 - } 248 - 249 - public func toCBOR(options: CBOROptions = CBOROptions()) -> CBOR { 250 - return CBOR.date(self) 251 - } 252 - } 253 - 254 - extension Data: CBOREncodable { 255 - public func encode(options: CBOROptions = CBOROptions()) -> [UInt8] { 256 - return CBOR.encodeByteString(self.map{ $0 }, options: options) 257 - } 258 - 259 - public func toCBOR(options: CBOROptions = CBOROptions()) -> CBOR { 260 - return CBOR.byteString(self.map { $0 }) 261 - } 262 - } 263 - #endif
-468
Old/CBOREncoder.swift
··· 1 - #if canImport(Foundation) 2 - import Foundation 3 - #endif 4 - 5 - let isBigEndian = Int(bigEndian: 42) == 42 6 - 7 - /// Takes a value breaks it into bytes. assumes necessity to reverse for endianness if needed 8 - /// This function has only been tested with UInt_s, Floats and Doubles 9 - /// T must be a simple type. It cannot be a collection type. 10 - func rawBytes<T>(of x: T) -> [UInt8] { 11 - var mutable = x // create mutable copy for `withUnsafeBytes` 12 - let bigEndianResult = withUnsafeBytes(of: &mutable) { Array($0) } 13 - return isBigEndian ? bigEndianResult : bigEndianResult.reversed() 14 - } 15 - 16 - /// Defines basic CBOR.encode API. 17 - /// Defines more fine-grained functions of form CBOR.encode*(_ x) 18 - /// for all CBOR types except Float16 19 - extension CBOR { 20 - public static func encode<T: CBOREncodable>(_ value: T, options: CBOROptions = CBOROptions()) -> [UInt8] { 21 - return value.encode(options: options) 22 - } 23 - 24 - /// Encodes an array as either a CBOR array type or a CBOR bytestring type, depending on `asByteString`. 25 - /// NOTE: when `asByteString` is true and T = UInt8, the array is interpreted in network byte order 26 - /// Arrays with values of all other types will have their bytes reversed if the system is little endian. 27 - public static func encode<T: CBOREncodable>(_ array: [T], asByteString: Bool = false, options: CBOROptions = CBOROptions()) -> [UInt8] { 28 - if asByteString { 29 - let length = array.count 30 - var res = length.encode() 31 - res[0] = res[0] | 0b010_00000 32 - let itemSize = MemoryLayout<T>.size 33 - let bytelength = length * itemSize 34 - res.reserveCapacity(res.count + bytelength) 35 - 36 - let noReversalNeeded = isBigEndian || T.self == UInt8.self 37 - 38 - array.withUnsafeBytes { bufferPtr in 39 - guard let ptr = bufferPtr.baseAddress?.bindMemory(to: UInt8.self, capacity: bytelength) else { 40 - fatalError("Invalid pointer") 41 - } 42 - var j = 0 43 - for i in 0..<bytelength { 44 - j = noReversalNeeded ? i : bytelength - 1 - i 45 - res.append((ptr + j).pointee) 46 - } 47 - } 48 - return res 49 - } else { 50 - return encodeArray(array, options: options) 51 - } 52 - } 53 - 54 - public static func encode<A: CBOREncodable, B: CBOREncodable>(_ dict: [A: B], options: CBOROptions = CBOROptions()) -> [UInt8] { 55 - return encodeMap(dict, options: options) 56 - } 57 - 58 - // MARK: - major 0: unsigned integer 59 - 60 - public static func encodeUInt8(_ x: UInt8) -> [UInt8] { 61 - if (x < 24) { return [x] } 62 - else { return [0x18, x] } 63 - } 64 - 65 - public static func encodeUInt16(_ x: UInt16) -> [UInt8] { 66 - return [0x19] + rawBytes(of: x) 67 - } 68 - 69 - public static func encodeUInt32(_ x: UInt32) -> [UInt8] { 70 - return [0x1a] + rawBytes(of: x) 71 - } 72 - 73 - public static func encodeUInt64(_ x: UInt64) -> [UInt8] { 74 - return [0x1b] + rawBytes(of: x) 75 - } 76 - 77 - internal static func encodeVarUInt(_ x: UInt64) -> [UInt8] { 78 - switch x { 79 - case let x where x <= UInt8.max: return CBOR.encodeUInt8(UInt8(x)) 80 - case let x where x <= UInt16.max: return CBOR.encodeUInt16(UInt16(x)) 81 - case let x where x <= UInt32.max: return CBOR.encodeUInt32(UInt32(x)) 82 - default: return CBOR.encodeUInt64(x) 83 - } 84 - } 85 - 86 - // MARK: - major 1: negative integer 87 - 88 - public static func encodeNegativeInt(_ x: Int64) -> [UInt8] { 89 - assert(x < 0) 90 - var res = encodeVarUInt(~UInt64(bitPattern: x)) 91 - res[0] = res[0] | 0b001_00000 92 - return res 93 - } 94 - 95 - // MARK: - major 2: bytestring 96 - 97 - public static func encodeByteString(_ bs: [UInt8], options: CBOROptions = CBOROptions()) -> [UInt8] { 98 - var res = bs.count.encode(options: options) 99 - res[0] = res[0] | 0b010_00000 100 - res.append(contentsOf: bs) 101 - return res 102 - } 103 - 104 - #if canImport(Foundation) 105 - public static func encodeData(_ data: Data, options: CBOROptions = CBOROptions()) -> [UInt8] { 106 - return encodeByteString([UInt8](data), options: options) 107 - } 108 - #endif 109 - 110 - // MARK: - major 3: UTF8 string 111 - 112 - public static func encodeString(_ str: String, options: CBOROptions = CBOROptions()) -> [UInt8] { 113 - let utf8array = Array(str.utf8) 114 - var res = utf8array.count.encode(options: options) 115 - res[0] = res[0] | 0b011_00000 116 - res.append(contentsOf: utf8array) 117 - return res 118 - } 119 - 120 - // MARK: - major 4: array of data items 121 - 122 - public static func encodeArray<T: CBOREncodable>(_ arr: [T], options: CBOROptions = CBOROptions()) -> [UInt8] { 123 - var res = arr.count.encode(options: options) 124 - res[0] = res[0] | 0b100_00000 125 - res.append(contentsOf: arr.flatMap{ return $0.encode(options: options) }) 126 - return res 127 - } 128 - 129 - // MARK: - major 5: a map of pairs of data items 130 - 131 - public static func encodeMap<A: CBOREncodable, B: CBOREncodable>(_ map: [A: B], options: CBOROptions = CBOROptions()) -> [UInt8] { 132 - if options.forbidNonStringMapKeys { 133 - try! ensureStringKey(A.self) 134 - } 135 - var res: [UInt8] = [] 136 - res.reserveCapacity(1 + map.count * (MemoryLayout<A>.size + MemoryLayout<B>.size + 2)) 137 - res = map.count.encode(options: options) 138 - res[0] = res[0] | 0b101_00000 139 - for (k, v) in map { 140 - res.append(contentsOf: k.encode(options: options)) 141 - res.append(contentsOf: v.encode(options: options)) 142 - } 143 - return res 144 - } 145 - 146 - public static func encodeMap<A: CBOREncodable>(_ map: [A: Any?], options: CBOROptions = CBOROptions()) throws -> [UInt8] { 147 - if options.forbidNonStringMapKeys { 148 - try ensureStringKey(A.self) 149 - } 150 - var res: [UInt8] = [] 151 - res = map.count.encode(options: options) 152 - res[0] = res[0] | 0b101_00000 153 - try CBOR.encodeMap(map, into: &res, options: options) 154 - return res 155 - } 156 - 157 - // MARK: - major 6: tagged values 158 - 159 - public static func encodeTagged<T: CBOREncodable>(tag: Tag, value: T, options: CBOROptions = CBOROptions()) -> [UInt8] { 160 - var res = encodeVarUInt(tag.rawValue) 161 - res[0] = res[0] | 0b110_00000 162 - res.append(contentsOf: value.encode(options: options)) 163 - return res 164 - } 165 - 166 - // MARK: - major 7: floats, simple values, the 'break' stop code 167 - 168 - public static func encodeSimpleValue(_ x: UInt8) -> [UInt8] { 169 - if x < 24 { 170 - return [0b111_00000 | x] 171 - } else { 172 - return [0xf8, x] 173 - } 174 - } 175 - 176 - public static func encodeNull() -> [UInt8] { 177 - return [0xf6] 178 - } 179 - 180 - public static func encodeUndefined() -> [UInt8] { 181 - return [0xf7] 182 - } 183 - 184 - public static func encodeBreak() -> [UInt8] { 185 - return [0xff] 186 - } 187 - 188 - public static func encodeFloat(_ x: Float) -> [UInt8] { 189 - return [0xfa] + rawBytes(of: x) 190 - } 191 - 192 - public static func encodeDouble(_ x: Double) -> [UInt8] { 193 - return [0xfb] + rawBytes(of: x) 194 - } 195 - 196 - public static func encodeBool(_ x: Bool) -> [UInt8] { 197 - return x ? [0xf5] : [0xf4] 198 - } 199 - 200 - // MARK: - Indefinite length items 201 - 202 - /// Returns a CBOR value indicating the opening of an indefinite-length data item. 203 - /// The user is responsible for creating and sending subsequent valid CBOR. 204 - /// In particular, the user must end the stream with the CBOR.break byte, which 205 - /// can be returned with `encodeStreamEnd()`. 206 - /// 207 - /// The stream API is limited right now, but will get better when Swift allows 208 - /// one to generically constrain the elements of generic Iterators, in which case 209 - /// streaming implementation is trivial 210 - public static func encodeArrayStreamStart() -> [UInt8] { 211 - return [0x9f] 212 - } 213 - 214 - public static func encodeMapStreamStart() -> [UInt8] { 215 - return [0xbf] 216 - } 217 - 218 - public static func encodeStringStreamStart() -> [UInt8] { 219 - return [0x7f] 220 - } 221 - 222 - public static func encodeByteStringStreamStart() -> [UInt8] { 223 - return [0x5f] 224 - } 225 - 226 - /// This is the same as a CBOR "break" value 227 - public static func encodeStreamEnd() -> [UInt8] { 228 - return [0xff] 229 - } 230 - 231 - // TODO: unify definite and indefinite code 232 - public static func encodeArrayChunk<T: CBOREncodable>(_ chunk: [T], options: CBOROptions = CBOROptions()) -> [UInt8] { 233 - var res: [UInt8] = [] 234 - res.reserveCapacity(chunk.count * MemoryLayout<T>.size) 235 - res.append(contentsOf: chunk.flatMap{ return $0.encode(options: options) }) 236 - return res 237 - } 238 - 239 - public static func encodeMapChunk<A: CBOREncodable, B: CBOREncodable>(_ map: [A: B], options: CBOROptions = CBOROptions()) -> [UInt8] { 240 - if options.forbidNonStringMapKeys { 241 - try! ensureStringKey(A.self) 242 - } 243 - var res: [UInt8] = [] 244 - let count = map.count 245 - res.reserveCapacity(count * MemoryLayout<A>.size + count * MemoryLayout<B>.size) 246 - for (k, v) in map { 247 - res.append(contentsOf: k.encode(options: options)) 248 - res.append(contentsOf: v.encode(options: options)) 249 - } 250 - return res 251 - } 252 - 253 - #if canImport(Foundation) 254 - public static func encodeDate(_ date: Date, options: CBOROptions = CBOROptions()) -> [UInt8] { 255 - let timeInterval = date.timeIntervalSince1970 256 - let (integral, fractional) = modf(timeInterval) 257 - 258 - let seconds = Int64(integral) 259 - let nanoseconds = Int32(fractional * Double(NSEC_PER_SEC)) 260 - 261 - switch options.dateStrategy { 262 - case .annotatedMap: 263 - var dateCBOR: CBOR 264 - if seconds < 0 && nanoseconds == 0 { 265 - dateCBOR = CBOR.negativeInt(UInt64(-Double(timeInterval + 1))) 266 - } else if seconds > UInt32.max { 267 - dateCBOR = CBOR.double(timeInterval) 268 - } else if nanoseconds != 0 { 269 - dateCBOR = CBOR.double(timeInterval) 270 - } else { 271 - dateCBOR = CBOR.unsignedInt(UInt64(seconds)) 272 - } 273 - 274 - let map: [String: CBOREncodable] = [ 275 - AnnotatedMapDateStrategy.typeKey: AnnotatedMapDateStrategy.typeValue, 276 - AnnotatedMapDateStrategy.valueKey: dateCBOR 277 - ] 278 - return try! CBOR.encodeMap(map, options: options) 279 - case .taggedAsEpochTimestamp: 280 - var res: [UInt8] = [0b110_00001] // Epoch timestamp tag is 1 281 - if seconds < 0 && nanoseconds == 0 { 282 - res.append(contentsOf: CBOR.encodeNegativeInt(Int64(timeInterval))) 283 - } else if seconds > UInt32.max { 284 - res.append(contentsOf: CBOR.encodeDouble(timeInterval)) 285 - } else if nanoseconds != 0 { 286 - res.append(contentsOf: CBOR.encodeDouble(timeInterval)) 287 - } else { 288 - res.append(contentsOf: CBOR.encode(Int(seconds), options: options)) 289 - } 290 - 291 - return res 292 - } 293 - } 294 - #endif 295 - 296 - public static func encodeAny(_ any: Any?, options: CBOROptions = CBOROptions()) throws -> [UInt8] { 297 - switch any { 298 - case is Int: 299 - return (any as! Int).encode() 300 - case is Int8: 301 - return (any as! Int8).encode() 302 - case is Int16: 303 - return (any as! Int16).encode() 304 - case is Int32: 305 - return (any as! Int32).encode() 306 - case is Int64: 307 - return (any as! Int64).encode() 308 - case is UInt: 309 - return (any as! UInt).encode() 310 - case is UInt8: 311 - return (any as! UInt8).encode() 312 - case is UInt16: 313 - return (any as! UInt16).encode() 314 - case is UInt32: 315 - return (any as! UInt32).encode() 316 - case is UInt64: 317 - return (any as! UInt64).encode() 318 - case is String: 319 - return (any as! String).encode(options: options) 320 - case is Float: 321 - return (any as! Float).encode() 322 - case is Double: 323 - return (any as! Double).encode() 324 - case is Bool: 325 - return (any as! Bool).encode() 326 - #if canImport(Foundation) 327 - case is Data: 328 - return CBOR.encodeByteString((any as! Data).map { $0 }, options: options) 329 - case is Date: 330 - return CBOR.encodeDate((any as! Date), options: options) 331 - case is NSNull: 332 - return CBOR.encodeNull() 333 - #endif 334 - case is [Any?]: 335 - let anyArr = any as! [Any?] 336 - var res = anyArr.count.encode(options: options) 337 - res[0] = res[0] | 0b100_00000 338 - let encodedInners = try anyArr.reduce(into: []) { acc, next in 339 - acc.append(contentsOf: try encodeAny(next, options: options)) 340 - } 341 - res.append(contentsOf: encodedInners) 342 - return res 343 - case is [String: Any?]: 344 - let anyMap = any as! [String: Any?] 345 - var res: [UInt8] = anyMap.count.encode(options: options) 346 - res[0] = res[0] | 0b101_00000 347 - try CBOR.encodeMap(anyMap, into: &res, options: options) 348 - return res 349 - case is Void: 350 - return CBOR.encodeUndefined() 351 - case nil: 352 - return CBOR.encodeNull() 353 - default: 354 - if let encodable = any as? CBOREncodable { 355 - return encodable.encode(options: options) 356 - } else if let encodable = any as? Codable { 357 - let encoder = CodableCBOREncoder() 358 - encoder.options = options.toCodableEncoderOptions() 359 - return try [UInt8](encoder.encode(encodable)) 360 - } 361 - throw CBOREncoderError.invalidType 362 - } 363 - } 364 - 365 - internal static func cborFromAny(_ any: Any?, options: CBOROptions = CBOROptions()) throws -> CBOR { 366 - switch any { 367 - case is Int: 368 - return cborFromInt64(Int64(any as! Int)) 369 - case is Int8: 370 - return cborFromInt64(Int64(any as! Int8)) 371 - case is Int16: 372 - return cborFromInt64(Int64(any as! Int16)) 373 - case is Int32: 374 - return cborFromInt64(Int64(any as! Int32)) 375 - case is Int64: 376 - return cborFromInt64(any as! Int64) 377 - case is UInt: 378 - return CBOR.unsignedInt(UInt64(any as! UInt)) 379 - case is UInt8: 380 - return CBOR.unsignedInt(UInt64(any as! UInt8)) 381 - case is UInt16: 382 - return CBOR.unsignedInt(UInt64(any as! UInt16)) 383 - case is UInt32: 384 - return CBOR.unsignedInt(UInt64(any as! UInt32)) 385 - case is UInt64: 386 - return CBOR.unsignedInt(any as! UInt64) 387 - case is String: 388 - return CBOR.utf8String(any as! String) 389 - case is Float: 390 - return CBOR.float(any as! Float) 391 - case is Double: 392 - return CBOR.double(any as! Double) 393 - case is Bool: 394 - return CBOR.boolean(any as! Bool) 395 - #if canImport(Foundation) 396 - case is Data: 397 - return CBOR.byteString((any as! Data).map { $0 }) 398 - case is Date: 399 - return CBOR.date(any as! Date) 400 - case is NSNull: 401 - return CBOR.null 402 - #endif 403 - case is [Any?]: 404 - let anyArr = any as! [Any?] 405 - return try CBOR.array(anyArr.map { try cborFromAny($0) }) 406 - case is [String: Any?]: 407 - let anyMap = any as! [String: Any?] 408 - return try CBOR.map(Dictionary( 409 - uniqueKeysWithValues: anyMap.map { try (cborFromAny($0.key), cborFromAny($0.value)) } 410 - )) 411 - case is Void: 412 - return CBOR.undefined 413 - case nil: 414 - return CBOR.null 415 - default: 416 - if let encodable = any as? CBOREncodable { 417 - return encodable.toCBOR(options: options) 418 - } else if let encodable = any as? Codable { 419 - // This is very much a slow path - we fully encode and then 420 - // decode the value to get it as a `CBOR` 421 - let encoder = CodableCBOREncoder() 422 - encoder.options = options.toCodableEncoderOptions() 423 - let encoded = try [UInt8](encoder.encode(encodable)) 424 - guard let decoded = try CBOR.decode(encoded) else { 425 - throw CBOREncoderError.invalidType 426 - } 427 - return decoded 428 - } 429 - throw CBOREncoderError.invalidType 430 - } 431 - } 432 - 433 - private static func cborFromInt64(_ i: Int64) -> CBOR { 434 - if i < 0 { 435 - return CBOR.negativeInt(~UInt64(bitPattern: i)) 436 - } else { 437 - return CBOR.unsignedInt(UInt64(i)) 438 - } 439 - } 440 - 441 - private static func encodeMap<A: CBOREncodable>(_ map: [A: Any?], into res: inout [UInt8], options: CBOROptions = CBOROptions()) throws { 442 - if options.forbidNonStringMapKeys { 443 - try ensureStringKey(A.self) 444 - } 445 - let sortedKeysWithEncodedKeys = map.keys.map { 446 - (encoded: $0.encode(options: options), key: $0) 447 - }.sorted(by: { 448 - $0.encoded.lexicographicallyPrecedes($1.encoded) 449 - }) 450 - 451 - try sortedKeysWithEncodedKeys.forEach { keyTuple in 452 - res.append(contentsOf: keyTuple.encoded) 453 - let encodedVal = try encodeAny(map[keyTuple.key]!, options: options) 454 - res.append(contentsOf: encodedVal) 455 - } 456 - } 457 - } 458 - 459 - public enum CBOREncoderError: Error { 460 - case invalidType 461 - case nonStringKeyInMap 462 - } 463 - 464 - func ensureStringKey<T>(_ keyType: T.Type) throws where T: CBOREncodable { 465 - guard T.self is SwiftCBORStringKey.Type else { 466 - throw CBOREncoderError.nonStringKeyInMap 467 - } 468 - }
-41
Old/CBORInputStream.swift
··· 1 - public protocol CBORInputStream { 2 - mutating func popByte() throws -> UInt8 3 - mutating func popBytes(_ n: Int) throws -> ArraySlice<UInt8> 4 - } 5 - 6 - // FUCK: https://openradar.appspot.com/23255436 7 - struct ArraySliceUInt8 { 8 - var slice : ArraySlice<UInt8> 9 - } 10 - 11 - struct ArrayUInt8 { 12 - var array : ArraySlice<UInt8> 13 - } 14 - 15 - extension ArraySliceUInt8: CBORInputStream { 16 - mutating func popByte() throws -> UInt8 { 17 - if slice.count < 1 { throw CBORError.unfinishedSequence } 18 - return slice.removeFirst() 19 - } 20 - 21 - mutating func popBytes(_ n: Int) throws -> ArraySlice<UInt8> { 22 - if slice.count < n { throw CBORError.unfinishedSequence } 23 - let result = slice.prefix(n) 24 - slice = slice.dropFirst(n) 25 - return result 26 - } 27 - } 28 - 29 - extension ArrayUInt8: CBORInputStream { 30 - mutating func popByte() throws -> UInt8 { 31 - guard array.count > 0 else { throw CBORError.unfinishedSequence } 32 - return array.removeFirst() 33 - } 34 - 35 - mutating func popBytes(_ n: Int) throws -> ArraySlice<UInt8> { 36 - guard array.count >= n else { throw CBORError.unfinishedSequence } 37 - let res = array.prefix(n) 38 - array = array.dropFirst(n) 39 - return res 40 - } 41 - }
-54
Old/CBOROptions.swift
··· 1 - public struct CBOROptions { 2 - let useStringKeys: Bool 3 - let dateStrategy: DateStrategy 4 - let forbidNonStringMapKeys: Bool 5 - let orderKeys: Bool 6 - /// The maximum number of nested items, inclusive, to decode. A maximum set to 0 dissallows anything other than top-level primitives. 7 - let maximumDepth: Int 8 - 9 - public init( 10 - useStringKeys: Bool = false, 11 - dateStrategy: DateStrategy = .taggedAsEpochTimestamp, 12 - forbidNonStringMapKeys: Bool = false, 13 - orderKeys: Bool = false, 14 - maximumDepth: Int = .max 15 - ) { 16 - self.useStringKeys = useStringKeys 17 - self.dateStrategy = dateStrategy 18 - self.forbidNonStringMapKeys = forbidNonStringMapKeys 19 - self.orderKeys = orderKeys 20 - self.maximumDepth = maximumDepth 21 - } 22 - 23 - func toCodableEncoderOptions() -> CodableCBOREncoder._Options { 24 - return CodableCBOREncoder._Options( 25 - useStringKeys: self.useStringKeys, 26 - dateStrategy: self.dateStrategy, 27 - forbidNonStringMapKeys: self.forbidNonStringMapKeys, 28 - orderKeys: self.orderKeys 29 - ) 30 - } 31 - 32 - func toCodableDecoderOptions() -> CodableCBORDecoder._Options { 33 - return CodableCBORDecoder._Options( 34 - useStringKeys: self.useStringKeys, 35 - dateStrategy: self.dateStrategy, 36 - maximumDepth: self.maximumDepth 37 - ) 38 - } 39 - } 40 - 41 - public enum DateStrategy { 42 - case taggedAsEpochTimestamp 43 - case annotatedMap 44 - } 45 - 46 - struct AnnotatedMapDateStrategy { 47 - static let typeKey = "__type" 48 - static let typeValue = "date_epoch_timestamp" 49 - static let valueKey = "__value" 50 - } 51 - 52 - protocol SwiftCBORStringKey {} 53 - 54 - extension String: SwiftCBORStringKey {}
-219
Old/Decoder/CodableCBORDecoder.swift
··· 1 - import Foundation 2 - 3 - final public class CodableCBORDecoder { 4 - public var useStringKeys: Bool = false 5 - public var dateStrategy: DateStrategy = .taggedAsEpochTimestamp 6 - 7 - struct _Options { 8 - let useStringKeys: Bool 9 - let dateStrategy: DateStrategy 10 - let maximumDepth: Int 11 - 12 - init( 13 - useStringKeys: Bool = false, 14 - dateStrategy: DateStrategy = .taggedAsEpochTimestamp, 15 - maximumDepth: Int = .max 16 - ) { 17 - self.useStringKeys = useStringKeys 18 - self.dateStrategy = dateStrategy 19 - self.maximumDepth = maximumDepth 20 - } 21 - 22 - func toCBOROptions() -> CBOROptions { 23 - return CBOROptions( 24 - useStringKeys: self.useStringKeys, 25 - dateStrategy: self.dateStrategy, 26 - maximumDepth: self.maximumDepth 27 - ) 28 - } 29 - } 30 - 31 - var options: _Options { 32 - return _Options(useStringKeys: self.useStringKeys, dateStrategy: self.dateStrategy) 33 - } 34 - 35 - public init() {} 36 - 37 - public var userInfo: [CodingUserInfoKey : Any] = [:] 38 - 39 - public func decode<T: Decodable>(_ type: T.Type, from data: Data) throws -> T { 40 - return try decode(type, from: ArraySlice([UInt8](data))) 41 - } 42 - 43 - public func decode<T: Decodable>(_ type: T.Type, from data: ArraySlice<UInt8>) throws -> T { 44 - let decoder = _CBORDecoder(data: data, options: self.options) 45 - decoder.userInfo = self.userInfo 46 - if type == Date.self { 47 - guard let cbor = try? CBORDecoder(input: [UInt8](data), options: self.options.toCBOROptions()).decodeItem(), 48 - case .date(let date) = cbor 49 - else { 50 - let context = DecodingError.Context(codingPath: [], debugDescription: "Unable to decode data for Date") 51 - throw DecodingError.dataCorrupted(context) 52 - } 53 - return date as! T 54 - } else if type == Data.self { 55 - guard let cbor = try? CBORDecoder(input: [UInt8](data), options: self.options.toCBOROptions()).decodeItem(), 56 - case .byteString(let data) = cbor 57 - else { 58 - let context = DecodingError.Context(codingPath: [], debugDescription: "Unable to decode data for Data") 59 - throw DecodingError.dataCorrupted(context) 60 - } 61 - return Data(data) as! T 62 - } 63 - return try T(from: decoder) 64 - } 65 - 66 - func setOptions(_ newOptions: _Options) { 67 - self.useStringKeys = newOptions.useStringKeys 68 - self.dateStrategy = newOptions.dateStrategy 69 - } 70 - } 71 - 72 - final class _CBORDecoder { 73 - var codingPath: [CodingKey] = [] 74 - 75 - var userInfo: [CodingUserInfoKey : Any] = [:] 76 - 77 - var container: CBORDecodingContainer? 78 - fileprivate var data: ArraySlice<UInt8> 79 - 80 - let options: CodableCBORDecoder._Options 81 - 82 - init(data: ArraySlice<UInt8>, options: CodableCBORDecoder._Options) { 83 - self.data = data 84 - self.options = options 85 - } 86 - } 87 - 88 - extension _CBORDecoder: Decoder { 89 - func container<Key: CodingKey>(keyedBy type: Key.Type) throws -> KeyedDecodingContainer<Key> { 90 - try ensureMap(self.data.first, keyType: Key.self) 91 - 92 - let container = KeyedContainer<Key>(data: self.data, codingPath: self.codingPath, userInfo: self.userInfo, options: self.options) 93 - self.container = container 94 - 95 - return KeyedDecodingContainer(container) 96 - } 97 - 98 - func unkeyedContainer() throws -> UnkeyedDecodingContainer { 99 - try ensureArray(self.data.first) 100 - 101 - let container = UnkeyedContainer(data: self.data, codingPath: self.codingPath, userInfo: self.userInfo, options: self.options) 102 - self.container = container 103 - 104 - return container 105 - } 106 - 107 - func singleValueContainer() throws -> SingleValueDecodingContainer { 108 - let container = SingleValueContainer(data: self.data, codingPath: self.codingPath, userInfo: self.userInfo, options: self.options) 109 - self.container = container 110 - 111 - return container 112 - } 113 - 114 - func ensureMap<Key: CodingKey>(_ initialByte: UInt8?, keyType: Key.Type) throws { 115 - switch initialByte { 116 - case .some(0xa0...0xbf): 117 - // all good, continue 118 - return 119 - case nil: 120 - let context = DecodingError.Context( 121 - codingPath: self.codingPath, 122 - debugDescription: "Unexpected end of data" 123 - ) 124 - throw DecodingError.dataCorrupted(context) 125 - default: 126 - let typeDescriptionOfByte = typeDescriptionFromByte(initialByte!) ?? "unknown" 127 - let context = DecodingError.Context( 128 - codingPath: self.codingPath, 129 - debugDescription: "Expected map but found \(typeDescriptionOfByte)" 130 - ) 131 - throw DecodingError.typeMismatch(keyType, context) 132 - } 133 - } 134 - 135 - func ensureArray(_ initialByte: UInt8?) throws { 136 - switch initialByte { 137 - case .some(0x80...0x9f): 138 - // all good, continue 139 - return 140 - case nil: 141 - let context = DecodingError.Context( 142 - codingPath: self.codingPath, 143 - debugDescription: "Unexpected end of data" 144 - ) 145 - throw DecodingError.dataCorrupted(context) 146 - default: 147 - let typeDescriptionOfByte = typeDescriptionFromByte(initialByte!) ?? "unknown" 148 - let context = DecodingError.Context( 149 - codingPath: self.codingPath, 150 - debugDescription: "Expected array but found \(typeDescriptionOfByte)" 151 - ) 152 - throw DecodingError.typeMismatch(Array<Any?>.self, context) 153 - } 154 - } 155 - } 156 - 157 - protocol CBORDecodingContainer: AnyObject { 158 - var codingPath: [CodingKey] { get set } 159 - 160 - var userInfo: [CodingUserInfoKey : Any] { get } 161 - 162 - var data: ArraySlice<UInt8> { get set } 163 - var index: Data.Index { get set } 164 - } 165 - 166 - extension CBORDecodingContainer { 167 - func readByte() throws -> UInt8 { 168 - return try read(1).first! 169 - } 170 - 171 - func read(_ length: Int) throws -> Data { 172 - let nextIndex = self.index.advanced(by: length) 173 - guard nextIndex <= self.data.endIndex else { 174 - let context = DecodingError.Context(codingPath: self.codingPath, debugDescription: "Unexpected end of data") 175 - throw DecodingError.dataCorrupted(context) 176 - } 177 - defer { self.index = nextIndex } 178 - 179 - return Data(Array(self.data[self.index..<(nextIndex)])) 180 - } 181 - 182 - func peekByte() throws -> UInt8 { 183 - return try peek(1).first! 184 - } 185 - 186 - func peek(_ length: Int) throws -> ArraySlice<UInt8> { 187 - let nextIndex = self.index.advanced(by: length) 188 - guard nextIndex <= self.data.endIndex else { 189 - let context = DecodingError.Context(codingPath: self.codingPath, debugDescription: "Unexpected end of data") 190 - throw DecodingError.dataCorrupted(context) 191 - } 192 - 193 - return self.data[self.index..<(nextIndex)] 194 - } 195 - 196 - func read<T: FixedWidthInteger>(_ type: T.Type) throws -> T { 197 - let stride = MemoryLayout<T>.stride 198 - let bytes = [UInt8](try read(stride)) 199 - return T(bytes: bytes) 200 - } 201 - } 202 - 203 - func typeDescriptionFromByte(_ byte: UInt8) -> String? { 204 - switch byte { 205 - case 0x00...0x1b, 0x20...0x3b: return "integer" 206 - case 0x40...0x5b, 0x5f: return "byte string" 207 - case 0x60...0x7b, 0x7f: return "string" 208 - case 0x80...0x9f: return "array" 209 - case 0xa0...0xbf: return "map" 210 - case 0xc0: return "text-based date/time" 211 - case 0xc1: return "epoch-based date/time" 212 - case 0xc2...0xdb: return "unspecified tagged value" 213 - case 0xf4, 0xf5: return "boolean" 214 - case 0xf6: return "null" 215 - case 0xf8...0xfb: return "float" 216 - default: 217 - return nil 218 - } 219 - }
-189
Old/Decoder/KeyedDecodingContainer.swift
··· 1 - import Foundation 2 - 3 - extension _CBORDecoder { 4 - final class KeyedContainer<Key: CodingKey> { 5 - 6 - // This is non-nil once nestedContainers() has been called once, and if the data is valid 7 - var _nestedContainers: [AnyCodingKey: CBORDecodingContainer]? = nil 8 - 9 - // This is non-nil once count() has been called once, and if the data is valid 10 - var _count: Int? 11 - 12 - var data: ArraySlice<UInt8> 13 - var index: Data.Index 14 - var codingPath: [CodingKey] 15 - var userInfo: [CodingUserInfoKey: Any] 16 - let options: CodableCBORDecoder._Options 17 - 18 - init(data: ArraySlice<UInt8>, codingPath: [CodingKey], userInfo: [CodingUserInfoKey : Any], options: CodableCBORDecoder._Options) { 19 - self.codingPath = codingPath 20 - self.userInfo = userInfo 21 - self.data = data 22 - self.index = self.data.startIndex 23 - self.options = options 24 - } 25 - 26 - func checkCanDecodeValue(forKey key: Key) throws { 27 - guard self.contains(key) else { 28 - let context = DecodingError.Context(codingPath: self.codingPath, debugDescription: "key not found: \(key)") 29 - throw DecodingError.keyNotFound(key, context) 30 - } 31 - } 32 - 33 - func nestedContainers() throws -> [AnyCodingKey: CBORDecodingContainer] { 34 - if let nestedContainers = self._nestedContainers { 35 - return nestedContainers 36 - } 37 - 38 - guard let count = try count() else { 39 - return [:] 40 - } 41 - 42 - var nestedContainers: [AnyCodingKey: CBORDecodingContainer] = [:] 43 - 44 - let unkeyedContainer = UnkeyedContainer(data: self.data.suffix(from: self.index), codingPath: self.codingPath, userInfo: self.userInfo, options: self.options) 45 - unkeyedContainer.count = count * 2 46 - 47 - var iterator = unkeyedContainer.nestedContainers.makeIterator() 48 - 49 - for _ in 0..<count { 50 - guard let keyContainer = iterator.next() as? _CBORDecoder.SingleValueContainer, 51 - let container = iterator.next() else { 52 - fatalError() // FIXME 53 - } 54 - 55 - let keyVal: AnyCodingKey 56 - if self.options.useStringKeys { 57 - let stringKey = try keyContainer.decode(String.self) 58 - keyVal = AnyCodingKey(stringValue: stringKey) 59 - } else { 60 - keyVal = try keyContainer.decode(AnyCodingKey.self) 61 - } 62 - nestedContainers[keyVal] = container 63 - } 64 - 65 - self.index = unkeyedContainer.index 66 - self._nestedContainers = nestedContainers 67 - return nestedContainers 68 - } 69 - 70 - func count() throws -> Int? { 71 - if let count = self._count { 72 - return count 73 - } 74 - 75 - let count: Int? 76 - 77 - let format = try self.readByte() 78 - switch format { 79 - case 0xa0...0xb7: count = Int(format & 0x1F) 80 - case 0xb8: count = Int(try read(UInt8.self)) 81 - case 0xb9: count = Int(try read(UInt16.self)) 82 - case 0xba: count = Int(try read(UInt32.self)) 83 - case 0xbb: count = Int(try read(UInt64.self)) 84 - case 0xbf: 85 - // FIXME: This is a very inefficient way of doing this. Really we should be modifying the 86 - // nestedContainers code so that if we're working with a map that has a break at the end 87 - // it creates the containers as it goes, rather than first calculating the count (which 88 - // involves going through all the bytes) and then going back through the data and decoding 89 - // each key-value pair in the map. 90 - let nextIndex = self.data.startIndex.advanced(by: 1) 91 - let remainingData = self.data.suffix(from: nextIndex) 92 - count = try? CBORDecoder(input: remainingData.map { $0 }).readPairsUntilBreak().keys.count 93 - default: 94 - let context = DecodingError.Context( 95 - codingPath: self.codingPath, 96 - debugDescription: "Unable to get count of elements in dictionary" 97 - ) 98 - throw DecodingError.typeMismatch(Int.self, context) 99 - } 100 - 101 - self._count = count 102 - return count 103 - } 104 - } 105 - } 106 - 107 - extension _CBORDecoder.KeyedContainer: KeyedDecodingContainerProtocol { 108 - var allKeys: [Key] { 109 - if let containers = try? self.nestedContainers() { 110 - return containers.keys.map { $0.key() } 111 - } 112 - return [] 113 - } 114 - 115 - func contains(_ key: Key) -> Bool { 116 - if let containers = try? self.nestedContainers() { 117 - return containers.keys.contains(anyCodingKeyForKey(key)) 118 - } 119 - return false 120 - } 121 - 122 - func decodeNil(forKey key: Key) throws -> Bool { 123 - let container = try self.nestedContainers()[anyCodingKeyForKey(key)] 124 - switch container { 125 - case is _CBORDecoder.SingleValueContainer: 126 - return (container as! _CBORDecoder.SingleValueContainer).decodeNil() 127 - case is _CBORDecoder.UnkeyedContainer: 128 - return try (container as! _CBORDecoder.UnkeyedContainer).decodeNil() 129 - case is _CBORDecoder.KeyedContainer<AnyCodingKey>: 130 - return try (container as! _CBORDecoder.KeyedContainer<AnyCodingKey>).decodeNil(forKey: anyCodingKeyForKey(key)) 131 - case nil: 132 - return false 133 - default: 134 - let context = DecodingError.Context(codingPath: self.codingPath, debugDescription: "cannot decode nil for key: \(key)") 135 - throw DecodingError.typeMismatch(Any?.self, context) 136 - } 137 - } 138 - 139 - func decode<T: Decodable>(_ type: T.Type, forKey key: Key) throws -> T { 140 - try checkCanDecodeValue(forKey: key) 141 - 142 - let container = try self.nestedContainers()[anyCodingKeyForKey(key)]! 143 - let decoder = CodableCBORDecoder() 144 - decoder.setOptions(self.options) 145 - return try decoder.decode(T.self, from: container.data) 146 - } 147 - 148 - func nestedUnkeyedContainer(forKey key: Key) throws -> UnkeyedDecodingContainer { 149 - try checkCanDecodeValue(forKey: key) 150 - 151 - guard let unkeyedContainer = try self.nestedContainers()[anyCodingKeyForKey(key)] as? _CBORDecoder.UnkeyedContainer else { 152 - throw DecodingError.dataCorruptedError(forKey: key, in: self, debugDescription: "cannot decode nested container for key: \(key)") 153 - } 154 - 155 - return unkeyedContainer 156 - } 157 - 158 - func nestedContainer<NestedKey: CodingKey>(keyedBy type: NestedKey.Type, forKey key: Key) throws -> KeyedDecodingContainer<NestedKey> { 159 - try checkCanDecodeValue(forKey: key) 160 - 161 - guard let anyCodingKeyedContainer = try self.nestedContainers()[anyCodingKeyForKey(key)] as? _CBORDecoder.KeyedContainer<AnyCodingKey> else { 162 - throw DecodingError.dataCorruptedError(forKey: key, in: self, debugDescription: "cannot decode nested container for key: \(key)") 163 - } 164 - let container = _CBORDecoder.KeyedContainer<NestedKey>( 165 - data: anyCodingKeyedContainer.data, 166 - codingPath: anyCodingKeyedContainer.codingPath, 167 - userInfo: anyCodingKeyedContainer.userInfo, 168 - options: anyCodingKeyedContainer.options 169 - ) 170 - return KeyedDecodingContainer(container) 171 - } 172 - 173 - func superDecoder() throws -> Decoder { 174 - return _CBORDecoder(data: self.data, options: self.options) 175 - } 176 - 177 - func superDecoder(forKey key: Key) throws -> Decoder { 178 - let decoder = _CBORDecoder(data: self.data, options: self.options) 179 - decoder.codingPath = [key] 180 - 181 - return decoder 182 - } 183 - 184 - fileprivate func anyCodingKeyForKey(_ key: Key) -> AnyCodingKey { 185 - return AnyCodingKey(key, useStringKey: self.options.useStringKeys) 186 - } 187 - } 188 - 189 - extension _CBORDecoder.KeyedContainer: CBORDecodingContainer {}
-245
Old/Decoder/SingleValueDecodingContainer.swift
··· 1 - import Foundation 2 - 3 - extension _CBORDecoder { 4 - final class SingleValueContainer { 5 - var codingPath: [CodingKey] 6 - var userInfo: [CodingUserInfoKey: Any] 7 - var data: ArraySlice<UInt8> 8 - var index: Data.Index 9 - let options: CodableCBORDecoder._Options 10 - 11 - init(data: ArraySlice<UInt8>, codingPath: [CodingKey], userInfo: [CodingUserInfoKey : Any], options: CodableCBORDecoder._Options) { 12 - self.codingPath = codingPath 13 - self.userInfo = userInfo 14 - self.data = data 15 - self.index = self.data.startIndex 16 - self.options = options 17 - } 18 - 19 - func checkCanDecode<T>(_ type: T.Type, format: UInt8) throws { 20 - guard self.index <= self.data.endIndex else { 21 - throw DecodingError.dataCorruptedError(in: self, debugDescription: "Unexpected end of data") 22 - } 23 - 24 - guard self.data[self.index] == format else { 25 - let context = DecodingError.Context(codingPath: self.codingPath, debugDescription: "Invalid format: \(format)") 26 - throw DecodingError.typeMismatch(type, context) 27 - } 28 - } 29 - 30 - } 31 - } 32 - 33 - extension _CBORDecoder.SingleValueContainer: SingleValueDecodingContainer { 34 - func decodeNil() -> Bool { 35 - guard let cbor = try? CBOR.decode(self.data.map { $0 }) else { 36 - return false 37 - } 38 - switch cbor { 39 - case .null: return true 40 - default: return false 41 - } 42 - } 43 - 44 - func decode(_ type: Bool.Type) throws -> Bool { 45 - guard let cbor = try? CBOR.decode(self.data.map { $0 }) else { 46 - let context = DecodingError.Context(codingPath: self.codingPath, debugDescription: "Invalid format: \(self.data)") 47 - throw DecodingError.dataCorrupted(context) 48 - } 49 - switch cbor { 50 - case .boolean(let bool): return bool 51 - default: 52 - let context = DecodingError.Context(codingPath: self.codingPath, debugDescription: "Invalid format: \(self.data)") 53 - throw DecodingError.typeMismatch(Bool.self, context) 54 - } 55 - } 56 - 57 - func decode(_ type: String.Type) throws -> String { 58 - guard let cbor = try? CBOR.decode(self.data.map { $0 }) else { 59 - let context = DecodingError.Context(codingPath: self.codingPath, debugDescription: "Invalid format: \(self.data)") 60 - throw DecodingError.dataCorrupted(context) 61 - } 62 - switch cbor { 63 - case .utf8String(let str): return str 64 - default: 65 - let context = DecodingError.Context(codingPath: self.codingPath, debugDescription: "Invalid format: \(self.data)") 66 - throw DecodingError.typeMismatch(String.self, context) 67 - } 68 - } 69 - 70 - func decode(_ type: Double.Type) throws -> Double { 71 - guard let cbor = try? CBOR.decode(self.data.map { $0 }) else { 72 - let context = DecodingError.Context(codingPath: self.codingPath, debugDescription: "Invalid format: \(self.data)") 73 - throw DecodingError.dataCorrupted(context) 74 - } 75 - switch cbor { 76 - case .double(let dbl): return dbl 77 - case .float(let flt): return Double(flt) 78 - case .half(let flt): return Double(flt) 79 - default: 80 - let context = DecodingError.Context(codingPath: self.codingPath, debugDescription: "Invalid format: \(self.data)") 81 - throw DecodingError.typeMismatch(Double.self, context) 82 - } 83 - } 84 - 85 - func decode(_ type: Float.Type) throws -> Float { 86 - guard let cbor = try? CBOR.decode(self.data.map { $0 }) else { 87 - let context = DecodingError.Context(codingPath: self.codingPath, debugDescription: "Invalid format: \(self.data)") 88 - throw DecodingError.dataCorrupted(context) 89 - } 90 - switch cbor { 91 - case .float(let flt): return flt 92 - case .half(let flt): return Float(flt) 93 - default: 94 - let context = DecodingError.Context(codingPath: self.codingPath, debugDescription: "Invalid format: \(self.data)") 95 - throw DecodingError.typeMismatch(Float.self, context) 96 - } 97 - } 98 - 99 - func decode(_ type: Int.Type) throws -> Int { 100 - guard let cbor = try? CBOR.decode(self.data.map { $0 }) else { 101 - let context = DecodingError.Context(codingPath: self.codingPath, debugDescription: "Invalid format: \(self.data)") 102 - throw DecodingError.dataCorrupted(context) 103 - } 104 - switch cbor { 105 - case .unsignedInt(let u64): return Int(u64) 106 - case .negativeInt(let u64): return -1 - Int(u64) 107 - default: 108 - let context = DecodingError.Context(codingPath: self.codingPath, debugDescription: "Invalid format: \(self.data)") 109 - throw DecodingError.typeMismatch(Int.self, context) 110 - } 111 - } 112 - 113 - func decode(_ type: Int8.Type) throws -> Int8 { 114 - guard let cbor = try? CBOR.decode(self.data.map { $0 }) else { 115 - let context = DecodingError.Context(codingPath: self.codingPath, debugDescription: "Invalid format: \(self.data)") 116 - throw DecodingError.dataCorrupted(context) 117 - } 118 - switch cbor { 119 - case .unsignedInt(let u64): return Int8(u64) 120 - case .negativeInt(let u64): return -1 - Int8(u64) 121 - default: 122 - let context = DecodingError.Context(codingPath: self.codingPath, debugDescription: "Invalid format: \(self.data)") 123 - throw DecodingError.typeMismatch(Int8.self, context) 124 - } 125 - } 126 - 127 - func decode(_ type: Int16.Type) throws -> Int16 { 128 - guard let cbor = try? CBOR.decode(self.data.map { $0 }) else { 129 - let context = DecodingError.Context(codingPath: self.codingPath, debugDescription: "Invalid format: \(self.data)") 130 - throw DecodingError.dataCorrupted(context) 131 - } 132 - switch cbor { 133 - case .unsignedInt(let u64): return Int16(u64) 134 - case .negativeInt(let u64): return -1 - Int16(u64) 135 - default: 136 - let context = DecodingError.Context(codingPath: self.codingPath, debugDescription: "Invalid format: \(self.data)") 137 - throw DecodingError.typeMismatch(Int16.self, context) 138 - } 139 - } 140 - 141 - func decode(_ type: Int32.Type) throws -> Int32 { 142 - guard let cbor = try? CBOR.decode(self.data.map { $0 }) else { 143 - let context = DecodingError.Context(codingPath: self.codingPath, debugDescription: "Invalid format: \(self.data)") 144 - throw DecodingError.dataCorrupted(context) 145 - } 146 - switch cbor { 147 - case .unsignedInt(let u64): return Int32(u64) 148 - case .negativeInt(let u64): return -1 - Int32(u64) 149 - default: 150 - let context = DecodingError.Context(codingPath: self.codingPath, debugDescription: "Invalid format: \(self.data)") 151 - throw DecodingError.typeMismatch(Int32.self, context) 152 - } 153 - } 154 - 155 - func decode(_ type: Int64.Type) throws -> Int64 { 156 - guard let cbor = try? CBOR.decode(self.data.map { $0 }) else { 157 - let context = DecodingError.Context(codingPath: self.codingPath, debugDescription: "Invalid format: \(self.data)") 158 - throw DecodingError.dataCorrupted(context) 159 - } 160 - switch cbor { 161 - case .unsignedInt(let u64): return Int64(u64) 162 - case .negativeInt(let u64): return -1 - Int64(u64) 163 - default: 164 - let context = DecodingError.Context(codingPath: self.codingPath, debugDescription: "Invalid format: \(self.data)") 165 - throw DecodingError.typeMismatch(Int64.self, context) 166 - } 167 - } 168 - 169 - func decode(_ type: UInt.Type) throws -> UInt { 170 - guard let cbor = try? CBOR.decode(self.data.map { $0 }) else { 171 - let context = DecodingError.Context(codingPath: self.codingPath, debugDescription: "Invalid format: \(self.data)") 172 - throw DecodingError.dataCorrupted(context) 173 - } 174 - switch cbor { 175 - case .unsignedInt(let u64): return UInt(u64) 176 - default: 177 - let context = DecodingError.Context(codingPath: self.codingPath, debugDescription: "Invalid format: \(self.data)") 178 - throw DecodingError.typeMismatch(UInt.self, context) 179 - } 180 - } 181 - 182 - func decode(_ type: UInt8.Type) throws -> UInt8 { 183 - guard let cbor = try? CBOR.decode(self.data.map { $0 }) else { 184 - let context = DecodingError.Context(codingPath: self.codingPath, debugDescription: "Invalid format: \(self.data)") 185 - throw DecodingError.dataCorrupted(context) 186 - } 187 - switch cbor { 188 - case .unsignedInt(let u64): return UInt8(u64) 189 - default: 190 - let context = DecodingError.Context(codingPath: self.codingPath, debugDescription: "Invalid format: \(self.data)") 191 - throw DecodingError.typeMismatch(UInt8.self, context) 192 - } 193 - } 194 - 195 - func decode(_ type: UInt16.Type) throws -> UInt16 { 196 - guard let cbor = try? CBOR.decode(self.data.map { $0 }) else { 197 - let context = DecodingError.Context(codingPath: self.codingPath, debugDescription: "Invalid format: \(self.data)") 198 - throw DecodingError.dataCorrupted(context) 199 - } 200 - switch cbor { 201 - case .unsignedInt(let u64): return UInt16(u64) 202 - default: 203 - let context = DecodingError.Context(codingPath: self.codingPath, debugDescription: "Invalid format: \(self.data)") 204 - throw DecodingError.typeMismatch(UInt16.self, context) 205 - } 206 - } 207 - 208 - func decode(_ type: UInt32.Type) throws -> UInt32 { 209 - guard let cbor = try? CBOR.decode(self.data.map { $0 }) else { 210 - let context = DecodingError.Context(codingPath: self.codingPath, debugDescription: "Invalid format: \(self.data)") 211 - throw DecodingError.dataCorrupted(context) 212 - } 213 - switch cbor { 214 - case .unsignedInt(let u64): return UInt32(u64) 215 - default: 216 - let context = DecodingError.Context(codingPath: self.codingPath, debugDescription: "Invalid format: \(self.data)") 217 - throw DecodingError.typeMismatch(UInt32.self, context) 218 - } 219 - } 220 - 221 - func decode(_ type: UInt64.Type) throws -> UInt64 { 222 - guard let cbor = try? CBOR.decode(self.data.map { $0 }) else { 223 - let context = DecodingError.Context(codingPath: self.codingPath, debugDescription: "Invalid format: \(self.data)") 224 - throw DecodingError.dataCorrupted(context) 225 - } 226 - switch cbor { 227 - case .unsignedInt(let u64): return u64 228 - default: 229 - let context = DecodingError.Context(codingPath: self.codingPath, debugDescription: "Invalid format: \(self.data)") 230 - throw DecodingError.typeMismatch(UInt64.self, context) 231 - } 232 - } 233 - 234 - func decode<T: Decodable>(_ type: T.Type) throws -> T { 235 - let decoder = _CBORDecoder(data: self.data, options: self.options) 236 - let value = try T(from: decoder) 237 - if let nextIndex = decoder.container?.index { 238 - self.index = nextIndex 239 - } 240 - 241 - return value 242 - } 243 - } 244 - 245 - extension _CBORDecoder.SingleValueContainer: CBORDecodingContainer {}
-310
Old/Decoder/UnkeyedDecodingContainer.swift
··· 1 - import Foundation 2 - 3 - extension _CBORDecoder { 4 - final class UnkeyedContainer { 5 - var codingPath: [CodingKey] 6 - 7 - var nestedCodingPath: [CodingKey] { 8 - return self.codingPath + [AnyCodingKey(intValue: self.count ?? 0)] 9 - } 10 - 11 - var userInfo: [CodingUserInfoKey: Any] 12 - 13 - var data: ArraySlice<UInt8> 14 - var index: Data.Index 15 - 16 - let options: CodableCBORDecoder._Options 17 - 18 - lazy var count: Int? = { 19 - do { 20 - let format = try self.readByte() 21 - switch format { 22 - case 0x80...0x97 : 23 - return Int(format & 0x1F) 24 - case 0x98: 25 - return Int(try read(UInt8.self)) 26 - case 0x99: 27 - return Int(try read(UInt16.self)) 28 - case 0x9a: 29 - return Int(try read(UInt32.self)) 30 - case 0x9b: 31 - return Int(try read(UInt64.self)) 32 - case 0x9f: 33 - // FIXME: This is a very inefficient way of doing this. Really we should be modifying the 34 - // nestedContainers code so that if we're working with an array that has a break at the 35 - // end it creates the containers as it goes, rather than first calculating the count 36 - // (which involves going through all the bytes) and then going back through the data and 37 - // decoding each item in the array. 38 - let nextIndex = self.data.startIndex.advanced(by: 1) 39 - let remainingData = self.data.suffix(from: nextIndex) 40 - return try? CBORDecoder(input: remainingData).readUntilBreak().count 41 - default: 42 - return nil 43 - } 44 - } catch { 45 - return nil 46 - } 47 - }() 48 - 49 - var currentIndex: Int = 0 50 - 51 - lazy var nestedContainers: [CBORDecodingContainer] = { 52 - guard let count = self.count else { 53 - return [] 54 - } 55 - 56 - var nestedContainers: [CBORDecodingContainer] = [] 57 - 58 - do { 59 - for _ in 0..<count { 60 - let container = try self.decodeContainer() 61 - nestedContainers.append(container) 62 - } 63 - } catch { 64 - fatalError("\(error)") // FIXME 65 - } 66 - 67 - self.currentIndex = 0 68 - 69 - return nestedContainers 70 - }() 71 - 72 - init(data: ArraySlice<UInt8>, codingPath: [CodingKey], userInfo: [CodingUserInfoKey : Any], options: CodableCBORDecoder._Options) { 73 - self.codingPath = codingPath 74 - self.userInfo = userInfo 75 - self.data = data 76 - self.index = self.data.startIndex 77 - self.options = options 78 - } 79 - 80 - var isAtEnd: Bool { 81 - guard let count = self.count else { 82 - return true 83 - } 84 - 85 - return currentIndex >= count 86 - } 87 - 88 - var isEmpty: Bool { 89 - if let count = self.count, count == 0 { 90 - return true 91 - } 92 - return false 93 - } 94 - 95 - func checkCanDecodeValue() throws { 96 - guard !self.isAtEnd else { 97 - throw DecodingError.dataCorruptedError(in: self, debugDescription: "Unexpected end of data") 98 - } 99 - } 100 - 101 - } 102 - } 103 - 104 - extension _CBORDecoder.UnkeyedContainer: UnkeyedDecodingContainer { 105 - 106 - func decodeNil() throws -> Bool { 107 - if self.isEmpty { 108 - return false 109 - } 110 - try checkCanDecodeValue() 111 - defer { self.currentIndex += 1 } 112 - 113 - switch self.nestedContainers[self.currentIndex] { 114 - case let singleValueContainer as _CBORDecoder.SingleValueContainer: 115 - return singleValueContainer.decodeNil() 116 - case is _CBORDecoder.UnkeyedContainer, is _CBORDecoder.KeyedContainer<AnyCodingKey>: 117 - return false 118 - default: 119 - let context = DecodingError.Context(codingPath: self.codingPath, debugDescription: "cannot decode nil for index: \(self.currentIndex)") 120 - throw DecodingError.typeMismatch(Any?.self, context) 121 - } 122 - } 123 - 124 - func decode<T: Decodable>(_ type: T.Type) throws -> T { 125 - try checkCanDecodeValue() 126 - defer { self.currentIndex += 1 } 127 - 128 - let container = self.nestedContainers[self.currentIndex] 129 - let decoder = CodableCBORDecoder() 130 - decoder.setOptions(self.options) 131 - let value = try decoder.decode(T.self, from: container.data) 132 - 133 - return value 134 - } 135 - 136 - func nestedUnkeyedContainer() throws -> UnkeyedDecodingContainer { 137 - try checkCanDecodeValue() 138 - defer { self.currentIndex += 1 } 139 - 140 - let container = self.nestedContainers[self.currentIndex] as! _CBORDecoder.UnkeyedContainer 141 - 142 - return container 143 - } 144 - 145 - func nestedContainer<NestedKey: CodingKey>(keyedBy type: NestedKey.Type) throws -> KeyedDecodingContainer<NestedKey> { 146 - try checkCanDecodeValue() 147 - defer { self.currentIndex += 1 } 148 - 149 - let anyCodingKeyContainer = self.nestedContainers[self.currentIndex] as! _CBORDecoder.KeyedContainer<AnyCodingKey> 150 - 151 - let container = _CBORDecoder.KeyedContainer<NestedKey>( 152 - data: anyCodingKeyContainer.data, 153 - codingPath: anyCodingKeyContainer.codingPath, 154 - userInfo: anyCodingKeyContainer.userInfo, 155 - options: anyCodingKeyContainer.options 156 - ) 157 - return KeyedDecodingContainer(container) 158 - } 159 - 160 - func superDecoder() throws -> Decoder { 161 - return _CBORDecoder(data: self.data, options: self.options) 162 - } 163 - } 164 - 165 - extension _CBORDecoder.UnkeyedContainer { 166 - func decodeContainer() throws -> CBORDecodingContainer { 167 - try checkCanDecodeValue() 168 - defer { self.currentIndex += 1 } 169 - 170 - let startIndex = self.index 171 - 172 - let length: Int 173 - let format = try self.readByte() 174 - 175 - switch format { 176 - // Integers 177 - case 0x00...0x1b, 0x20...0x3b: 178 - length = try getLengthOfItem(format: format, startIndex: startIndex) 179 - // Byte strings 180 - case 0x40...0x5b: 181 - length = try getLengthOfItem(format: format, startIndex: startIndex) 182 - // Terminated by break 183 - case 0x5f: 184 - // TODO: Is this ever going to get hit? 185 - throw DecodingError.dataCorruptedError(in: self, debugDescription: "Handling byte strings with break bytes is not supported yet") 186 - // UTF8 strings 187 - case 0x60...0x7b: 188 - length = try getLengthOfItem(format: format, startIndex: startIndex) 189 - // Terminated by break 190 - case 0x7f: 191 - // FIXME 192 - throw DecodingError.dataCorruptedError(in: self, debugDescription: "Handling UTF8 strings with break bytes is not supported yet") 193 - // Arrays 194 - case 0x80...0x9f: 195 - let container = _CBORDecoder.UnkeyedContainer(data: self.data.suffix(from: startIndex), codingPath: self.nestedCodingPath, userInfo: self.userInfo, options: self.options) 196 - _ = container.nestedContainers 197 - 198 - self.index = container.index 199 - // Ensure that we're moving the index along for indefinite arrays so 200 - // that we don't try and decode the break byte (0xff) 201 - if format == 0x9f { 202 - if self.data.suffix(from: self.index).count > 0 { 203 - self.index = self.index.advanced(by: 1) 204 - } 205 - } 206 - return container 207 - // Maps 208 - case 0xa0...0xbf: 209 - let container = _CBORDecoder.KeyedContainer<AnyCodingKey>(data: self.data.suffix(from: startIndex), codingPath: self.nestedCodingPath, userInfo: self.userInfo, options: self.options) 210 - let _ = try container.nestedContainers() // FIXME 211 - 212 - self.index = container.index 213 - // Ensure that we're moving the index along for indefinite arrays so 214 - // that we don't try and decode the break byte (0xff) 215 - if format == 0xbf { 216 - if self.data.suffix(from: self.index).count > 0 { 217 - self.index = self.index.advanced(by: 1) 218 - } 219 - } 220 - return container 221 - case 0xc0: 222 - throw DecodingError.dataCorruptedError(in: self, debugDescription: "Handling text-based date/time is not supported yet") 223 - // Tagged value (epoch-baed date/time) 224 - case 0xc1: 225 - length = try getLengthOfItem(format: try self.peekByte(), startIndex: startIndex.advanced(by: 1)) + 1 226 - case 0xc2...0xdb: 227 - // FIXME 228 - throw DecodingError.dataCorruptedError(in: self, debugDescription: "Handling tags (other than epoch-based date/time) is not supported yet") 229 - case 0xe0...0xfb, 0xff: 230 - length = try getLengthOfItem(format: format, startIndex: startIndex.advanced(by: 1)) 231 - default: 232 - throw DecodingError.dataCorruptedError(in: self, debugDescription: "Invalid format: \(format)") 233 - } 234 - 235 - let range: Range<Data.Index> = startIndex..<self.index.advanced(by: length) 236 - self.index = range.upperBound 237 - 238 - let container = _CBORDecoder.SingleValueContainer(data: self.data[range.startIndex..<(range.endIndex)], codingPath: self.codingPath, userInfo: self.userInfo, options: self.options) 239 - 240 - return container 241 - } 242 - 243 - func getLengthOfItem(format: UInt8, startIndex: Data.Index) throws -> Int { 244 - switch format { 245 - // Integers 246 - // Small positive and negative integers 247 - case 0x00...0x17, 0x20...0x37: 248 - return 0 249 - // UInt8 in following byte 250 - case 0x18, 0x38: 251 - return 1 252 - // UInt16 in following bytes 253 - case 0x19, 0x39: 254 - return 2 255 - // UInt32 in following bytes 256 - case 0x1a, 0x3a: 257 - return 4 258 - // UInt64 in following bytes 259 - case 0x1b, 0x3b: 260 - return 8 261 - // Byte strings 262 - case 0x40...0x57: 263 - return try CBORDecoder(input: [0]).readLength(format, base: 0x40) 264 - case 0x58: 265 - let remainingData = self.data.suffix(from: startIndex.advanced(by: 1)) 266 - return try CBORDecoder(input: remainingData).readLength(format, base: 0x40) + 1 267 - case 0x59: 268 - let remainingData = self.data.suffix(from: startIndex.advanced(by: 1)) 269 - return try CBORDecoder(input: remainingData).readLength(format, base: 0x40) + 2 270 - case 0x5a: 271 - let remainingData = self.data.suffix(from: startIndex.advanced(by: 1)) 272 - return try CBORDecoder(input: remainingData).readLength(format, base: 0x40) + 4 273 - case 0x5b: 274 - let remainingData = self.data.suffix(from: startIndex.advanced(by: 1)) 275 - return try CBORDecoder(input: remainingData).readLength(format, base: 0x40) + 8 276 - // UTF8 strings 277 - case 0x60...0x77: 278 - return try CBORDecoder(input: [0]).readLength(format, base: 0x60) 279 - case 0x78: 280 - let remainingData = self.data.suffix(from: startIndex.advanced(by: 1)) 281 - return try CBORDecoder(input: remainingData).readLength(format, base: 0x60) + 1 282 - case 0x79: 283 - let remainingData = self.data.suffix(from: startIndex.advanced(by: 1)) 284 - return try CBORDecoder(input: remainingData).readLength(format, base: 0x60) + 2 285 - case 0x7a: 286 - let remainingData = self.data.suffix(from: startIndex.advanced(by: 1)) 287 - return try CBORDecoder(input: remainingData).readLength(format, base: 0x60) + 4 288 - case 0x7b: 289 - let remainingData = self.data.suffix(from: startIndex.advanced(by: 1)) 290 - return try CBORDecoder(input: remainingData).readLength(format, base: 0x60) + 8 291 - case 0xe0...0xf3: 292 - return 0 293 - case 0xf4, 0xf5, 0xf6, 0xf7, 0xf8: 294 - return 0 295 - case 0xf9: 296 - return 2 297 - case 0xfa: 298 - return 4 299 - case 0xfb: 300 - return 8 301 - case 0xff: 302 - return 0 303 - default: 304 - throw DecodingError.dataCorruptedError(in: self, debugDescription: "Invalid format for getting length of item: \(format)") 305 - } 306 - 307 - } 308 - } 309 - 310 - extension _CBORDecoder.UnkeyedContainer: CBORDecodingContainer {}
-131
Old/Encoder/CodableCBOREncoder.swift
··· 1 - import Foundation 2 - 3 - public class CodableCBOREncoder { 4 - public var useStringKeys: Bool = false 5 - public var dateStrategy: DateStrategy = .taggedAsEpochTimestamp 6 - public var forbidNonStringMapKeys: Bool = false 7 - public var orderKeys: Bool = false 8 - 9 - struct _Options { 10 - let useStringKeys: Bool 11 - let dateStrategy: DateStrategy 12 - let forbidNonStringMapKeys: Bool 13 - let orderKeys: Bool 14 - 15 - init( 16 - useStringKeys: Bool = false, 17 - dateStrategy: DateStrategy = .taggedAsEpochTimestamp, 18 - forbidNonStringMapKeys: Bool = false, 19 - orderKeys: Bool = false 20 - ) { 21 - self.useStringKeys = useStringKeys 22 - self.dateStrategy = dateStrategy 23 - self.forbidNonStringMapKeys = forbidNonStringMapKeys 24 - self.orderKeys = orderKeys 25 - } 26 - 27 - func toCBOROptions() -> CBOROptions { 28 - return CBOROptions( 29 - useStringKeys: self.useStringKeys, 30 - dateStrategy: self.dateStrategy, 31 - forbidNonStringMapKeys: self.forbidNonStringMapKeys 32 - ) 33 - } 34 - } 35 - 36 - var options: _Options { 37 - get { 38 - _Options( 39 - useStringKeys: self.useStringKeys, 40 - dateStrategy: self.dateStrategy, 41 - forbidNonStringMapKeys: self.forbidNonStringMapKeys, 42 - orderKeys: self.orderKeys 43 - ) 44 - } 45 - set { 46 - self.useStringKeys = newValue.useStringKeys 47 - self.dateStrategy = newValue.dateStrategy 48 - self.forbidNonStringMapKeys = newValue.forbidNonStringMapKeys 49 - } 50 - } 51 - 52 - public init() {} 53 - 54 - public func encode(_ value: Encodable) throws -> Data { 55 - let encoder = _CBOREncoder(options: self.options) 56 - if let dateVal = value as? Date { 57 - return Data(CBOR.encodeDate(dateVal, options: self.options.toCBOROptions())) 58 - } else if let dataVal = value as? Data { 59 - return Data(CBOR.encodeData(dataVal, options: self.options.toCBOROptions())) 60 - } 61 - if options.forbidNonStringMapKeys { 62 - if let dict = value as? Dictionary<AnyHashable, Any?> { 63 - guard let _ = dict as? Dictionary<String, Any?> else { 64 - throw CBOREncoderError.nonStringKeyInMap 65 - } 66 - } 67 - } 68 - 69 - try value.encode(to: encoder) 70 - return try encoder.data() 71 - } 72 - } 73 - 74 - final class _CBOREncoder { 75 - var codingPath: [CodingKey] = [] 76 - 77 - var userInfo: [CodingUserInfoKey : Any] = [:] 78 - 79 - fileprivate var container: CBOREncodingContainer? { 80 - willSet { 81 - precondition(self.container == nil) 82 - } 83 - } 84 - 85 - func data() throws -> Data { 86 - try container?.data() ?? Data() 87 - } 88 - 89 - let options: CodableCBOREncoder._Options 90 - 91 - init(options: CodableCBOREncoder._Options = CodableCBOREncoder._Options()) { 92 - self.options = options 93 - } 94 - } 95 - 96 - extension _CBOREncoder: Encoder { 97 - fileprivate func assertCanCreateContainer() { 98 - precondition(self.container == nil) 99 - } 100 - 101 - func container<Key: CodingKey>(keyedBy type: Key.Type) -> KeyedEncodingContainer<Key> { 102 - assertCanCreateContainer() 103 - 104 - let container = KeyedContainer<Key>(codingPath: self.codingPath, userInfo: self.userInfo, options: self.options) 105 - self.container = container 106 - 107 - return KeyedEncodingContainer(container) 108 - } 109 - 110 - func unkeyedContainer() -> UnkeyedEncodingContainer { 111 - assertCanCreateContainer() 112 - 113 - let container = UnkeyedContainer(codingPath: self.codingPath, userInfo: self.userInfo, options: self.options) 114 - self.container = container 115 - 116 - return container 117 - } 118 - 119 - func singleValueContainer() -> SingleValueEncodingContainer { 120 - assertCanCreateContainer() 121 - 122 - let container = SingleValueContainer(codingPath: self.codingPath, userInfo: self.userInfo, options: self.options) 123 - self.container = container 124 - 125 - return container 126 - } 127 - } 128 - 129 - protocol CBOREncodingContainer: AnyObject { 130 - func data() throws -> Data 131 - }
-124
Old/Encoder/KeyedEncodingContainer.swift
··· 1 - import Foundation 2 - import HeapModule 3 - 4 - extension _CBOREncoder { 5 - final class KeyedContainer<Key: CodingKey> { 6 - struct StorageItem: Comparable { 7 - let key: AnyCodingKey 8 - let value: CBOREncodingContainer 9 - 10 - static func < (lhs: StorageItem, rhs: StorageItem) -> Bool { 11 - lhs.key.stringValue < rhs.key.stringValue 12 - } 13 - 14 - static func == (lhs: StorageItem, rhs: StorageItem) -> Bool { 15 - lhs.key.stringValue == rhs.key.stringValue 16 - } 17 - } 18 - 19 - var storage: Heap<StorageItem> = [] 20 - 21 - var codingPath: [CodingKey] 22 - var userInfo: [CodingUserInfoKey: Any] 23 - 24 - let options: CodableCBOREncoder._Options 25 - 26 - init(codingPath: [CodingKey], userInfo: [CodingUserInfoKey : Any], options: CodableCBOREncoder._Options) { 27 - self.codingPath = codingPath 28 - self.userInfo = userInfo 29 - self.options = options 30 - } 31 - } 32 - } 33 - 34 - extension _CBOREncoder.KeyedContainer: KeyedEncodingContainerProtocol { 35 - func encodeNil(forKey key: Key) throws { 36 - var container = self.nestedSingleValueContainer(forKey: key) 37 - try container.encodeNil() 38 - } 39 - 40 - func encode<T: Encodable>(_ value: T, forKey key: Key) throws { 41 - var container = self.nestedSingleValueContainer(forKey: key) 42 - try container.encode(value) 43 - } 44 - 45 - private func nestedCodingPath(forKey key: CodingKey) -> [CodingKey] { 46 - return self.codingPath + [key] 47 - } 48 - 49 - private func nestedSingleValueContainer(forKey key: Key) -> SingleValueEncodingContainer { 50 - let container = _CBOREncoder.SingleValueContainer( 51 - codingPath: self.nestedCodingPath(forKey: key), 52 - userInfo: self.userInfo, 53 - options: self.options 54 - ) 55 - self.storage.insert(storageItem(forKey: key, container: container)) 56 - return container 57 - } 58 - 59 - func nestedUnkeyedContainer(forKey key: Key) -> UnkeyedEncodingContainer { 60 - let container = _CBOREncoder.UnkeyedContainer( 61 - codingPath: self.nestedCodingPath(forKey: key), 62 - userInfo: self.userInfo, 63 - options: self.options 64 - ) 65 - self.storage.insert(storageItem(forKey: key, container: container)) 66 - return container 67 - } 68 - 69 - func nestedContainer<NestedKey: CodingKey>(keyedBy keyType: NestedKey.Type, forKey key: Key) -> KeyedEncodingContainer<NestedKey> { 70 - let container = _CBOREncoder.KeyedContainer<NestedKey>( 71 - codingPath: self.nestedCodingPath(forKey: key), 72 - userInfo: self.userInfo, 73 - options: self.options 74 - ) 75 - self.storage.insert(storageItem(forKey: key, container: container)) 76 - return KeyedEncodingContainer(container) 77 - } 78 - 79 - fileprivate func storageItem(forKey key: Key, container: CBOREncodingContainer) -> StorageItem { 80 - StorageItem( 81 - key: AnyCodingKey(key, useStringKey: self.options.useStringKeys), 82 - value: container 83 - ) 84 - } 85 - 86 - func superEncoder() -> Encoder { 87 - fatalError("Unimplemented") // FIXME 88 - } 89 - 90 - func superEncoder(forKey key: Key) -> Encoder { 91 - fatalError("Unimplemented") // FIXME 92 - } 93 - } 94 - 95 - extension _CBOREncoder.KeyedContainer: CBOREncodingContainer { 96 - func data() throws -> Data { 97 - var data = Data() 98 - data.append(0b101_00000) // Blank count for now 99 - var foundKeys: Set<String> = [] 100 - 101 - while let item = storage.popMin() { 102 - let key = item.key 103 - let container = item.value 104 - 105 - guard !foundKeys.contains(key.stringValue) else { continue } 106 - foundKeys.insert(key.stringValue) 107 - 108 - let keyContainer = _CBOREncoder.SingleValueContainer(codingPath: self.codingPath, userInfo: self.userInfo, options: self.options) 109 - try keyContainer.encode(key) 110 - data.append(contentsOf: try keyContainer.data()) 111 - data.append(contentsOf: try container.data()) 112 - 113 - } 114 - 115 - if foundKeys.count >= 31 { 116 - data[0] = data[0] | UInt8(0b11111) // >= 31 keys means we've broken the maximum size 117 - data.append(0xFF) // 32, the BREAK code to end the indeterminate mep length. 118 - } else { 119 - data[0] = data[0] | UInt8(foundKeys.count) 120 - } 121 - 122 - return Data(data) 123 - } 124 - }
-169
Old/Encoder/SingleValueEncodingContainer.swift
··· 1 - import Foundation 2 - 3 - extension _CBOREncoder { 4 - final class SingleValueContainer { 5 - private var storage: Data = Data() 6 - 7 - fileprivate var canEncodeNewValue = true 8 - fileprivate func checkCanEncode(value: Any?) throws { 9 - guard self.canEncodeNewValue else { 10 - let context = EncodingError.Context(codingPath: self.codingPath, debugDescription: "Attempt to encode value through single value container when previously value already encoded.") 11 - throw EncodingError.invalidValue(value as Any, context) 12 - } 13 - } 14 - 15 - var codingPath: [CodingKey] 16 - var userInfo: [CodingUserInfoKey: Any] 17 - 18 - let options: CodableCBOREncoder._Options 19 - 20 - init(codingPath: [CodingKey], userInfo: [CodingUserInfoKey : Any], options: CodableCBOREncoder._Options) { 21 - self.codingPath = codingPath 22 - self.userInfo = userInfo 23 - self.options = options 24 - } 25 - } 26 - } 27 - 28 - extension _CBOREncoder.SingleValueContainer: SingleValueEncodingContainer { 29 - func encodeNil() throws { 30 - try checkCanEncode(value: nil) 31 - defer { self.canEncodeNewValue = false } 32 - 33 - self.storage.append(contentsOf: CBOR.encodeNull()) 34 - } 35 - 36 - func encode(_ value: Bool) throws { 37 - try checkCanEncode(value: value) 38 - defer { self.canEncodeNewValue = false } 39 - 40 - self.storage.append(contentsOf: CBOR.encodeBool(value)) 41 - } 42 - 43 - func encode(_ value: String) throws { 44 - try checkCanEncode(value: value) 45 - defer { self.canEncodeNewValue = false } 46 - 47 - self.storage.append(contentsOf: CBOR.encodeString(value, options: self.options.toCBOROptions())) 48 - } 49 - 50 - func encode(_ value: Double) throws { 51 - try checkCanEncode(value: value) 52 - defer { self.canEncodeNewValue = false } 53 - 54 - self.storage.append(contentsOf: CBOR.encodeDouble(value)) 55 - } 56 - 57 - func encode(_ value: Float) throws { 58 - try checkCanEncode(value: value) 59 - defer { self.canEncodeNewValue = false } 60 - 61 - self.storage.append(contentsOf: CBOR.encodeFloat(value)) 62 - } 63 - 64 - func encode(_ value: Int) throws { 65 - try checkCanEncode(value: value) 66 - defer { self.canEncodeNewValue = false } 67 - 68 - self.storage.append(contentsOf: CBOR.encode(value)) 69 - } 70 - 71 - func encode(_ value: Int8) throws { 72 - try checkCanEncode(value: value) 73 - defer { self.canEncodeNewValue = false } 74 - 75 - self.storage.append(contentsOf: CBOR.encode(Int(value))) 76 - } 77 - 78 - func encode(_ value: Int16) throws { 79 - try checkCanEncode(value: value) 80 - defer { self.canEncodeNewValue = false } 81 - 82 - self.storage.append(contentsOf: CBOR.encode(Int(value))) 83 - } 84 - 85 - func encode(_ value: Int32) throws { 86 - try checkCanEncode(value: value) 87 - defer { self.canEncodeNewValue = false } 88 - 89 - self.storage.append(contentsOf: CBOR.encode(Int(value))) 90 - } 91 - 92 - func encode(_ value: Int64) throws { 93 - try checkCanEncode(value: value) 94 - defer { self.canEncodeNewValue = false } 95 - 96 - self.storage.append(contentsOf: CBOR.encode(Int(value))) 97 - } 98 - 99 - func encode(_ value: UInt) throws { 100 - try checkCanEncode(value: value) 101 - defer { self.canEncodeNewValue = false } 102 - 103 - self.storage.append(contentsOf: CBOR.encode(value)) 104 - } 105 - 106 - func encode(_ value: UInt8) throws { 107 - try checkCanEncode(value: value) 108 - defer { self.canEncodeNewValue = false } 109 - 110 - self.storage.append(contentsOf: CBOR.encode(value)) 111 - } 112 - 113 - func encode(_ value: UInt16) throws { 114 - try checkCanEncode(value: value) 115 - defer { self.canEncodeNewValue = false } 116 - 117 - self.storage.append(contentsOf: CBOR.encode(value)) 118 - } 119 - 120 - func encode(_ value: UInt32) throws { 121 - try checkCanEncode(value: value) 122 - defer { self.canEncodeNewValue = false } 123 - 124 - self.storage.append(contentsOf: CBOR.encode(value)) 125 - } 126 - 127 - func encode(_ value: UInt64) throws { 128 - try checkCanEncode(value: value) 129 - defer { self.canEncodeNewValue = false } 130 - 131 - self.storage.append(contentsOf: CBOR.encode(value)) 132 - } 133 - 134 - func encodeDate(_ value: Date) throws { 135 - try checkCanEncode(value: value) 136 - defer { self.canEncodeNewValue = false } 137 - 138 - self.storage.append(contentsOf: CBOR.encodeDate(value, options: self.options.toCBOROptions())) 139 - } 140 - 141 - func encodeData(_ value: Data) throws { 142 - try checkCanEncode(value: value) 143 - defer { self.canEncodeNewValue = false } 144 - 145 - self.storage.append(contentsOf: CBOR.encodeData(value, options: self.options.toCBOROptions())) 146 - } 147 - 148 - func encode<T: Encodable>(_ value: T) throws { 149 - try checkCanEncode(value: value) 150 - defer { self.canEncodeNewValue = false } 151 - 152 - switch value { 153 - case let data as Data: 154 - try self.encodeData(data) 155 - case let date as Date: 156 - try self.encodeDate(date) 157 - default: 158 - let encoder = _CBOREncoder(options: self.options) 159 - try value.encode(to: encoder) 160 - self.storage.append(try encoder.data()) 161 - } 162 - } 163 - } 164 - 165 - extension _CBOREncoder.SingleValueContainer: CBOREncodingContainer { 166 - func data() throws -> Data { 167 - return storage 168 - } 169 - }
-85
Old/Encoder/UnkeyedEncodingContainer.swift
··· 1 - import Foundation 2 - 3 - extension _CBOREncoder { 4 - final class UnkeyedContainer { 5 - private var storage: [CBOREncodingContainer] = [] 6 - 7 - var count: Int { 8 - return storage.count 9 - } 10 - 11 - var codingPath: [CodingKey] 12 - 13 - var nestedCodingPath: [CodingKey] { 14 - return self.codingPath + [AnyCodingKey(intValue: self.count)] 15 - } 16 - 17 - var userInfo: [CodingUserInfoKey: Any] 18 - 19 - let options: CodableCBOREncoder._Options 20 - 21 - init(codingPath: [CodingKey], userInfo: [CodingUserInfoKey : Any], options: CodableCBOREncoder._Options) { 22 - self.codingPath = codingPath 23 - self.userInfo = userInfo 24 - self.options = options 25 - } 26 - } 27 - } 28 - 29 - extension _CBOREncoder.UnkeyedContainer: UnkeyedEncodingContainer { 30 - func encodeNil() throws { 31 - var container = self.nestedSingleValueContainer() 32 - try container.encodeNil() 33 - } 34 - 35 - func encode<T: Encodable>(_ value: T) throws { 36 - var container = self.nestedSingleValueContainer() 37 - try container.encode(value) 38 - } 39 - 40 - private func nestedSingleValueContainer() -> SingleValueEncodingContainer { 41 - let container = _CBOREncoder.SingleValueContainer(codingPath: self.nestedCodingPath, userInfo: self.userInfo, options: self.options) 42 - self.storage.append(container) 43 - 44 - return container 45 - } 46 - 47 - func nestedContainer<NestedKey: CodingKey>(keyedBy keyType: NestedKey.Type) -> KeyedEncodingContainer<NestedKey> { 48 - let container = _CBOREncoder.KeyedContainer<NestedKey>(codingPath: self.nestedCodingPath, userInfo: self.userInfo, options: self.options) 49 - self.storage.append(container) 50 - 51 - return KeyedEncodingContainer(container) 52 - } 53 - 54 - func nestedUnkeyedContainer() -> UnkeyedEncodingContainer { 55 - let container = _CBOREncoder.UnkeyedContainer(codingPath: self.nestedCodingPath, userInfo: self.userInfo, options: self.options) 56 - self.storage.append(container) 57 - 58 - return container 59 - } 60 - 61 - func superEncoder() -> Encoder { 62 - fatalError("Unimplemented") // FIXME 63 - } 64 - } 65 - 66 - extension _CBOREncoder.UnkeyedContainer: CBOREncodingContainer { 67 - func data() throws -> Data { 68 - var data = Data() 69 - if storage.count >= 31 { 70 - data.append(0b100_11111) // array tag + indefinite count 71 - } else { 72 - data.append(0b100_00000 | UInt8(storage.count)) // array tag + count 73 - } 74 - 75 - for container in storage { 76 - data.append(contentsOf: try container.data()) 77 - } 78 - 79 - if storage.count >= 31 { 80 - data.append(0xFF) // 32, the BREAK code to end the indeterminate array length. 81 - } 82 - 83 - return Data(data) 84 - } 85 - }
-19
Old/FixedWidthInteger+Bytes.swift
··· 1 - extension FixedWidthInteger { 2 - init(bytes: [UInt8]) { 3 - self = bytes.withUnsafeBufferPointer { 4 - $0.baseAddress!.withMemoryRebound(to: Self.self, capacity: 1) { 5 - $0.pointee 6 - } 7 - }.bigEndian 8 - } 9 - 10 - var bytes: [UInt8] { 11 - let capacity = MemoryLayout<Self>.size 12 - var mutableValue = self.bigEndian 13 - return withUnsafePointer(to: &mutableValue) { 14 - return $0.withMemoryRebound(to: UInt8.self, capacity: capacity) { 15 - return Array(UnsafeBufferPointer(start: $0, count: capacity)) 16 - } 17 - } 18 - } 19 - }
-555
Old/SwiftCBORTests-old/CBORCodableRoundtripTests.swift
··· 1 - import XCTest 2 - import Foundation 3 - @testable import SwiftCBOR 4 - 5 - class CBORCodableRoundtripTests: XCTestCase { 6 - struct MyStruct: Codable, Equatable, Hashable { 7 - let age: Int 8 - let name: String 9 - } 10 - 11 - func testSimpleStruct() { 12 - let encoded = try! CodableCBOREncoder().encode(MyStruct(age: 27, name: "Ham")) 13 - let decoded = try! CodableCBORDecoder().decode(MyStruct.self, from: encoded) 14 - XCTAssertEqual(decoded, MyStruct(age: 27, name: "Ham")) 15 - } 16 - 17 - func testSimpleStructsInArray() { 18 - let encoded = try! CodableCBOREncoder().encode([ 19 - MyStruct(age: 27, name: "Ham"), 20 - MyStruct(age: 24, name: "Greg") 21 - ]) 22 - let decoded = try! CodableCBORDecoder().decode([MyStruct].self, from: encoded) 23 - XCTAssertEqual(decoded, [MyStruct(age: 27, name: "Ham"), MyStruct(age: 24, name: "Greg")]) 24 - } 25 - 26 - func testSimpleStructsAsValuesInMap() { 27 - let encoded = try! CodableCBOREncoder().encode([ 28 - "Ham": MyStruct(age: 27, name: "Ham"), 29 - "Greg": MyStruct(age: 24, name: "Greg") 30 - ]) 31 - let decoded = try! CodableCBORDecoder().decode([String: MyStruct].self, from: encoded) 32 - XCTAssertEqual( 33 - decoded, 34 - [ 35 - "Ham": MyStruct(age: 27, name: "Ham"), 36 - "Greg": MyStruct(age: 24, name: "Greg") 37 - ] 38 - ) 39 - } 40 - 41 - func testSimpleStructsAsKeysInMap() { 42 - let encoded = try! CodableCBOREncoder().encode([ 43 - MyStruct(age: 27, name: "Ham"): "Ham", 44 - MyStruct(age: 24, name: "Greg"): "Greg" 45 - ]) 46 - let decoded = try! CodableCBORDecoder().decode([MyStruct: String].self, from: encoded) 47 - XCTAssertEqual( 48 - decoded, 49 - [ 50 - MyStruct(age: 27, name: "Ham"): "Ham", 51 - MyStruct(age: 24, name: "Greg"): "Greg" 52 - ] 53 - ) 54 - } 55 - 56 - func testNil() { 57 - let nilValue = try! CodableCBOREncoder().encode(Optional<String>(nil)) 58 - let nilDecoded = try! CodableCBORDecoder().decode(Optional<String>.self, from: nilValue) 59 - XCTAssertNil(nilDecoded) 60 - } 61 - 62 - func testBools() { 63 - let falseVal = try! CodableCBOREncoder().encode(false) 64 - let falseValDecoded = try! CodableCBORDecoder().decode(Bool.self, from: falseVal) 65 - XCTAssertFalse(falseValDecoded) 66 - let trueVal = try! CodableCBOREncoder().encode(true) 67 - let trueValDecoded = try! CodableCBORDecoder().decode(Bool.self, from: trueVal) 68 - XCTAssertTrue(trueValDecoded) 69 - } 70 - 71 - func testInts() { 72 - // Less than 24 73 - let zero = try! CodableCBOREncoder().encode(0) 74 - let zeroDecoded = try! CodableCBORDecoder().decode(Int.self, from: zero) 75 - XCTAssertEqual(zeroDecoded, 0) 76 - let eight = try! CodableCBOREncoder().encode(8) 77 - let eightDecoded = try! CodableCBORDecoder().decode(Int.self, from: eight) 78 - XCTAssertEqual(eightDecoded, 8) 79 - let ten = try! CodableCBOREncoder().encode(10) 80 - let tenDecoded = try! CodableCBORDecoder().decode(Int.self, from: ten) 81 - XCTAssertEqual(tenDecoded, 10) 82 - let twentyThree = try! CodableCBOREncoder().encode(23) 83 - let twentyThreeDecoded = try! CodableCBORDecoder().decode(Int.self, from: twentyThree) 84 - XCTAssertEqual(twentyThreeDecoded, 23) 85 - 86 - // Just bigger than 23 87 - let twentyFour = try! CodableCBOREncoder().encode(24) 88 - let twentyFourDecoded = try! CodableCBORDecoder().decode(Int.self, from: twentyFour) 89 - XCTAssertEqual(twentyFourDecoded, 24) 90 - let twentyFive = try! CodableCBOREncoder().encode(25) 91 - let twentyFiveDecoded = try! CodableCBORDecoder().decode(Int.self, from: twentyFive) 92 - XCTAssertEqual(twentyFiveDecoded, 25) 93 - 94 - // Bigger 95 - let hundred = try! CodableCBOREncoder().encode(100) 96 - let hundredDecoded = try! CodableCBORDecoder().decode(Int.self, from: hundred) 97 - XCTAssertEqual(hundredDecoded, 100) 98 - let thousand = try! CodableCBOREncoder().encode(1_000) 99 - let thousandDecoded = try! CodableCBORDecoder().decode(Int.self, from: thousand) 100 - XCTAssertEqual(thousandDecoded, 1_000) 101 - let million = try! CodableCBOREncoder().encode(1_000_000) 102 - let millionDecoded = try! CodableCBORDecoder().decode(Int.self, from: million) 103 - XCTAssertEqual(millionDecoded, 1_000_000) 104 - let trillion = try! CodableCBOREncoder().encode(1_000_000_000_000) 105 - let trillionDecoded = try! CodableCBORDecoder().decode(Int.self, from: trillion) 106 - XCTAssertEqual(trillionDecoded, 1_000_000_000_000) 107 - 108 - // TODO: Tagged byte strings for big numbers 109 - // let bigNum = try! CodableCBORDecoder().decode(Int.self, from: Data([0x1b, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff])) 110 - // XCTAssertEqual(bigNum, 18_446_744_073_709_551_615) 111 - // let biggerNum = try! CodableCBORDecoder().decode(Int.self, from: Data([0x2c, 0x49, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,])) 112 - // XCTAssertEqual(biggerNum, 18_446_744_073_709_551_616) 113 - } 114 - 115 - func testNegativeInts() { 116 - // Less than 24 117 - let minusOne = try! CodableCBOREncoder().encode(-1) 118 - let minusOneDecoded = try! CodableCBORDecoder().decode(Int.self, from: minusOne) 119 - XCTAssertEqual(minusOneDecoded, -1) 120 - let minusTen = try! CodableCBOREncoder().encode(-10) 121 - let minusTenDecoded = try! CodableCBORDecoder().decode(Int.self, from: minusTen) 122 - XCTAssertEqual(minusTenDecoded, -10) 123 - 124 - // Bigger 125 - let minusHundred = try! CodableCBOREncoder().encode(-100) 126 - let minusHundredDecoded = try! CodableCBORDecoder().decode(Int.self, from: minusHundred) 127 - XCTAssertEqual(minusHundredDecoded, -100) 128 - let minusThousand = try! CodableCBOREncoder().encode(-1_000) 129 - let minusThousandDecoded = try! CodableCBORDecoder().decode(Int.self, from: minusThousand) 130 - XCTAssertEqual(minusThousandDecoded, -1_000) 131 - 132 - // TODO: Tagged byte strings for big numbers 133 - // let bigNum = try! CodableCBORDecoder().decode(Int.self, from: Data([0x1b, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff])) 134 - // XCTAssertEqual(bigNum, 18_446_744_073_709_551_615) 135 - // let biggerNum = try! CodableCBORDecoder().decode(Int.self, from: Data([0x2c, 0x49, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,])) 136 - // XCTAssertEqual(biggerNum, 18_446_744_073_709_551_616) 137 - } 138 - 139 - func testStrings() { 140 - let empty = try! CodableCBOREncoder().encode("") 141 - let emptyDecoded = try! CodableCBORDecoder().decode(String.self, from: empty) 142 - XCTAssertEqual(emptyDecoded, "") 143 - let a = try! CodableCBOREncoder().encode("a") 144 - let aDecoded = try! CodableCBORDecoder().decode(String.self, from: a) 145 - XCTAssertEqual(aDecoded, "a") 146 - let IETF = try! CodableCBOREncoder().encode("IETF") 147 - let IETFDecoded = try! CodableCBORDecoder().decode(String.self, from: IETF) 148 - XCTAssertEqual(IETFDecoded, "IETF") 149 - let quoteSlash = try! CodableCBOREncoder().encode("\"\\") 150 - let quoteSlashDecoded = try! CodableCBORDecoder().decode(String.self, from: quoteSlash) 151 - XCTAssertEqual(quoteSlashDecoded, "\"\\") 152 - let littleUWithDiaeresis = try! CodableCBOREncoder().encode("\u{00FC}") 153 - let littleUWithDiaeresisDecoded = try! CodableCBORDecoder().decode(String.self, from: littleUWithDiaeresis) 154 - XCTAssertEqual(littleUWithDiaeresisDecoded, "\u{00FC}") 155 - } 156 - 157 - func testArrays() { 158 - let empty = try! CodableCBOREncoder().encode([String]()) 159 - let emptyDecoded = try! CodableCBORDecoder().decode([String].self, from: empty) 160 - XCTAssertEqual(emptyDecoded, []) 161 - let oneTwoThree = try! CodableCBOREncoder().encode([1, 2, 3]) 162 - let oneTwoThreeDecoded = try! CodableCBORDecoder().decode([Int].self, from: oneTwoThree) 163 - XCTAssertEqual(oneTwoThreeDecoded, [1, 2, 3]) 164 - let lotsOfInts = try! CodableCBOREncoder().encode([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]) 165 - let lotsOfIntsDecoded = try! CodableCBORDecoder().decode([Int].self, from: lotsOfInts) 166 - XCTAssertEqual(lotsOfIntsDecoded, [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]) 167 - let nestedSimple = try! CodableCBOREncoder().encode([[1], [2, 3], [4, 5]]) 168 - let nestedSimpleDecoded = try! CodableCBORDecoder().decode([[Int]].self, from: nestedSimple) 169 - XCTAssertEqual(nestedSimpleDecoded, [[1], [2, 3], [4, 5]]) 170 - } 171 - 172 - func testMaps() { 173 - let empty = try! CodableCBOREncoder().encode([String: String]()) 174 - let emptyDecoded = try! CodableCBORDecoder().decode([String: String].self, from: empty) 175 - XCTAssertEqual(emptyDecoded, [:]) 176 - let stringToString = try! CodableCBOREncoder().encode(["a": "A", "b": "B", "c": "C", "d": "D", "e": "E"]) 177 - let stringToStringDecoded = try! CodableCBORDecoder().decode([String: String].self, from: stringToString) 178 - XCTAssertEqual(stringToStringDecoded, ["a": "A", "b": "B", "c": "C", "d": "D", "e": "E"]) 179 - let intKeyedMap = [1: 2, 3: 4] 180 - let oneTwoThreeFour = try! CodableCBOREncoder().encode(intKeyedMap) 181 - let oneTwoThreeFourDecoded = try! CodableCBORDecoder().decode([Int: Int].self, from: oneTwoThreeFour) 182 - XCTAssertEqual(oneTwoThreeFourDecoded, intKeyedMap) 183 - 184 - let encoder = CodableCBOREncoder() 185 - encoder.forbidNonStringMapKeys = true 186 - XCTAssertThrowsError(try encoder.encode(intKeyedMap)) { err in 187 - XCTAssertEqual(err as! CBOREncoderError, CBOREncoderError.nonStringKeyInMap) 188 - } 189 - } 190 - 191 - func testWrappedStruct() { 192 - struct Wrapped<T: Codable>: Decodable { 193 - let _id: String 194 - let value: T 195 - 196 - private enum CodingKeys: String, CodingKey { 197 - case _id 198 - } 199 - 200 - init(from decoder: Decoder) throws { 201 - let container = try decoder.container(keyedBy: CodingKeys.self) 202 - 203 - _id = try container.decode(String.self, forKey: ._id) 204 - value = try T(from: decoder) 205 - } 206 - } 207 - 208 - struct BasicCar: Codable { 209 - let color: String 210 - let age: Int 211 - let data: Data 212 - } 213 - 214 - struct Car: Codable { 215 - let _id: String 216 - let color: String 217 - let age: Int 218 - let data: Data 219 - } 220 - 221 - // Generate some random Data 222 - let randomBytes = (1...4).map { _ in UInt8.random(in: 0...UInt8.max) } 223 - let data = Data(randomBytes) 224 - 225 - let car = Car( 226 - _id: "5caf23633337661721236cfa", 227 - color: "Red", 228 - age: 56, 229 - data: data 230 - ) 231 - 232 - let encodedCar = try! CodableCBOREncoder().encode(car) 233 - let decoded = try! CodableCBORDecoder().decode(Wrapped<BasicCar>.self, from: encodedCar) 234 - 235 - XCTAssertEqual(decoded._id, car._id) 236 - XCTAssertEqual(decoded.value.color, car.color) 237 - XCTAssertEqual(decoded.value.age, car.age) 238 - XCTAssertEqual(decoded.value.data, data) 239 - } 240 - 241 - func testStructWithFloat() { 242 - struct MenuItemWithFloatOrdinal: Codable { 243 - var _id: String 244 - var category: String 245 - var ordinal: Float 246 - } 247 - 248 - let menuItem = MenuItemWithFloatOrdinal( 249 - _id: "aaa", 250 - category: "cake", 251 - ordinal: 12 252 - ) 253 - 254 - let encoded = try! CodableCBOREncoder().encode(menuItem) 255 - let decoded = try! CodableCBORDecoder().decode(MenuItemWithFloatOrdinal.self, from: encoded) 256 - 257 - XCTAssertEqual(decoded._id, menuItem._id) 258 - XCTAssertEqual(decoded.category, menuItem.category) 259 - XCTAssertEqual(decoded.ordinal, menuItem.ordinal) 260 - } 261 - 262 - func testStructContainingEnum() { 263 - enum Status: Codable { 264 - case done, underway, open 265 - } 266 - 267 - struct Order: Codable { 268 - var status: Status = .done 269 - } 270 - 271 - let order = Order() 272 - let cborOrder = try! CodableCBOREncoder().encode(order) 273 - let decodedCBOROrder = try! CodableCBORDecoder().decode(Order.self, from: cborOrder) 274 - 275 - XCTAssertEqual(decodedCBOROrder.status, order.status) 276 - } 277 - 278 - func testStructWithArray() { 279 - struct StructWithArray: Codable, Equatable { 280 - let arr: [Int] 281 - } 282 - 283 - let arraysToTest = [[], [1], [2, 3]] 284 - 285 - for arr in arraysToTest { 286 - let structWithArray = StructWithArray(arr: arr) 287 - 288 - let encoded = try! CodableCBOREncoder().encode(structWithArray) 289 - let decoded = try! CodableCBORDecoder().decode(StructWithArray.self, from: encoded) 290 - 291 - XCTAssertEqual(structWithArray, decoded) 292 - } 293 - } 294 - 295 - func testMultiTypeStruct() { 296 - struct MultiTypeStruct: Codable, Equatable { 297 - let stringVal: String 298 - let bytesVal: Data 299 - let integer: Int 300 - let booleanVal: Bool 301 - let doubleVal: Double 302 - let arrayVal: [Int]? 303 - } 304 - 305 - let arraysToTest: [[Int]?] = [[], nil] 306 - 307 - for arr in arraysToTest { 308 - let multiTypeStruct = MultiTypeStruct( 309 - stringVal: "s", 310 - bytesVal: Data(hex: "aabbcc")!, 311 - integer: 4711, 312 - booleanVal: true, 313 - doubleVal: 3.14, 314 - arrayVal: arr 315 - ) 316 - 317 - let encoded = try! CodableCBOREncoder().encode(multiTypeStruct) 318 - let decoded = try! CodableCBORDecoder().decode(MultiTypeStruct.self, from: encoded) 319 - 320 - XCTAssertEqual(multiTypeStruct, decoded) 321 - } 322 - 323 - let hexToRoundtrip = [ 324 - // Definite map without an arrayVal key-value pair 325 - "a56a626f6f6c65616e56616cf569737472696e6756616c63666f6f69646f75626c6556616cfb40091eb851eb851f67696e746567657219126768627974657356616c43aabbcc", 326 - 327 - // Indefinite map without an arrayVal key-value pair 328 - "bf6a626f6f6c65616e56616cf569737472696e6756616c63666f6f69646f75626c6556616cfb40091eb851eb851f67696e746567657219126768627974657356616c43aabbccff", 329 - 330 - // Definite map with an arrayVal key-value pair 331 - "a669737472696e6756616c63666f6f6a626f6f6c65616e56616cf567696e746567657219126769646f75626c6556616cfb40091eb851eb851f68627974657356616c43aabbcc68617272617956616c84010222191267", 332 - 333 - // Indefinite map with an arrayVal key-value pair 334 - "bf69737472696e6756616c63666f6f6a626f6f6c65616e56616cf567696e746567657219126769646f75626c6556616cfb40091eb851eb851f68627974657356616c43aabbcc68617272617956616c84010222191267ff" 335 - ] 336 - 337 - for hex in hexToRoundtrip { 338 - let _ = try! CodableCBORDecoder().decode(MultiTypeStruct.self, from: Data(hex: hex)!) 339 - } 340 - } 341 - 342 - func testAnyRecursive() { 343 - let anyRecursive: AnyRecursive = .object([ 344 - "intValue": .number(10), 345 - "floatValue": .number(130.1), 346 - "stringValue": .string("name 1"), 347 - "boolValue": .bool(true), 348 - "nilValue": .null, 349 - "arrayValue": .array([.number(1000), .number(2000), .number(3000)]), 350 - "objectValue": .object(["intValue": .number(5100)]) 351 - ]) 352 - 353 - let encoded = try! CodableCBOREncoder().encode(anyRecursive) 354 - let decoded = try! CodableCBORDecoder().decode(AnyRecursive.self, from: encoded) 355 - XCTAssertEqual(anyRecursive, decoded) 356 - } 357 - 358 - func testOptionalArray() { 359 - struct StructWithOptionalArray: Codable, Equatable { 360 - var array: [InnerStruct]? 361 - } 362 - 363 - struct InnerStruct: Codable, Equatable { 364 - var parameter: String 365 - } 366 - 367 - let test1 = StructWithOptionalArray(array: [InnerStruct(parameter: "present")]) 368 - let test2 = StructWithOptionalArray(array: nil) 369 - 370 - for testVal in [test1, test2] { 371 - let encoded = try! CodableCBOREncoder().encode(testVal) 372 - let decoded = try! CodableCBORDecoder().decode(StructWithOptionalArray.self, from: encoded) 373 - XCTAssertEqual(testVal, decoded) 374 - } 375 - } 376 - 377 - func testFoundationHeavyType() { 378 - struct FoundationLaden: Codable, Equatable { 379 - let date: Date 380 - let oldDate: Date 381 - let dateComponents: DateComponents 382 - let calendar: Calendar 383 - let locale: Locale 384 - let url: URL 385 - let urlComponents: URLComponents 386 - let measurement: Measurement<UnitMass> 387 - let uuid: UUID 388 - let personNameComponents: PersonNameComponents 389 - let timeZone: TimeZone 390 - let decimal: Decimal 391 - let dateInterval: DateInterval 392 - let characterSet: CharacterSet 393 - let indexPath: IndexPath 394 - let indexSet: IndexSet 395 - let range: Range<Int> 396 - let data: Data 397 - } 398 - 399 - var personNameComponents = PersonNameComponents() 400 - personNameComponents.givenName = "Bridget" 401 - personNameComponents.familyName = "Christie" 402 - personNameComponents.middleName = "Louise" 403 - personNameComponents.namePrefix = "Dame" 404 - personNameComponents.nickname = "Bridge" 405 - personNameComponents.nameSuffix = "Esq." 406 - 407 - var calendar = Calendar(identifier: .gregorian) 408 - calendar.timeZone = TimeZone(identifier: "UTC")! 409 - let dateComponents: Set<Calendar.Component> = [ 410 - .era, 411 - .year, 412 - .month, 413 - .day, 414 - .hour, 415 - .minute, 416 - .second, 417 - .weekday, 418 - .weekdayOrdinal, 419 - .weekOfMonth, 420 - .weekOfYear, 421 - .yearForWeekOfYear, 422 - .timeZone, 423 - .calendar, 424 - .nanosecond, 425 - .quarter, 426 - ] 427 - 428 - let foundationLadenObj = FoundationLaden( 429 - date: Date(timeIntervalSince1970: 1501283774), 430 - oldDate: Date(timeIntervalSince1970: -65672354), 431 - dateComponents: calendar.dateComponents(dateComponents, from: Date(timeIntervalSince1970: 1501283775)), 432 - calendar: calendar, 433 - locale: Locale(identifier: "UTC"), 434 - url: URL(string: "https://www.cars.com/cool/big?color=yellow")!, 435 - urlComponents: URLComponents(string: "https://subdomain.domain.com/some/path?and_a_query=string")!, 436 - measurement: Measurement(value: 67.4, unit: UnitMass.grams), 437 - uuid: UUID(), 438 - personNameComponents: personNameComponents, 439 - timeZone: TimeZone(identifier: "PST")!, 440 - decimal: Decimal(sign: .plus, exponent: -10, significand: 31415926536), 441 - dateInterval: DateInterval(start: Date(timeIntervalSince1970: 1501283772), duration: 86400), 442 - characterSet: CharacterSet.illegalCharacters, 443 - indexPath: IndexPath(indexes: [12, 3]), 444 - indexSet: IndexSet(arrayLiteral: 1, 2, 3, 9, 123, 1247890123), 445 - range: Range(NSRange(location: 12, length: 366))!, 446 - data: Data([163, 99, 95, 105, 100, 99, 97, 97, 97, 104, 99, 97, 116, 101, 103, 111, 114, 121, 100, 99, 97, 107, 101, 103, 111, 114, 100, 105, 110, 97, 108, 250, 65, 64, 0, 0]) 447 - ) 448 - 449 - let encoder = CodableCBOREncoder() 450 - encoder.useStringKeys = true 451 - let encodedWithStringKeys = try! encoder.encode(foundationLadenObj) 452 - let decoder = CodableCBORDecoder() 453 - decoder.useStringKeys = true 454 - let decodedFromStringKeys = try! decoder.decode(FoundationLaden.self, from: encodedWithStringKeys) 455 - XCTAssertEqual(decodedFromStringKeys, foundationLadenObj) 456 - 457 - encoder.dateStrategy = .annotatedMap 458 - let encodedWithStringKeysAndAnnotatedMapDate = try! encoder.encode(foundationLadenObj) 459 - decoder.dateStrategy = .annotatedMap 460 - let decodedFromStringKeysAndAnnotatedMapDate = try! decoder.decode(FoundationLaden.self, from: encodedWithStringKeysAndAnnotatedMapDate) 461 - XCTAssertEqual(decodedFromStringKeysAndAnnotatedMapDate, foundationLadenObj) 462 - 463 - XCTAssertNotEqual(encodedWithStringKeys, encodedWithStringKeysAndAnnotatedMapDate) 464 - 465 - let encoded = try! CodableCBOREncoder().encode(foundationLadenObj) 466 - let decoded = try! CodableCBORDecoder().decode(FoundationLaden.self, from: encoded) 467 - XCTAssertEqual(decoded, foundationLadenObj) 468 - 469 - XCTAssertNotEqual(encoded, encodedWithStringKeys) 470 - XCTAssertNotEqual(encoded, encodedWithStringKeysAndAnnotatedMapDate) 471 - } 472 - 473 - #if os(macOS) 474 - func testMacOSOnlyTypes() { 475 - struct MacOSOnlyTypes: Codable, Equatable { 476 - let affineTransform: AffineTransform 477 - let point: NSPoint 478 - let size: NSSize 479 - } 480 - 481 - let macOSOnlyObj = MacOSOnlyTypes( 482 - affineTransform: AffineTransform(translationByX: 12.34, byY: -56.78), 483 - point: NSPoint(x: -99.123, y: 2.04), 484 - size: NSSize(width: 77.77, height: 88.88) 485 - ) 486 - 487 - let encoder = CodableCBOREncoder() 488 - encoder.useStringKeys = true 489 - let encodedWithStringKeys = try! encoder.encode(macOSOnlyObj) 490 - let decoder = CodableCBORDecoder() 491 - decoder.useStringKeys = true 492 - let decodedFromStringKeys = try! decoder.decode(MacOSOnlyTypes.self, from: encodedWithStringKeys) 493 - XCTAssertEqual(decodedFromStringKeys, macOSOnlyObj) 494 - 495 - let encoded = try! CodableCBOREncoder().encode(macOSOnlyObj) 496 - let decoded = try! CodableCBORDecoder().decode(MacOSOnlyTypes.self, from: encoded) 497 - XCTAssertEqual(decoded, macOSOnlyObj) 498 - } 499 - #endif 500 - } 501 - 502 - enum AnyRecursive: Equatable { 503 - case string(String) 504 - case number(Float) 505 - case object([String: AnyRecursive]) 506 - case array([AnyRecursive]) 507 - case bool(Bool) 508 - case null 509 - } 510 - 511 - extension AnyRecursive: Codable { 512 - init(from decoder: Decoder) throws { 513 - let container = try decoder.singleValueContainer() 514 - 515 - if let object = try? container.decode([String: AnyRecursive].self) { 516 - self = .object(object) 517 - } else if let array = try? container.decode([AnyRecursive].self) { 518 - self = .array(array) 519 - } else if let string = try? container.decode(String.self) { 520 - self = .string(string) 521 - } else if let bool = try? container.decode(Bool.self) { 522 - self = .bool(bool) 523 - } else if let number = try? container.decode(Float.self) { 524 - self = .number(number) 525 - } else if container.decodeNil() { 526 - self = .null 527 - } else { 528 - throw DecodingError.dataCorrupted( 529 - .init( 530 - codingPath: decoder.codingPath, 531 - debugDescription: "Invalid \(String(describing: AnyRecursive.self)) value." 532 - ) 533 - ) 534 - } 535 - } 536 - 537 - func encode(to encoder: Encoder) throws { 538 - var container = encoder.singleValueContainer() 539 - 540 - switch self { 541 - case let .array(array): 542 - try container.encode(array) 543 - case let .object(object): 544 - try container.encode(object) 545 - case let .string(string): 546 - try container.encode(string) 547 - case let .number(number): 548 - try container.encode(number) 549 - case let .bool(bool): 550 - try container.encode(bool) 551 - case .null: 552 - try container.encodeNil() 553 - } 554 - } 555 - }
-221
Old/SwiftCBORTests-old/CBORDecoderTests.swift
··· 1 - import XCTest 2 - @testable import SwiftCBOR 3 - 4 - class CBORDecoderTests: XCTestCase { 5 - func testDecodeNumbers() { 6 - for i in (0..<24) { 7 - XCTAssertEqual(try! CBORDecoder(input: [UInt8(i)]).decodeItem(), CBOR.unsignedInt(UInt64(i))) 8 - } 9 - XCTAssertEqual(try! CBORDecoder(input: [0x18, 0xff]).decodeItem(), 255) 10 - XCTAssertEqual(try! CBORDecoder(input: [0x19, 0x03, 0xe8]).decodeItem(), 1000) // Network byte order! 11 - XCTAssertEqual(try! CBORDecoder(input: [0x19, 0xff, 0xff]).decodeItem(), 65535) 12 - do { _ = try CBORDecoder(input: [0x19, 0xff]).decodeItem(); XCTAssertTrue(false) } catch { XCTAssertTrue(true) } 13 - XCTAssertEqual(try! CBORDecoder(input: [0x1a, 0x00, 0x0f, 0x42, 0x40]).decodeItem(), 1000000) 14 - XCTAssertEqual(try! CBORDecoder(input: [0x1a, 0xff, 0xff, 0xff, 0xff]).decodeItem(), 4294967295) 15 - do { _ = try CBORDecoder(input: [0x1a]).decodeItem(); XCTAssertTrue(false) } catch { XCTAssertTrue(true) } 16 - XCTAssertEqual(try! CBORDecoder(input: [0x1b, 0x00, 0x00, 0x00, 0xe8, 0xd4, 0xa5, 0x10, 0x00]).decodeItem(), 1000000000000) 17 - XCTAssertEqual(try! CBORDecoder(input: [0x1b, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff]).decodeItem(), CBOR.unsignedInt(18446744073709551615)) 18 - do { _ = try CBORDecoder(input: [0x1b, 0x00, 0x00]).decodeItem(); XCTAssertTrue(false) } catch { XCTAssertTrue(true) } 19 - 20 - XCTAssertEqual(try! CBORDecoder(input: [0x20]).decodeItem(), -1) 21 - XCTAssertEqual(try! CBORDecoder(input: [0x21]).decodeItem(), CBOR.negativeInt(1)) 22 - XCTAssertEqual(try! CBORDecoder(input: [0x37]).decodeItem(), -24) 23 - XCTAssertEqual(try! CBORDecoder(input: [0x38, 0xff]).decodeItem(), -256) 24 - XCTAssertEqual(try! CBORDecoder(input: [0x39, 0x03, 0xe7]).decodeItem(), -1000) 25 - XCTAssertEqual(try! CBORDecoder(input: [0x3a, 0x00, 0x0f, 0x42, 0x3f]).decodeItem(), CBOR.negativeInt(999999)) 26 - XCTAssertEqual(try! CBORDecoder(input: [0x3b, 0x00, 0x00, 0x00, 0xe8, 0xd4, 0xa5, 0x0f, 0xff]).decodeItem(), CBOR.negativeInt(999999999999)) 27 - } 28 - 29 - func testDecodeByteStrings() { 30 - XCTAssertEqual(try! CBORDecoder(input: [0x40]).decodeItem(), CBOR.byteString([])) 31 - XCTAssertEqual(try! CBORDecoder(input: [0x41, 0xf0]).decodeItem(), CBOR.byteString([0xf0])) 32 - XCTAssertEqual(try! CBORDecoder(input: [0x57, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xaa]).decodeItem(), CBOR.byteString([0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xaa])) 33 - XCTAssertEqual(try! CBORDecoder(input: [0x58, 0]).decodeItem(), CBOR.byteString([])) 34 - XCTAssertEqual(try! CBORDecoder(input: [0x58, 1, 0xf0]).decodeItem(), CBOR.byteString([0xf0])) 35 - XCTAssertEqual(try! CBORDecoder(input: [0x59, 0x00, 3, 0xc0, 0xff, 0xee]).decodeItem(), CBOR.byteString([0xc0, 0xff, 0xee])) 36 - XCTAssertEqual(try! CBORDecoder(input: [0x5a, 0x00, 0x00, 0x00, 3, 0xc0, 0xff, 0xee]).decodeItem(), CBOR.byteString([0xc0, 0xff, 0xee])) 37 - XCTAssertEqual(try! CBORDecoder(input: [0x5b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 3, 0xc0, 0xff, 0xee]).decodeItem(), CBOR.byteString([0xc0, 0xff, 0xee])) 38 - XCTAssertEqual(try! CBORDecoder(input: [0x5f, 0x58, 3, 0xc0, 0xff, 0xee, 0x43, 0xc0, 0xff, 0xee, 0xff]).decodeItem(), CBOR.byteString([0xc0, 0xff, 0xee, 0xc0, 0xff, 0xee])) 39 - } 40 - 41 - func testDecodeData() { 42 - XCTAssertEqual(try! CBORDecoder(input: [0x40]).decodeItem(), CBOR.byteString([])) 43 - XCTAssertEqual(try! CBORDecoder(input: [0x41, 0xf0]).decodeItem(), CBOR.byteString([0xf0])) 44 - XCTAssertEqual(try! CBORDecoder(input: [0x57, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xaa]).decodeItem(), CBOR.byteString([0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xaa])) 45 - XCTAssertEqual(try! CBORDecoder(input: [0x58, 0]).decodeItem(), CBOR.byteString([])) 46 - XCTAssertEqual(try! CBORDecoder(input: [0x58, 1, 0xf0]).decodeItem(), CBOR.byteString([0xf0])) 47 - XCTAssertEqual(try! CBORDecoder(input: [0x59, 0x00, 3, 0xc0, 0xff, 0xee]).decodeItem(), CBOR.byteString([0xc0, 0xff, 0xee])) 48 - XCTAssertEqual(try! CBORDecoder(input: [0x5a, 0x00, 0x00, 0x00, 3, 0xc0, 0xff, 0xee]).decodeItem(), CBOR.byteString([0xc0, 0xff, 0xee])) 49 - XCTAssertEqual(try! CBORDecoder(input: [0x5b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 3, 0xc0, 0xff, 0xee]).decodeItem(), CBOR.byteString([0xc0, 0xff, 0xee])) 50 - XCTAssertEqual(try! CBORDecoder(input: [0x5f, 0x58, 3, 0xc0, 0xff, 0xee, 0x43, 0xc0, 0xff, 0xee, 0xff]).decodeItem(), CBOR.byteString([0xc0, 0xff, 0xee, 0xc0, 0xff, 0xee])) 51 - } 52 - 53 - func testDecodeUtf8Strings() { 54 - XCTAssertEqual(try! CBORDecoder(input: [0x60]).decodeItem(), CBOR.utf8String("")) 55 - XCTAssertEqual(try! CBORDecoder(input: [0x61, 0x42]).decodeItem(), "B") 56 - XCTAssertEqual(try! CBORDecoder(input: [0x78, 0]).decodeItem(), "") 57 - XCTAssertEqual(try! CBORDecoder(input: [0x78, 1, 0x42]).decodeItem(), "B") 58 - XCTAssertEqual(try! CBORDecoder(input: [0x79, 0x00, 3, 0x41, 0x42, 0x43]).decodeItem(), CBOR.utf8String("ABC")) 59 - XCTAssertEqual(try! CBORDecoder(input: [0x7a, 0x00, 0x00, 0x00, 3, 0x41, 0x42, 0x43]).decodeItem(), "ABC") 60 - XCTAssertEqual(try! CBORDecoder(input: [0x7b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 3, 0x41, 0x42, 0x43]).decodeItem(), "ABC") 61 - XCTAssertEqual(try! CBORDecoder(input: [0x7f, 0x78, 3, 0x41, 0x42, 0x43, 0x63, 0x41, 0x42, 0x43, 0xff]).decodeItem(), "ABCABC") 62 - } 63 - 64 - func testDecodeArrays() { 65 - XCTAssertEqual(try! CBORDecoder(input: [0x80]).decodeItem(), []) 66 - XCTAssertEqual(try! CBORDecoder(input: [0x82, 0x18, 1, 0x79, 0x00, 3, 0x41, 0x42, 0x43]).decodeItem(), [1, "ABC"]) 67 - XCTAssertEqual(try! CBORDecoder(input: [0x98, 0]).decodeItem(), []) 68 - XCTAssertEqual(try! CBORDecoder(input: [0x98, 3, 0x18, 2, 0x18, 2, 0x79, 0x00, 3, 0x41, 0x42, 0x43, 0xff]).decodeItem(), [2, 2, "ABC"]) 69 - XCTAssertEqual(try! CBORDecoder(input: [0x9f, 0x18, 255, 0x9b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 2, 0x18, 1, 0x79, 0x00, 3, 0x41, 0x42, 0x43, 0x79, 0x00, 3, 0x41, 0x42, 0x43, 0xff]).decodeItem(), [255, [1, "ABC"], "ABC"]) 70 - XCTAssertEqual(try! CBORDecoder(input: [0x9f, 0x81, 0x01, 0x82, 0x02, 0x03, 0x9f, 0x04, 0x05, 0xff, 0xff]).decodeItem(), [[1], [2, 3], [4, 5]]) 71 - } 72 - 73 - func testDecodeMaps() { 74 - XCTAssertEqual(try! CBORDecoder(input: [0xa0]).decodeItem(), [:]) 75 - XCTAssertEqual(try! CBORDecoder(input: [0xa1, 0x63, 0x6b, 0x65, 0x79, 0x37]).decodeItem()!["key"], -24) 76 - XCTAssertEqual(try! CBORDecoder(input: [0xb8, 1, 0x63, 0x6b, 0x65, 0x79, 0x81, 0x37]).decodeItem(), ["key" : [-24]]) 77 - XCTAssertEqual(try! CBORDecoder(input: [0xbf, 0x63, 0x6b, 0x65, 0x79, 0xa1, 0x63, 0x6b, 0x65, 0x79, 0x37, 0xff]).decodeItem(), ["key" : ["key" : -24]]) 78 - XCTAssertEqual(try! CBORDecoder(input: [0xa3, 0x63, 0x5f, 0x69, 0x64, 0x63, 0x61, 0x61, 0x61, 0x68, 0x63, 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, 0x79, 0x64, 0x63, 0x61, 0x6b, 0x65, 0x67, 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x61, 0x6c, 0xf9, 0x4a, 0x00]).decodeItem(), ["_id": "aaa", "category": "cake", "ordinal": CBOR.half(12.0)]) 79 - } 80 - 81 - func testDecodeTagged() { 82 - XCTAssertEqual(try! CBORDecoder(input: [0xc0, 0x79, 0x00, 3, 0x41, 0x42, 0x43]).decodeItem(), CBOR.tagged(.standardDateTimeString, "ABC")) 83 - XCTAssertEqual(try! CBORDecoder(input: [0xd8, 255, 0x79, 0x00, 3, 0x41, 0x42, 0x43]).decodeItem(), CBOR.tagged(.init(rawValue: 255), "ABC")) 84 - XCTAssertEqual(try! CBORDecoder(input: [0xdb, 255, 255, 255, 255, 255, 255, 255, 255, 0x79, 0x00, 3, 0x41, 0x42, 0x43]).decodeItem(), CBOR.tagged(.init(rawValue: UInt64.max), "ABC")) 85 - XCTAssertEqual(try! CBORDecoder(input: [0xdb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 3, 0xbf, 0x63, 0x6b, 0x65, 0x79, 0xa1, 0x63, 0x6b, 0x65, 0x79, 0x37, 0xff]).decodeItem(), CBOR.tagged(.negativeBignum, ["key" : ["key" : -24]])) 86 - } 87 - 88 - func testDecodeSimple() { 89 - XCTAssertEqual(try! CBORDecoder(input: [0xe0]).decodeItem(), CBOR.simple(0)) 90 - XCTAssertEqual(try! CBORDecoder(input: [0xf3]).decodeItem(), CBOR.simple(19)) 91 - XCTAssertEqual(try! CBORDecoder(input: [0xf8, 19]).decodeItem(), CBOR.simple(19)) 92 - XCTAssertEqual(try! CBORDecoder(input: [0xf4]).decodeItem(), false) 93 - XCTAssertEqual(try! CBORDecoder(input: [0xf5]).decodeItem(), true) 94 - XCTAssertEqual(try! CBORDecoder(input: [0xf6]).decodeItem(), CBOR.null) 95 - XCTAssertEqual(try! CBORDecoder(input: [0xf7]).decodeItem(), CBOR.undefined) 96 - } 97 - 98 - func testDecodeFloats() { 99 - XCTAssertEqual(try! CBORDecoder(input: [0xf9, 0xc4, 0x00]).decodeItem(), CBOR.half(-4.0)) 100 - XCTAssertEqual(try! CBORDecoder(input: [0xf9, 0xfc, 0x00]).decodeItem(), CBOR.half(-Float.infinity)) 101 - XCTAssertEqual(try! CBORDecoder(input: [0xfa, 0x47, 0xc3, 0x50, 0x00]).decodeItem(), 100000.0) 102 - XCTAssertEqual(try! CBORDecoder(input: [0xfa, 0x7f, 0x80, 0x00, 0x00]).decodeItem(), CBOR.float(Float.infinity)) 103 - XCTAssertEqual(try! CBORDecoder(input: [0xfb, 0xc0, 0x10, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66]).decodeItem(), CBOR.double(-4.1)) 104 - } 105 - 106 - func testDecodeDates() { 107 - let dateOne = Date(timeIntervalSince1970: 1363896240) 108 - XCTAssertEqual(try! CBOR.decode([0xc1, 0x1a, 0x51, 0x4b, 0x67, 0xb0]), CBOR.date(dateOne)) 109 - let dateTwo = Date(timeIntervalSince1970: 1363896240.5) 110 - XCTAssertEqual(try! CBOR.decode([0xc1, 0xfb, 0x41, 0xd4, 0x52, 0xd9, 0xec, 0x20, 0x00, 0x00]), CBOR.date(dateTwo)) 111 - } 112 - 113 - func testDecodePerformance() { 114 - var data : ArraySlice<UInt8> = [0x9f] 115 - for i in (0..<255) { 116 - data.append(contentsOf: [0xbf, 0x63, 0x6b, 0x65, 0x79, 0xa1, 0x63, 0x6b, 0x65, 0x79, 0x18, UInt8(i), 0xff]) 117 - } 118 - data.append(0xff) 119 - self.measure { 120 - _ = try! CBORDecoder(input: data).decodeItem() 121 - } 122 - } 123 - 124 - func testDecodeMapFromIssue29() { 125 - let loremIpsumData: [UInt8] = [0x4c, 0x6f, 0x72, 0x65, 0x6d, 0x20, 0x69, 0x70, 0x73, 0x75, 0x6d, 0x20, 0x64, 0x6f, 0x6c, 0x6f, 0x72, 0x20, 0x73, 0x69, 0x74, 0x20, 0x61, 0x6d, 0x65, 0x74, 0x2c, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x63, 0x74, 0x65, 0x74, 0x75, 0x72, 0x20, 0x61, 0x64, 0x69, 0x70, 0x69, 0x73, 0x63, 0x69, 0x6e, 0x67, 0x20, 0x65, 0x6c, 0x69, 0x74, 0x2e, 0x20, 0x51, 0x75, 0x69, 0x73, 0x71, 0x75, 0x65, 0x20, 0x65, 0x78, 0x20, 0x61, 0x6e, 0x74, 0x65, 0x2c, 0x20, 0x73, 0x65, 0x6d, 0x70, 0x65, 0x72, 0x20, 0x75, 0x74, 0x20, 0x66, 0x61, 0x75, 0x63, 0x69, 0x62, 0x75, 0x73, 0x20, 0x70, 0x68, 0x61, 0x72, 0x65, 0x74, 0x72, 0x61, 0x2c, 0x20, 0x61, 0x63, 0x63, 0x75, 0x6d, 0x73, 0x61, 0x6e, 0x20, 0x65, 0x74, 0x20, 0x61, 0x75, 0x67, 0x75, 0x65, 0x2e, 0x20, 0x56, 0x65, 0x73, 0x74, 0x69, 0x62, 0x75, 0x6c, 0x75, 0x6d, 0x20, 0x76, 0x75, 0x6c, 0x70, 0x75, 0x74, 0x61, 0x74, 0x65, 0x20, 0x65, 0x6c, 0x69, 0x74, 0x20, 0x6c, 0x69, 0x67, 0x75, 0x6c, 0x61, 0x2c, 0x20, 0x65, 0x75, 0x20, 0x74, 0x69, 0x6e, 0x63, 0x69, 0x64, 0x75, 0x6e, 0x74, 0x20, 0x6f, 0x72, 0x63, 0x69, 0x20, 0x6c, 0x61, 0x63, 0x69, 0x6e, 0x69, 0x61, 0x20, 0x71, 0x75, 0x69, 0x73, 0x2e, 0x20, 0x50, 0x72, 0x6f, 0x69, 0x6e, 0x20, 0x73, 0x63, 0x65, 0x6c, 0x65, 0x72, 0x69, 0x73, 0x71, 0x75, 0x65, 0x20, 0x64, 0x75, 0x69, 0x20, 0x61, 0x74, 0x20, 0x6d, 0x61, 0x67, 0x6e, 0x61, 0x20, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x72, 0x61, 0x74, 0x2c, 0x20, 0x69, 0x64, 0x20, 0x62, 0x6c, 0x61, 0x6e, 0x64, 0x69, 0x74, 0x20, 0x66, 0x65, 0x6c, 0x69, 0x73, 0x20, 0x76, 0x65, 0x68, 0x69, 0x63, 0x75, 0x6c, 0x61, 0x2e, 0x20, 0x4d, 0x61, 0x65, 0x63, 0x65, 0x6e, 0x61, 0x73, 0x20, 0x61, 0x63, 0x20, 0x6e, 0x69, 0x73, 0x6c, 0x20, 0x61, 0x20, 0x6f, 0x64, 0x69, 0x6f, 0x20, 0x76, 0x61, 0x72, 0x69, 0x75, 0x73, 0x20, 0x63, 0x6f, 0x6e, 0x64, 0x69, 0x6d, 0x65, 0x6e, 0x74, 0x75, 0x6d, 0x20, 0x6c] 126 - let data: [UInt8] = [0xbf, 0x63, 0x6f, 0x66, 0x66, 0x00, 0x64, 0x64, 0x61, 0x74, 0x61, 0x59, 0x01, 0x2c] 127 - + loremIpsumData 128 - + [0x62, 0x72, 0x63, 0x00, 0x63, 0x6c, 0x65, 0x6e, 0x19, 0x01, 0x2c, 0xff] 129 - 130 - let expectedMap = CBOR.map([ 131 - CBOR.utf8String("off"): CBOR.unsignedInt(0), 132 - CBOR.utf8String("data"): CBOR.byteString(loremIpsumData), 133 - CBOR.utf8String("rc"): CBOR.unsignedInt(0), 134 - CBOR.utf8String("len"): CBOR.unsignedInt(300) 135 - ]) 136 - 137 - let decoded = try! CBOR.decode(data) 138 - XCTAssertEqual(decoded, expectedMap) 139 - } 140 - 141 - func testDecodeFromIssue78() { 142 - struct CborFiles: Codable { 143 - let files: [File] 144 - let status: Int 145 - } 146 - 147 - struct File: Codable { 148 - let name: String 149 - let time, id, size, checksum: Int 150 - } 151 - 152 - let withDefiniteArrayHex = "bf6566696c657381a5626964016474696d651a001b7d4868636865636b73756d1a0ad227576473697a6505646e616d656d2f6c66732f68722f31312e68726673746174757301ff" 153 - let _ = try! CodableCBORDecoder().decode(CborFiles.self, from: withDefiniteArrayHex.hexaData) 154 - 155 - let withIndefiniteArrayHex = "bf6566696c65739fa5626964016474696d651a001b7d4868636865636b73756d1a0ad227576473697a6505646e616d656d2f6c66732f68722f31312e6872ff6673746174757301ff" 156 - let _ = try! CodableCBORDecoder().decode(CborFiles.self, from: withIndefiniteArrayHex.hexaData) 157 - } 158 - 159 - func testDecodeOfStructContainingNestedIndefiniteMapsAndArrays() { 160 - struct NestedIndefinite: Codable, Equatable { 161 - let nested: [String: [String: [[String: [[[String: [[String: Int]]]? ]]]]]] 162 - } 163 - 164 - let hex = "bf666e6573746564bf6161bf61629fbf61639f9fbf61649fbf6165187bffffffff9fff9ff6ffffffffffffff" 165 - 166 - let decoded = try! CodableCBORDecoder().decode(NestedIndefinite.self, from: hex.hexaData) 167 - let expected = NestedIndefinite(nested: ["a": ["b": [["c": [[["d": [["e": 123 ]] ]], [], [nil]]]]]]) 168 - 169 - XCTAssertEqual(decoded, expected) 170 - } 171 - 172 - func testDecodeFailsForExtremelyDeepStructures() { 173 - let justOverTags: [UInt8] = Array(repeating: 202, count: 1025) + [0] 174 - XCTAssertThrowsError(try CBOR.decode(justOverTags, options: CBOROptions(maximumDepth: 1024))) { error in 175 - XCTAssertEqual(error as? CBORError, CBORError.maximumDepthExceeded) 176 - } 177 - let endlessTags: [UInt8] = Array(repeating: 202, count: 10000) + [0] 178 - XCTAssertThrowsError(try CBOR.decode(endlessTags, options: CBOROptions(maximumDepth: 1024))) { error in 179 - XCTAssertEqual(error as? CBORError, CBORError.maximumDepthExceeded) 180 - } 181 - } 182 - 183 - func testDecodeFailsForSillyMaximumDepths() { 184 - let singleItem: [UInt8] = [0] 185 - XCTAssertThrowsError(try CBOR.decode(singleItem, options: CBOROptions(maximumDepth: -1))) { error in 186 - XCTAssertEqual(error as? CBORError, CBORError.maximumDepthExceeded) 187 - } 188 - } 189 - 190 - func testDecodeSucceedsForAllowedDeepStructures() { 191 - let singleItem: [UInt8] = [0] 192 - XCTAssertNoThrow(try CBOR.decode(singleItem, options: CBOROptions(maximumDepth: 0))) 193 - let endlessTags: [UInt8] = Array(repeating: 202, count: 1024) + [0] 194 - XCTAssertNoThrow(try CBOR.decode(endlessTags, options: CBOROptions(maximumDepth: 1024))) 195 - } 196 - 197 - func testRandomInputDoesNotHitStackLimits() { 198 - for _ in 1...50 { 199 - let length = Int.random(in: 1...1_000_000) 200 - let randomData: [UInt8] = Array(repeating: UInt8.random(in: 0...255), count: length) 201 - _ = try? CBOR.decode(randomData, options: CBOROptions(maximumDepth: 512)) 202 - } 203 - } 204 - } 205 - 206 - #if os(Android) 207 - 208 - extension XCTestCase { 209 - /// XCTestCase.measure on Android is problematic because 210 - /// the emulator on a virtualized runner can be quite slow 211 - /// but there is no way to set the standard deviation threshold 212 - /// for failure, so we override it to simply run the block 213 - /// and not perform any measurement. 214 - /// 215 - /// See: https://github.com/swiftlang/swift-corelibs-xctest/pull/506 216 - func measure(_ count: Int = 0, _ block: () -> ()) { 217 - block() 218 - } 219 - } 220 - #endif 221 -
-66
Old/SwiftCBORTests-old/CBOREncodableTests.swift
··· 1 - import XCTest 2 - @testable import SwiftCBOR 3 - 4 - class CBOREncodableTests: XCTestCase { 5 - func testToCBOR() { 6 - XCTAssertEqual(CBOR.unsignedInt(0), 0.toCBOR(options: CBOROptions())) 7 - XCTAssertEqual(CBOR.unsignedInt(1), 1.toCBOR(options: CBOROptions())) 8 - XCTAssertEqual(CBOR.unsignedInt(20), 20.toCBOR(options: CBOROptions())) 9 - 10 - XCTAssertEqual(CBOR.unsignedInt(UInt64(Int8.max)), Int8.max.toCBOR(options: CBOROptions())) 11 - XCTAssertEqual(127, Int8.max.toCBOR(options: CBOROptions())) 12 - XCTAssertEqual(CBOR.unsignedInt(UInt64(Int16.max)), Int16.max.toCBOR(options: CBOROptions())) 13 - XCTAssertEqual(32_767, Int16.max.toCBOR(options: CBOROptions())) 14 - XCTAssertEqual(CBOR.unsignedInt(UInt64(Int32.max)), Int32.max.toCBOR(options: CBOROptions())) 15 - XCTAssertEqual(2_147_483_647, Int32.max.toCBOR(options: CBOROptions())) 16 - XCTAssertEqual(CBOR.unsignedInt(UInt64(Int64.max)), Int64.max.toCBOR(options: CBOROptions())) 17 - XCTAssertEqual(9_223_372_036_854_775_807, Int64.max.toCBOR(options: CBOROptions())) 18 - 19 - XCTAssertEqual(CBOR.unsignedInt(UInt64(UInt8.max)), UInt8.max.toCBOR(options: CBOROptions())) 20 - XCTAssertEqual(255, UInt8.max.toCBOR(options: CBOROptions())) 21 - XCTAssertEqual(CBOR.unsignedInt(UInt64(UInt16.max)), UInt16.max.toCBOR(options: CBOROptions())) 22 - XCTAssertEqual(65_535, UInt16.max.toCBOR(options: CBOROptions())) 23 - XCTAssertEqual(CBOR.unsignedInt(UInt64(UInt32.max)), UInt32.max.toCBOR(options: CBOROptions())) 24 - XCTAssertEqual(4_294_967_295, UInt32.max.toCBOR(options: CBOROptions())) 25 - XCTAssertEqual(CBOR.unsignedInt(UInt64.max), UInt64.max.toCBOR(options: CBOROptions())) 26 - 27 - XCTAssertEqual(CBOR.negativeInt(~UInt64(bitPattern: Int64(Int8.min))), Int8.min.toCBOR(options: CBOROptions())) 28 - XCTAssertEqual(-128, Int8.min.toCBOR(options: CBOROptions())) 29 - XCTAssertEqual(CBOR.negativeInt(~UInt64(bitPattern: Int64(Int16.min))), Int16.min.toCBOR(options: CBOROptions())) 30 - XCTAssertEqual(-32_768, Int16.min.toCBOR(options: CBOROptions())) 31 - XCTAssertEqual(CBOR.negativeInt(~UInt64(bitPattern: Int64(Int32.min))), Int32.min.toCBOR(options: CBOROptions())) 32 - XCTAssertEqual(-2_147_483_648, Int32.min.toCBOR(options: CBOROptions())) 33 - XCTAssertEqual(CBOR.negativeInt(~UInt64(bitPattern: Int64(Int64.min))), Int64.min.toCBOR(options: CBOROptions())) 34 - XCTAssertEqual(-9_223_372_036_854_775_808, Int64.min.toCBOR(options: CBOROptions())) 35 - 36 - XCTAssertEqual(CBOR.double(Double.greatestFiniteMagnitude), Double.greatestFiniteMagnitude.toCBOR(options: CBOROptions())) 37 - XCTAssertEqual(CBOR.double(Double.leastNonzeroMagnitude), Double.leastNonzeroMagnitude.toCBOR(options: CBOROptions())) 38 - XCTAssertEqual(CBOR.double(Double.pi), Double.pi.toCBOR(options: CBOROptions())) 39 - XCTAssertEqual(CBOR.double(0.123456789), 0.123456789.toCBOR(options: CBOROptions())) 40 - 41 - XCTAssertEqual(CBOR.float(Float.greatestFiniteMagnitude), Float.greatestFiniteMagnitude.toCBOR(options: CBOROptions())) 42 - XCTAssertEqual(CBOR.float(Float.leastNonzeroMagnitude), Float.leastNonzeroMagnitude.toCBOR(options: CBOROptions())) 43 - XCTAssertEqual(CBOR.float(Float.pi), Float.pi.toCBOR(options: CBOROptions())) 44 - XCTAssertEqual(CBOR.float(0.123456789), Float(0.123456789).toCBOR(options: CBOROptions())) 45 - 46 - XCTAssertEqual(CBOR.boolean(true), true.toCBOR(options: CBOROptions())) 47 - XCTAssertEqual(true, true.toCBOR(options: CBOROptions())) 48 - XCTAssertEqual(CBOR.boolean(false), false.toCBOR(options: CBOROptions())) 49 - XCTAssertEqual(false, false.toCBOR(options: CBOROptions())) 50 - 51 - XCTAssertEqual(CBOR.utf8String("test"), "test".toCBOR(options: CBOROptions())) 52 - XCTAssertEqual("test", "test".toCBOR(options: CBOROptions())) 53 - 54 - XCTAssertEqual(CBOR.null, Optional<String>.none.toCBOR(options: CBOROptions())) 55 - XCTAssertEqual(nil, Optional<String>.none.toCBOR(options: CBOROptions())) 56 - 57 - XCTAssertEqual(CBOR.byteString([1, 2, 3]), Data([1, 2, 3]).toCBOR(options: CBOROptions())) 58 - 59 - XCTAssertEqual(CBOR.array([CBOR.unsignedInt(1), CBOR.unsignedInt(2)]), [1, 2].toCBOR(options: CBOROptions())) 60 - 61 - XCTAssertEqual( 62 - CBOR.map([CBOR.utf8String("a"): CBOR.unsignedInt(1), CBOR.utf8String("b"): CBOR.unsignedInt(2)]), 63 - ["a": 1, "b": 2].toCBOR(options: CBOROptions()) 64 - ) 65 - } 66 - }
-287
Old/SwiftCBORTests-old/CBOREncoderTests.swift
··· 1 - import XCTest 2 - @testable import SwiftCBOR 3 - 4 - class CBOREncoderTests: XCTestCase { 5 - func assertEquivalent<T: CBOREncodable>(_ input: T, _ cbor: [UInt8], options: CBOROptions = CBOROptions()) { 6 - XCTAssertEqual(input.encode(options: options), cbor) 7 - XCTAssertEqual(try! CBOR.decode(input.encode(options: options)), try! CBOR.decode(cbor)) 8 - } 9 - 10 - func testEncodeInts() { 11 - for i in 0..<24 { 12 - assertEquivalent(i, [UInt8(i)]) 13 - XCTAssertEqual((-i).encode().count, 1) 14 - } 15 - XCTAssertEqual(Int(-1).encode(), [0x20]) 16 - XCTAssertEqual(UInt(1).encode(), [0x1]) 17 - XCTAssertEqual(CBOR.encode(-10), [0x29]) 18 - XCTAssertEqual(Int(-24).encode(), [0x37]) 19 - XCTAssertEqual(Int(-25).encode(), [0x38, 24]) 20 - XCTAssertEqual(1000000.encode(), [0x1a, 0x00, 0x0f, 0x42, 0x40]) 21 - XCTAssertEqual(4294967295.encode(), [0x1a, 0xff, 0xff, 0xff, 0xff]) //UInt32.max 22 - XCTAssertEqual(1000000000000.encode(), [0x1b, 0x00, 0x00, 0x00, 0xe8, 0xd4, 0xa5, 0x10, 0x00]) 23 - XCTAssertEqual(Int(-1_000_000).encode(), [0x3a, 0x00, 0x0f, 0x42, 0x3f]) 24 - XCTAssertEqual(Int(-1_000_000_000_000).encode(), [0x3b, 0x00, 0x00, 0x00, 0xe8, 0xd4, 0xa5, 0x0f, 0xff]) 25 - } 26 - 27 - func testEncodeByteStrings() { 28 - XCTAssertEqual(CBOR.encode([UInt8](), asByteString: true), [0x40]) 29 - XCTAssertEqual(CBOR.encode([UInt8]([0xf0]), asByteString: true), [0x41, 0xf0]) 30 - XCTAssertEqual(CBOR.encode([UInt8]([0x01, 0x02, 0x03, 0x04]), asByteString: true), [0x44, 0x01, 0x02, 0x03, 0x04]) 31 - let bs23: [UInt8] = [0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xaa] 32 - assert(bs23.count == 23) 33 - XCTAssertEqual(CBOR.encode(bs23, asByteString: true), [0x57] + bs23) 34 - let bs24 = bs23 + [0xaa] 35 - XCTAssertEqual(CBOR.encode(bs24, asByteString: true), [0x58, 24] + bs24) 36 - 37 - // non-UInt8, raw bytes (reversed). 38 - XCTAssertEqual(CBOR.encode([UInt16]([240]), asByteString: true), [0x41, 0x00, 0xf0]) 39 - } 40 - 41 - func testEncodeData() { 42 - XCTAssertEqual(CBOR.encode(Data()), [0x40]) 43 - XCTAssertEqual(CBOR.encode(Data([0xf0])), [0x41, 0xf0]) 44 - XCTAssertEqual(CBOR.encode(Data([0x01, 0x02, 0x03, 0x04])), [0x44, 0x01, 0x02, 0x03, 0x04]) 45 - let bs23 = Data([0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xaa]) 46 - assert(bs23.count == 23) 47 - XCTAssertEqual(CBOR.encode(bs23), [0x57] + bs23) 48 - let bs24 = Data(bs23 + [0xaa]) 49 - XCTAssertEqual(CBOR.encode(bs24), [0x58, 24] + bs24) 50 - 51 - // non-UInt8, raw bytes (reversed). 52 - XCTAssertEqual(CBOR.encode([UInt16]([240]), asByteString: true), [0x41, 0x00, 0xf0]) 53 - } 54 - 55 - func testEncodeUtf8Strings() { 56 - XCTAssertEqual("".encode(), [0x60]) 57 - XCTAssertEqual("a".encode(), [0x61, 0x61]) 58 - XCTAssertEqual("B".encode(), [0x61, 0x42]) 59 - XCTAssertEqual(try! CBOR.decode("B".encode()), try! CBOR.decode([0x78, 1, 0x42])) 60 - XCTAssertEqual("ABC".encode(), [0x63, 0x41, 0x42, 0x43]) 61 - XCTAssertEqual(try! CBOR.decode("ABC".encode()), try! CBOR.decode([0x79, 0x00, 3, 0x41, 0x42, 0x43])) 62 - XCTAssertEqual("IETF".encode(), [0x64, 0x49, 0x45, 0x54, 0x46]) 63 - XCTAssertEqual("今日は".encode(), [0x69, 0xE4, 0xBB, 0x8A, 0xE6, 0x97, 0xA5, 0xE3, 0x81, 0xAF]) 64 - XCTAssertEqual("♨️français;日本語!Longer text\n with break?".encode(), [0x78, 0x34, 0xe2, 0x99, 0xa8, 0xef, 0xb8, 0x8f, 0x66, 0x72, 0x61, 0x6e, 0xc3, 0xa7, 0x61, 0x69, 0x73, 0x3b, 0xe6, 0x97, 0xa5, 0xe6, 0x9c, 0xac, 0xe8, 0xaa, 0x9e, 0xef, 0xbc, 0x81, 0x4c, 0x6f, 0x6e, 0x67, 0x65, 0x72, 0x20, 0x74, 0x65, 0x78, 0x74, 0x0a, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x62, 0x72, 0x65, 0x61, 0x6b, 0x3f]) 65 - XCTAssertEqual("\"\\".encode(), [0x62, 0x22, 0x5c]) 66 - XCTAssertEqual("\u{6C34}".encode(), [0x63, 0xe6, 0xb0, 0xb4]) 67 - XCTAssertEqual("水".encode(), [0x63, 0xe6, 0xb0, 0xb4]) 68 - XCTAssertEqual("\u{00fc}".encode(), [0x62, 0xc3, 0xbc]) 69 - XCTAssertEqual("abc\n123".encode(), [0x67, 0x61, 0x62, 0x63, 0x0a, 0x31, 0x32, 0x33]) 70 - } 71 - 72 - func testEncodeArrays() { 73 - XCTAssertEqual(CBOR.encode(Array<Int>()), [0x80]) 74 - XCTAssertEqual(Array<Int>().encode(), [0x80]) 75 - 76 - XCTAssertEqual(CBOR.encode([1, 2, 3]), [0x83, 0x01, 0x02, 0x03]) 77 - XCTAssertEqual([1, 2, 3].encode(), [0x83, 0x01, 0x02, 0x03]) 78 - 79 - let arr: [[UInt64]] = [[1], [2, 3], [4, 5]] 80 - 81 - let wrapped = arr.map{ inner in return CBOR.array(inner.map{ return CBOR.unsignedInt($0) })} 82 - XCTAssertEqual(CBOR.encode(wrapped), [0x83, 0x81, 0x01, 0x82, 0x02, 0x03, 0x82, 0x04, 0x05]) 83 - 84 - let arr25Enc: [UInt8] = [0x98,0x19,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x18,0x18,0x19] 85 - XCTAssertEqual(CBOR.encode(Array<Int>(1...25)), arr25Enc) 86 - } 87 - 88 - func testEncodeMaps() { 89 - XCTAssertEqual(CBOR.encode(Dictionary<Int, Int>()), [0xa0]) 90 - 91 - let encoded = CBOR.encode([1: 2, 3: 4]) 92 - XCTAssert(encoded == [0xa2, 0x01, 0x02, 0x03, 0x04] || encoded == [0xa2, 0x03, 0x04, 0x01, 0x02]) 93 - 94 - let arr1: CBOR = [1] 95 - let arr2: CBOR = [2,3] 96 - let nestedEnc: [UInt8] = CBOR.encode(["a": arr1, "b": arr2]) 97 - let encodedAFirst: [UInt8] = [0xa2, 0x61, 0x61, 0x81, 0x01, 0x61, 0x62, 0x82, 0x02, 0x03] 98 - let encodedBFirst: [UInt8] = [0xa2, 0x61, 0x62, 0x82, 0x02, 0x03, 0x61, 0x61, 0x81, 0x01] 99 - XCTAssert(nestedEnc == encodedAFirst || nestedEnc == encodedBFirst) 100 - 101 - let mapToAny: [String: Any] = [ 102 - "a": 1, 103 - "b": [2, 3] 104 - ] 105 - let encodedMapToAny = try! CBOR.encodeMap(mapToAny) 106 - XCTAssertEqual(encodedMapToAny, [0xa2, 0x61, 0x61, 0x01, 0x61, 0x62, 0x82, 0x02, 0x03]) 107 - 108 - let mapToAnyWithIntKeys: [Int: Any] = [ 109 - 12: 1, 110 - 51: "testing" 111 - ] 112 - XCTAssertThrowsError(try CBOR.encodeMap(mapToAnyWithIntKeys, options: CBOROptions(forbidNonStringMapKeys: true))) { err in 113 - XCTAssertEqual(err as! CBOREncoderError, CBOREncoderError.nonStringKeyInMap) 114 - } 115 - } 116 - 117 - func testEncodeTagged() { 118 - let bignum: [UInt8] = [0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] // 2**64 119 - let bignumCBOR = CBOR.byteString(bignum) 120 - XCTAssertEqual(CBOR.encodeTagged(tag: .positiveBignum, value: bignumCBOR), [0xc2, 0x49] + bignum) 121 - XCTAssertEqual(CBOR.encodeTagged(tag: .init(rawValue: UInt64.max), value: bignumCBOR), [0xdb, 255, 255, 255, 255, 255, 255, 255, 255, 0x49] + bignum) 122 - } 123 - 124 - func testEncodeSimple() { 125 - XCTAssertEqual(false.encode(), [0xf4]) 126 - XCTAssertEqual(true.encode(), [0xf5]) 127 - XCTAssertEqual(CBOR.null.encode(), [0xf6]) 128 - XCTAssertEqual(CBOR.undefined.encode(), [0xf7]) 129 - XCTAssertEqual(CBOR.simple(16).encode(), [0xf0]) 130 - XCTAssertEqual(CBOR.simple(24).encode(), [0xf8, 0x18]) 131 - XCTAssertEqual(CBOR.simple(255).encode(), [0xf8, 0xff]) 132 - XCTAssertEqual(CBOR.break.encode(), [0xff]) 133 - } 134 - 135 - func testEncodeFloats() { 136 - // The following tests are modifications of examples of Float16 in the RFC 137 - XCTAssertEqual(Float(0.0).encode(), [0xfa,0x00, 0x00, 0x00, 0x00]) 138 - XCTAssertEqual(Float(-0.0).encode(), [0xfa, 0x80, 0x00, 0x00, 0x00]) 139 - XCTAssertEqual(Float(1.0).encode(), [0xfa, 0x3f, 0x80, 0x00, 0x00]) 140 - XCTAssertEqual(Float(1.5).encode(), [0xfa,0x3f,0xc0, 0x00,0x00]) 141 - XCTAssertEqual(Float(65504.0).encode(), [0xfa, 0x47, 0x7f, 0xe0, 0x00]) 142 - 143 - // The following are seen as Float32s in the RFC 144 - XCTAssertEqual(Float(100000.0).encode(), [0xfa,0x47,0xc3,0x50,0x00]) 145 - XCTAssertEqual(Float(3.4028234663852886e+38).encode(), [0xfa, 0x7f, 0x7f, 0xff, 0xff]) 146 - 147 - // The following are seen as Doubles in the RFC 148 - XCTAssertEqual(Double(1.1).encode(), [0xfb,0x3f,0xf1,0x99,0x99,0x99,0x99,0x99,0x9a]) 149 - XCTAssertEqual(Double(-4.1).encode(), [0xfb, 0xc0, 0x10, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66]) 150 - XCTAssertEqual(CBOR.encode(1.0e+300), [0xfb, 0x7e, 0x37, 0xe4, 0x3c, 0x88, 0x00, 0x75, 0x9c]) 151 - XCTAssertEqual(Double(5.960464477539063e-8).encode(), [0xfb, 0x3e, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]) 152 - 153 - // Special values 154 - XCTAssertEqual(Float.infinity.encode(), [0xfa, 0x7f, 0x80, 0x00, 0x00]) 155 - XCTAssertEqual(CBOR.encode(-Float.infinity), [0xfa, 0xff, 0x80, 0x00, 0x00]) 156 - XCTAssertEqual(Double.infinity.encode(), [0xfb, 0x7f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]) 157 - XCTAssertEqual(CBOR.encode(-Double.infinity), [0xfb, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]) 158 - XCTAssertEqual(Float.nan.encode(), [0xfa,0x7f, 0xc0, 0x00, 0x00]) 159 - XCTAssertEqual(Double.nan.encode(), [0xfb, 0x7f, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]) 160 - 161 - // Swift's floating point literals are read as Doubles unless specifically specified. e.g. 162 - XCTAssertEqual(CBOR.encode(0.0), [0xfb,0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]) 163 - } 164 - 165 - func testEncodeIndefiniteArrays() { 166 - var indefArray = CBOR.encodeArrayStreamStart() 167 - XCTAssertEqual(indefArray, [0x9f]) 168 - let a: [Int] = [1, 2] 169 - indefArray.append(contentsOf: CBOR.encodeArrayChunk(a)) // this encode a definite array! 170 - // send current indef array (without close. the receiver would be programmed to anticipate this. 171 - indefArray.append(contentsOf: 3.encode()) 172 - indefArray.append(contentsOf: CBOR.encodeStreamEnd()) 173 - XCTAssertEqual(indefArray, [0x9f, 0x01, 0x02, 0x03, 0xff]) 174 - 175 - indefArray.removeLast() // remove stream end 176 - let innerArray = [UInt8]([1,2,3]) 177 - indefArray.append(contentsOf: CBOR.encodeArrayStreamStart() + CBOR.encodeArrayChunk(innerArray)) 178 - indefArray.append(contentsOf: CBOR.encodeStreamEnd()) // close inner array 179 - indefArray.append(contentsOf: CBOR.encodeStreamEnd()) // close outer 180 - XCTAssertEqual(indefArray, [0x9f, 0x01, 0x02, 0x03, 0x9f, 0x01, 0x02, 0x03, 0xff, 0xff]) 181 - } 182 - 183 - func testEncodeIndefiniteMaps() { 184 - XCTAssertEqual(CBOR.encodeMapStreamStart(), [0xbf]) 185 - let map: [String: Int] = ["a": 1] 186 - let map2 = ["B": 2] 187 - let a1_enc: [UInt8] = [0x61, 0x61, 0x01] 188 - let b2_enc: [UInt8] = [0x61, 0x42, 0x02] 189 - let final: [UInt8] = CBOR.encodeMapStreamStart() + CBOR.encodeMapChunk(map) + CBOR.encodeMapChunk(map2) + CBOR.encodeStreamEnd() 190 - XCTAssertEqual(final, [0xbf] + a1_enc + b2_enc + [0xff]) 191 - } 192 - 193 - func testEncodeIndefiniteStrings() { 194 - XCTAssertEqual(CBOR.encodeStringStreamStart(), [0x7f]) 195 - let s = "a" 196 - let t = "B" 197 - let st_enc: [UInt8] = [0x7f, 0x61, 0x61, 0x61, 0x42, 0xff] 198 - XCTAssertEqual(CBOR.encodeStringStreamStart() + CBOR.encode(s) + CBOR.encode(t) + CBOR.encodeStreamEnd(), st_enc) 199 - } 200 - 201 - func testEncodeIndefiniteByteStrings() { 202 - XCTAssertEqual(CBOR.encodeByteStringStreamStart(), [0x5f]) 203 - let bs: [UInt8] = [0xf0] 204 - let bs2: [UInt8] = [0xff] 205 - let cbor: [UInt8] = [0x5f, 0x41, 0xf0, 0x41, 0xff, 0xff] 206 - let encoded = CBOR.encodeByteStringStreamStart() 207 - + CBOR.encode(bs, asByteString: true) 208 - + CBOR.encode(bs2, asByteString: true) 209 - + CBOR.encodeStreamEnd() 210 - XCTAssertEqual(encoded, cbor) 211 - } 212 - 213 - func testEncodeDates() { 214 - let dateFormatter = DateFormatter() 215 - dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ssZ" 216 - dateFormatter.locale = Locale(identifier: "en_US_POSIX") 217 - dateFormatter.timeZone = TimeZone(secondsFromGMT: 0) 218 - let dateOne = dateFormatter.date(from: "2013-03-21T20:04:00+00:00")! 219 - XCTAssertEqual(CBOR.encodeDate(dateOne), [0xc1, 0x1a, 0x51, 0x4b, 0x67, 0xb0]) 220 - 221 - let dateTwo = Date(timeIntervalSince1970: 1363896240.5) 222 - XCTAssertEqual(CBOR.encodeDate(dateTwo), [0xc1, 0xfb, 0x41, 0xd4, 0x52, 0xd9, 0xec, 0x20, 0x00, 0x00]) 223 - 224 - let dateAsMap = Date(timeIntervalSince1970: 1363896240.5) 225 - XCTAssertEqual( 226 - CBOR.encodeDate(dateAsMap, options: CBOROptions(dateStrategy: .annotatedMap)), 227 - [0xa2, 0x66, 0x5f, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x74, 0x64, 0x61, 0x74, 0x65, 0x5f, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x67, 0x5f, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0xfb, 0x41, 0xd4, 0x52, 0xd9, 0xec, 0x20, 0x00, 0x00] 228 - ) 229 - 230 - let oldDateAsMap = Date(timeIntervalSince1970: -156896240.5) 231 - XCTAssertEqual( 232 - CBOR.encodeDate(oldDateAsMap, options: CBOROptions(dateStrategy: .annotatedMap)), 233 - [0xa2, 0x66, 0x5f, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x74, 0x64, 0x61, 0x74, 0x65, 0x5f, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x67, 0x5f, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0xfb, 0xc1, 0xa2, 0xb4, 0x17, 0xe1, 0x00, 0x00, 0x00] 234 - ) 235 - } 236 - 237 - func testReadmeExamples() { 238 - XCTAssertEqual(100.encode(), [0x18, 0x64]) 239 - XCTAssertEqual(CBOR.encode(100), [0x18, 0x64]) 240 - XCTAssertEqual("hello".encode(), [0x65, 0x68, 0x65, 0x6c, 0x6c, 0x6f]) 241 - XCTAssertEqual(CBOR.encode(["a", "b", "c"]), [0x83, 0x61, 0x61, 0x61, 0x62, 0x61, 0x63]) 242 - 243 - struct MyStruct: CBOREncodable { 244 - var x: Int 245 - var y: String 246 - 247 - public func encode(options: CBOROptions = CBOROptions()) -> [UInt8] { 248 - let cborWrapper: CBOR = [ 249 - "x": CBOR(integerLiteral: self.x), 250 - "y": .utf8String(self.y) 251 - ] 252 - return cborWrapper.encode(options: options) 253 - } 254 - 255 - public func toCBOR(options: CBOROptions = CBOROptions()) -> CBOR { 256 - return CBOR(dictionaryLiteral:("x", CBOR(integerLiteral: self.x)), ("y", .utf8String(self.y))) 257 - } 258 - } 259 - 260 - let encoded = MyStruct(x: 42, y: "words").encode() 261 - XCTAssert( 262 - encoded == [0xa2, 0x61, 0x79, 0x65, 0x77, 0x6f, 0x72, 0x64, 0x73, 0x61, 0x78, 0x18, 0x2a] 263 - || encoded == [0xa2, 0x61, 0x78, 0x18, 0x2a, 0x61, 0x79, 0x65, 0x77, 0x6f, 0x72, 0x64, 0x73] 264 - ) 265 - } 266 - 267 - func testEncodeAny() { 268 - struct MyCodableThing: Codable, Equatable { 269 - var zipcode: String 270 - var locationId: Int 271 - 272 - static func random() -> MyCodableThing { 273 - let formatter = NumberFormatter() 274 - formatter.minimumIntegerDigits = 5 275 - let randomInt = Int.random(in: 0..<99999) 276 - let zip = formatter.string(from: NSNumber(integerLiteral: randomInt))! 277 - return MyCodableThing(zipcode: zip, locationId: Int.random(in: 0..<1000)) 278 - } 279 - } 280 - 281 - let myCodableThing = MyCodableThing.random() 282 - 283 - let encoded = try! CBOR.encodeAny(myCodableThing) 284 - let decoded = try! CodableCBORDecoder().decode(MyCodableThing.self, from: Data(encoded)) 285 - XCTAssertEqual(decoded, myCodableThing) 286 - } 287 - }
-61
Old/SwiftCBORTests-old/CBORTests.swift
··· 1 - import XCTest 2 - @testable import SwiftCBOR 3 - 4 - class CBORTests: XCTestCase { 5 - func testSubscriptSetter() { 6 - let dictionary: [String: Any] = [ 7 - "foo": 1, 8 - "bar": "a", 9 - "zwii": "hd", 10 - "tags": [ 11 - "a": "1", 12 - "b": 2 13 - ] 14 - ] 15 - 16 - let cborEncoded: [UInt8] = try! CBOR.encodeMap(dictionary) 17 - var cbor = try! CBOR.decode(cborEncoded)! 18 - cbor["foo"] = "changed" 19 - XCTAssertEqual(cbor["foo"], "changed") 20 - } 21 - 22 - func testNestedSubscriptSetter() { 23 - let dictionary: [String: Any] = [ 24 - "foo": 1, 25 - "bar": "a", 26 - "zwii": "hd", 27 - "tags": [ 28 - "a": "1", 29 - "b": 2 30 - ] 31 - ] 32 - 33 - let cborEncoded: [UInt8] = try! CBOR.encodeMap(dictionary) 34 - var cbor = try! CBOR.decode(cborEncoded)! 35 - cbor["tags"]?[2] = "changed" 36 - XCTAssertEqual(cbor["tags"]?[2], "changed") 37 - } 38 - 39 - func testNestedSubscriptSetterWithNewMap() { 40 - let dictionary: [String: Any] = [ 41 - "foo": 1, 42 - "bar": "a", 43 - "zwii": "hd", 44 - "tags": [ 45 - "a": "1", 46 - "b": 2 47 - ] 48 - ] 49 - 50 - let cborEncoded: [UInt8] = try! CBOR.encodeMap(dictionary) 51 - var cbor = try! CBOR.decode(cborEncoded)! 52 - 53 - let nestedMap: [CBOR: CBOR] = [ 54 - "joe": "schmoe", 55 - "age": 56 56 - ] 57 - 58 - cbor["tags"]?[2] = CBOR.map(nestedMap) 59 - XCTAssertEqual(cbor["tags"]?[2], CBOR.map(nestedMap)) 60 - } 61 - }
-128
Old/SwiftCBORTests-old/CodableCBORDecoderTests.swift
··· 1 - import XCTest 2 - @testable import SwiftCBOR 3 - 4 - class CodableCBORDecoderTests: XCTestCase { 5 - func testDecodeNull() { 6 - let decoded = try! CodableCBORDecoder().decode(Optional<String>.self, from: Data([0xf6])) 7 - XCTAssertNil(decoded) 8 - } 9 - 10 - func testDecodeBools() { 11 - let falseVal = try! CodableCBORDecoder().decode(Bool.self, from: Data([0xf4])) 12 - XCTAssertEqual(falseVal, false) 13 - let trueVal = try! CodableCBORDecoder().decode(Bool.self, from: Data([0xf5])) 14 - XCTAssertEqual(trueVal, true) 15 - } 16 - 17 - func testDecodeInts() { 18 - // Less than 24 19 - let zero = try! CodableCBORDecoder().decode(Int.self, from: Data([0x00])) 20 - XCTAssertEqual(zero, 0) 21 - let eight = try! CodableCBORDecoder().decode(Int.self, from: Data([0x08])) 22 - XCTAssertEqual(eight, 8) 23 - let ten = try! CodableCBORDecoder().decode(Int.self, from: Data([0x0a])) 24 - XCTAssertEqual(ten, 10) 25 - let twentyThree = try! CodableCBORDecoder().decode(Int.self, from: Data([0x17])) 26 - XCTAssertEqual(twentyThree, 23) 27 - 28 - // Just bigger than 23 29 - let twentyFour = try! CodableCBORDecoder().decode(Int.self, from: Data([0x18, 0x18])) 30 - XCTAssertEqual(twentyFour, 24) 31 - let twentyFive = try! CodableCBORDecoder().decode(Int.self, from: Data([0x18, 0x19])) 32 - XCTAssertEqual(twentyFive, 25) 33 - 34 - // Bigger 35 - let hundred = try! CodableCBORDecoder().decode(Int.self, from: Data([0x18, 0x64])) 36 - XCTAssertEqual(hundred, 100) 37 - let thousand = try! CodableCBORDecoder().decode(Int.self, from: Data([0x19, 0x03, 0xe8])) 38 - XCTAssertEqual(thousand, 1_000) 39 - let million = try! CodableCBORDecoder().decode(Int.self, from: Data([0x1a, 0x00, 0x0f, 0x42, 0x40])) 40 - XCTAssertEqual(million, 1_000_000) 41 - let trillion = try! CodableCBORDecoder().decode(Int.self, from: Data([0x1b, 0x00, 0x00, 0x00, 0xe8, 0xd4, 0xa5, 0x10, 0x00])) 42 - XCTAssertEqual(trillion, 1_000_000_000_000) 43 - 44 - // TODO: Tagged byte strings for big numbers 45 - // let bigNum = try! CodableCBORDecoder().decode(Int.self, from: Data([0x1b, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff])) 46 - // XCTAssertEqual(bigNum, 18_446_744_073_709_551_615) 47 - // let biggerNum = try! CodableCBORDecoder().decode(Int.self, from: Data([0x2c, 0x49, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,])) 48 - // XCTAssertEqual(biggerNum, 18_446_744_073_709_551_616) 49 - } 50 - 51 - func testDecodeNegativeInts() { 52 - // Less than 24 53 - let minusOne = try! CodableCBORDecoder().decode(Int.self, from: Data([0x20])) 54 - XCTAssertEqual(minusOne, -1) 55 - let minusTen = try! CodableCBORDecoder().decode(Int.self, from: Data([0x29])) 56 - XCTAssertEqual(minusTen, -10) 57 - 58 - // Bigger 59 - let minusHundred = try! CodableCBORDecoder().decode(Int.self, from: Data([0x38, 0x63])) 60 - XCTAssertEqual(minusHundred, -100) 61 - let minusThousand = try! CodableCBORDecoder().decode(Int.self, from: Data([0x39, 0x03, 0xe7])) 62 - XCTAssertEqual(minusThousand, -1_000) 63 - 64 - // TODO: Tagged byte strings for big numbers 65 - // let bigNum = try! CodableCBORDecoder().decode(Int.self, from: Data([0x1b, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff])) 66 - // XCTAssertEqual(bigNum, 18_446_744_073_709_551_615) 67 - // let biggerNum = try! CodableCBORDecoder().decode(Int.self, from: Data([0x2c, 0x49, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,])) 68 - // XCTAssertEqual(biggerNum, 18_446_744_073_709_551_616) 69 - } 70 - 71 - func testDecodeStrings() { 72 - let empty = try! CodableCBORDecoder().decode(String.self, from: Data([0x60])) 73 - XCTAssertEqual(empty, "") 74 - let a = try! CodableCBORDecoder().decode(String.self, from: Data([0x61, 0x61])) 75 - XCTAssertEqual(a, "a") 76 - let IETF = try! CodableCBORDecoder().decode(String.self, from: Data([0x64, 0x49, 0x45, 0x54, 0x46])) 77 - XCTAssertEqual(IETF, "IETF") 78 - let quoteSlash = try! CodableCBORDecoder().decode(String.self, from: Data([0x62, 0x22, 0x5c])) 79 - XCTAssertEqual(quoteSlash, "\"\\") 80 - let littleUWithDiaeresis = try! CodableCBORDecoder().decode(String.self, from: Data([0x62, 0xc3, 0xbc])) 81 - XCTAssertEqual(littleUWithDiaeresis, "\u{00FC}") 82 - 83 - } 84 - 85 - func testDecodeByteStrings() { 86 - let fourByteByteString = try! CodableCBORDecoder().decode(Data.self, from: Data([0x44, 0x01, 0x02, 0x03, 0x04])) 87 - XCTAssertEqual(fourByteByteString, Data([0x01, 0x02, 0x03, 0x04])) 88 - let indefiniteByteSting = try! CodableCBORDecoder().decode(Data.self, from: Data([0x5f, 0x42, 0x01, 0x02, 0x43, 0x03, 0x04, 0x05, 0xff])) 89 - XCTAssertEqual(indefiniteByteSting, Data([0x01, 0x02, 0x03, 0x04, 0x05])) 90 - } 91 - 92 - func testDecodeArrays() { 93 - let empty = try! CodableCBORDecoder().decode([String].self, from: Data([0x80])) 94 - XCTAssertEqual(empty, []) 95 - let oneTwoThree = try! CodableCBORDecoder().decode([Int].self, from: Data([0x83, 0x01, 0x02, 0x03])) 96 - XCTAssertEqual(oneTwoThree, [1, 2, 3]) 97 - let lotsOfInts = try! CodableCBORDecoder().decode([Int].self, from: Data([0x98, 0x19, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x18, 0x18, 0x19])) 98 - XCTAssertEqual(lotsOfInts, [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]) 99 - let nestedSimple = try! CodableCBORDecoder().decode([[Int]].self, from: Data([0x83, 0x81, 0x01, 0x82, 0x02, 0x03, 0x82, 0x04, 0x05])) 100 - XCTAssertEqual(nestedSimple, [[1], [2, 3], [4, 5]]) 101 - let indefiniteArray = try! CodableCBORDecoder().decode([Int].self, from: Data([0x9f, 0x04, 0x05, 0xff])) 102 - XCTAssertEqual(indefiniteArray, [4, 5]) 103 - let nestedIndefiniteArrays = try! CodableCBORDecoder().decode([[Int]].self, from: Data([0x9f, 0x81, 0x01, 0x82, 0x02, 0x03, 0x9f, 0x04, 0x05, 0xff, 0xff])) 104 - XCTAssertEqual(nestedIndefiniteArrays, [[1], [2, 3], [4, 5]]) 105 - } 106 - 107 - func testDecodeMaps() { 108 - let empty = try! CodableCBORDecoder().decode([String: String].self, from: Data([0xa0])) 109 - XCTAssertEqual(empty, [:]) 110 - let stringToString = try! CodableCBORDecoder().decode([String: String].self, from: Data([0xa5, 0x61, 0x61, 0x61, 0x41, 0x61, 0x62, 0x61, 0x42, 0x61, 0x63, 0x61, 0x43, 0x61, 0x64, 0x61, 0x44, 0x61, 0x65, 0x61, 0x45])) 111 - XCTAssertEqual(stringToString, ["a": "A", "b": "B", "c": "C", "d": "D", "e": "E"]) 112 - let oneTwoThreeFour = try! CodableCBORDecoder().decode([Int: Int].self, from: Data([0xa2, 0x01, 0x02, 0x03, 0x04])) 113 - XCTAssertEqual(oneTwoThreeFour, [1: 2, 3: 4]) 114 - let indefiniteMap = try! CodableCBORDecoder().decode([String: String].self, from: Data([0xbf, 0x63, 0x46, 0x75, 0x6e, 0x61, 0x62, 0x63, 0x41, 0x6d, 0x74, 0x61, 0x63, 0xff])) 115 - XCTAssertEqual(indefiniteMap, ["Fun": "b", "Amt": "c"]) 116 - let nestedIndefiniteMap = try! CodableCBORDecoder().decode([String: [String: String]].self, from: Data([0xbf, 0x63, 0x46, 0x75, 0x6e, 0xa1, 0x61, 0x62, 0x61, 0x42, 0x63, 0x41, 0x6d, 0x74, 0xbf, 0x61, 0x63, 0x61, 0x43, 0xff, 0xff])) 117 - XCTAssertEqual(nestedIndefiniteMap, ["Fun": ["b": "B"], "Amt": ["c": "C"]]) 118 - } 119 - 120 - func testDecodeDates() { 121 - let expectedDateOne = Date(timeIntervalSince1970: 1363896240) 122 - let dateOne = try! CodableCBORDecoder().decode(Date.self, from: Data([0xc1, 0x1a, 0x51, 0x4b, 0x67, 0xb0])) 123 - XCTAssertEqual(dateOne, expectedDateOne) 124 - let expectedDateTwo = Date(timeIntervalSince1970: 1363896240.5) 125 - let dateTwo = try! CodableCBORDecoder().decode(Date.self, from: Data([0xc1, 0xfb, 0x41, 0xd4, 0x52, 0xd9, 0xec, 0x20, 0x00, 0x00])) 126 - XCTAssertEqual(dateTwo, expectedDateTwo) 127 - } 128 - }
-141
Old/SwiftCBORTests-old/CodableCBOREncoderTests.swift
··· 1 - import XCTest 2 - @testable import SwiftCBOR 3 - 4 - class CodableCBOREncoderTests: XCTestCase { 5 - func testEncodeNull() { 6 - let encoded = try! CodableCBOREncoder().encode(Optional<String>(nil)) 7 - XCTAssertEqual(encoded, Data([0xf6])) 8 - } 9 - 10 - func testEncodeBools() { 11 - let falseVal = try! CodableCBOREncoder().encode(false) 12 - XCTAssertEqual(falseVal, Data([0xf4])) 13 - let trueVal = try! CodableCBOREncoder().encode(true) 14 - XCTAssertEqual(trueVal, Data([0xf5])) 15 - } 16 - 17 - func testEncodeInts() { 18 - // Less than 24 19 - let zero = try! CodableCBOREncoder().encode(0) 20 - XCTAssertEqual(zero, Data([0x00])) 21 - let eight = try! CodableCBOREncoder().encode(8) 22 - XCTAssertEqual(eight, Data([0x08])) 23 - let ten = try! CodableCBOREncoder().encode(10) 24 - XCTAssertEqual(ten, Data([0x0a])) 25 - let twentyThree = try! CodableCBOREncoder().encode(23) 26 - XCTAssertEqual(twentyThree, Data([0x17])) 27 - 28 - // Just bigger than 23 29 - let twentyFour = try! CodableCBOREncoder().encode(24) 30 - XCTAssertEqual(twentyFour, Data([0x18, 0x18])) 31 - let twentyFive = try! CodableCBOREncoder().encode(25) 32 - XCTAssertEqual(twentyFive, Data([0x18, 0x19])) 33 - 34 - // Bigger 35 - let hundred = try! CodableCBOREncoder().encode(100) 36 - XCTAssertEqual(hundred, Data([0x18, 0x64])) 37 - let thousand = try! CodableCBOREncoder().encode(1_000) 38 - XCTAssertEqual(thousand, Data([0x19, 0x03, 0xe8])) 39 - let million = try! CodableCBOREncoder().encode(1_000_000) 40 - XCTAssertEqual(million, Data([0x1a, 0x00, 0x0f, 0x42, 0x40])) 41 - let trillion = try! CodableCBOREncoder().encode(1_000_000_000_000) 42 - XCTAssertEqual(trillion, Data([0x1b, 0x00, 0x00, 0x00, 0xe8, 0xd4, 0xa5, 0x10, 0x00])) 43 - 44 - // TODO: Tagged byte strings for big numbers 45 - // let bigNum = try! CodableCBORDecoder().decode(Int.self, from: Data([0x1b, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff])) 46 - // XCTAssertEqual(bigNum, 18_446_744_073_709_551_615) 47 - // let biggerNum = try! CodableCBORDecoder().decode(Int.self, from: Data([0x2c, 0x49, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,])) 48 - // XCTAssertEqual(biggerNum, 18_446_744_073_709_551_616) 49 - } 50 - 51 - func testEncodeNegativeInts() { 52 - // Less than 24 53 - let minusOne = try! CodableCBOREncoder().encode(-1) 54 - XCTAssertEqual(minusOne, Data([0x20])) 55 - let minusTen = try! CodableCBOREncoder().encode(-10) 56 - XCTAssertEqual(minusTen, Data([0x29])) 57 - 58 - // Bigger 59 - let minusHundred = try! CodableCBOREncoder().encode(-100) 60 - XCTAssertEqual(minusHundred, Data([0x38, 0x63])) 61 - let minusThousand = try! CodableCBOREncoder().encode(-1_000) 62 - XCTAssertEqual(minusThousand, Data([0x39, 0x03, 0xe7])) 63 - 64 - // TODO: Tagged byte strings for big negative numbers 65 - // let bigNum = try! CodableCBORDecoder().decode(Int.self, from: Data([0x1b, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff])) 66 - // XCTAssertEqual(bigNum, 18_446_744_073_709_551_615) 67 - // let biggerNum = try! CodableCBORDecoder().decode(Int.self, from: Data([0x2c, 0x49, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,])) 68 - // XCTAssertEqual(biggerNum, 18_446_744_073_709_551_616) 69 - } 70 - 71 - func testEncodeStrings() { 72 - let empty = try! CodableCBOREncoder().encode("") 73 - XCTAssertEqual(empty, Data([0x60])) 74 - let a = try! CodableCBOREncoder().encode("a") 75 - XCTAssertEqual(a, Data([0x61, 0x61])) 76 - let IETF = try! CodableCBOREncoder().encode("IETF") 77 - XCTAssertEqual(IETF, Data([0x64, 0x49, 0x45, 0x54, 0x46])) 78 - let quoteSlash = try! CodableCBOREncoder().encode("\"\\") 79 - XCTAssertEqual(quoteSlash, Data([0x62, 0x22, 0x5c])) 80 - let littleUWithDiaeresis = try! CodableCBOREncoder().encode("\u{00FC}") 81 - XCTAssertEqual(littleUWithDiaeresis, Data([0x62, 0xc3, 0xbc])) 82 - } 83 - 84 - func testEncodeByteStrings() { 85 - let fourByteByteString = try! CodableCBOREncoder().encode(Data([0x01, 0x02, 0x03, 0x04])) 86 - XCTAssertEqual(fourByteByteString, Data([0x44, 0x01, 0x02, 0x03, 0x04])) 87 - } 88 - 89 - func testEncodeArrays() { 90 - let empty = try! CodableCBOREncoder().encode([String]()) 91 - XCTAssertEqual(empty, Data([0x80])) 92 - let oneTwoThree = try! CodableCBOREncoder().encode([1, 2, 3]) 93 - XCTAssertEqual(oneTwoThree, Data([0x83, 0x01, 0x02, 0x03])) 94 - let lotsOfInts = try! CodableCBOREncoder().encode([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]) 95 - XCTAssertEqual(lotsOfInts, Data([0x98, 0x19, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x18, 0x18, 0x19])) 96 - let nestedSimple = try! CodableCBOREncoder().encode([[1], [2, 3], [4, 5]]) 97 - XCTAssertEqual(nestedSimple, Data([0x83, 0x81, 0x01, 0x82, 0x02, 0x03, 0x82, 0x04, 0x05])) 98 - } 99 - 100 - func testEncodeMaps() { 101 - let empty = try! CodableCBOREncoder().encode([String: String]()) 102 - XCTAssertEqual(empty, Data([0xa0])) 103 - let stringToString = try! CodableCBOREncoder().encode(["a": "A", "b": "B", "c": "C", "d": "D", "e": "E"]) 104 - XCTAssertEqual(stringToString.first!, 0xa5) 105 - let dataMinusFirstByte = stringToString[1...].map { $0 }.chunked(into: 4).sorted(by: { $0.lexicographicallyPrecedes($1) }) 106 - let dataForKeyValuePairs: [[UInt8]] = [[0x61, 0x61, 0x61, 0x41], [0x61, 0x62, 0x61, 0x42], [0x61, 0x63, 0x61, 0x43], [0x61, 0x64, 0x61, 0x44], [0x61, 0x65, 0x61, 0x45]] 107 - XCTAssertEqual(dataMinusFirstByte, dataForKeyValuePairs) 108 - let oneTwoThreeFour = try! CodableCBOREncoder().encode([1: 2, 3: 4]) 109 - XCTAssert( 110 - oneTwoThreeFour == Data([0xa2, 0x01, 0x02, 0x03, 0x04]) 111 - || oneTwoThreeFour == Data([0xa2, 0x03, 0x04, 0x01, 0x02]) 112 - ) 113 - 114 - let encoder = CodableCBOREncoder() 115 - encoder.useStringKeys = true 116 - let encodedWithStringKeys = try! encoder.encode([1: 2, 3: 4]) 117 - XCTAssert(encodedWithStringKeys == Data([0xa2, 0x61, 0x31, 0x02, 0x61, 0x33, 0x04]) || encodedWithStringKeys == Data([0xa2, 0x61, 0x33, 0x04, 0x61, 0x31, 0x02])) 118 - } 119 - 120 - func testEncodeSimpleStructs() { 121 - struct MyStruct: Codable { 122 - let age: Int 123 - let name: String 124 - } 125 - 126 - let encoded = try! CodableCBOREncoder().encode(MyStruct(age: 27, name: "Ham")).map { $0 } 127 - 128 - XCTAssert( 129 - encoded == [0xa2, 0x63, 0x61, 0x67, 0x65, 0x18, 0x1b, 0x64, 0x6e, 0x61, 0x6d, 0x65, 0x63, 0x48, 0x61, 0x6d] 130 - || encoded == [0xa2, 0x64, 0x6e, 0x61, 0x6d, 0x65, 0x63, 0x48, 0x61, 0x6d, 0x63, 0x61, 0x67, 0x65, 0x18, 0x1b] 131 - ) 132 - } 133 - } 134 - 135 - extension Array { 136 - func chunked(into size: Int) -> [[Element]] { 137 - return stride(from: 0, to: count, by: size).map { 138 - Array(self[$0 ..< Swift.min($0 + size, count)]) 139 - } 140 - } 141 - }
-39
Old/SwiftCBORTests-old/Helpers.swift
··· 1 - import Foundation 2 - 3 - extension Data { 4 - init?(hex: String) { 5 - let len = hex.count / 2 6 - var data = Data(capacity: len) 7 - for i in 0..<len { 8 - let j = hex.index(hex.startIndex, offsetBy: i*2) 9 - let k = hex.index(j, offsetBy: 2) 10 - let bytes = hex[j..<k] 11 - if var num = UInt8(bytes, radix: 16) { 12 - data.append(&num, count: 1) 13 - } else { 14 - return nil 15 - } 16 - } 17 - self = data 18 - } 19 - } 20 - 21 - extension Data { 22 - var hex: String { 23 - return reduce("") { $0 + String(format: "%02x", $1) } 24 - } 25 - } 26 - 27 - extension StringProtocol { 28 - var hexaData: Data { .init(hexa) } 29 - var hexaBytes: [UInt8] { .init(hexa) } 30 - 31 - private var hexa: UnfoldSequence<UInt8, Index> { 32 - sequence(state: startIndex) { startIndex in 33 - guard startIndex < self.endIndex else { return nil } 34 - let endIndex = self.index(startIndex, offsetBy: 2, limitedBy: self.endIndex) ?? self.endIndex 35 - defer { startIndex = endIndex } 36 - return UInt8(self[startIndex..<endIndex], radix: 16) 37 - } 38 - } 39 - }
-49
Old/Util.swift
··· 1 - final class Util { 2 - // https://stackoverflow.com/questions/24465475/how-can-i-create-a-string-from-utf8-in-swift 3 - static func decodeUtf8(_ bytes: ArraySlice<UInt8>) throws -> String { 4 - var result = "" 5 - var decoder = UTF8() 6 - var generator = bytes.makeIterator() 7 - var finished = false 8 - repeat { 9 - let decodingResult = decoder.decode(&generator) 10 - switch decodingResult { 11 - case .scalarValue(let char): 12 - result.append(String(char)) 13 - case .emptyInput: 14 - finished = true 15 - case .error: 16 - throw CBORError.incorrectUTF8String 17 - } 18 - } while (!finished) 19 - return result 20 - } 21 - 22 - static func djb2Hash(_ array: [Int]) -> Int { 23 - return array.reduce(5381, { hash, elem in ((hash << 5) &+ hash) &+ Int(elem) }) 24 - } 25 - 26 - // https://gist.github.com/martinkallman/5049614 27 - // rewritten to Swift + applied fixes from comments + added NaN/Inf checks 28 - // should be good enough, who cares about float16 29 - static func readFloat16(x: UInt16) -> Float32 { 30 - if (x & 0x7fff) > 0x7c00 { 31 - return Float32.nan 32 - } 33 - if x == 0x7c00 { 34 - return Float32.infinity 35 - } 36 - if x == 0xfc00 { 37 - return -Float32.infinity 38 - } 39 - var t1 = UInt32(x & 0x7fff) // Non-sign bits 40 - var t2 = UInt32(x & 0x8000) // Sign bit 41 - let t3 = UInt32(x & 0x7c00) // Exponent 42 - t1 <<= 13 // Align mantissa on MSB 43 - t2 <<= 16 // Shift sign bit into position 44 - t1 += 0x38000000 // Adjust bias 45 - t1 = (t3 == 0 ? 0 : t1) // Denormals-as-zero 46 - t1 |= t2 // Re-insert sign bit 47 - return Float32(bitPattern: t1) 48 - } 49 - }
+4
Package.swift
··· 18 18 .product(name: "Collections", package: "swift-collections") 19 19 ] 20 20 ), 21 + .executableTarget( 22 + name: "Fuzzing", 23 + dependencies: ["CBOR"] 24 + ), 21 25 .testTarget( 22 26 name: "CBORTests", 23 27 dependencies: ["CBOR"],
+48 -32
Sources/CBOR/Decoder/CBORDecoder.swift
··· 40 40 let scanner = CBORScanner(data: reader, options: options) 41 41 try scanner.scan() 42 42 43 + guard !scanner.isEmpty else { 44 + throw ScanError.unexpectedEndOfData 45 + } 46 + 43 47 let context = DecodingContext(scanner: scanner) 44 48 let region = scanner.load(at: 0) 45 49 46 50 return try SingleValueCBORDecodingContainer(context: context, data: region).decode(T.self) 47 51 } 48 52 } catch { 49 - if let error = error as? CBORScanner.ScanError { 50 - switch error { 51 - case .unexpectedEndOfData: 52 - throw DecodingError.dataCorrupted( 53 - .init(codingPath: [], debugDescription: "Unexpected end of data.") 54 - ) 55 - case let .invalidMajorType(byte, offset): 56 - throw DecodingError.dataCorrupted(.init( 57 - codingPath: [], 58 - debugDescription: "Unexpected major type: \(String(byte, radix: 2)) at offset \(offset)" 59 - )) 60 - case let .invalidSize(byte, offset): 61 - throw DecodingError.dataCorrupted(.init( 62 - codingPath: [], 63 - debugDescription: "Unexpected size argument: \(String(byte, radix: 2)) at offset \(offset)" 64 - )) 65 - case let .expectedMajorType(offset): 66 - throw DecodingError.dataCorrupted(.init( 67 - codingPath: [], 68 - debugDescription: "Expected major type at offset \(offset)" 69 - )) 70 - case let .typeInIndeterminateString(type, offset): 71 - throw DecodingError.dataCorrupted(.init( 72 - codingPath: [], 73 - debugDescription: "Unexpected major type in indeterminate \(type) at offset \(offset)" 74 - )) 75 - case let .rejectedIndeterminateLength(type, offset): 76 - throw DecodingError.dataCorrupted(.init( 77 - codingPath: [], 78 - debugDescription: "Rejected indeterminate length type \(type) at offset \(offset)" 79 - )) 80 - } 53 + if let error = error as? ScanError { 54 + try throwScanError(error) 81 55 } else { 82 56 throw error 83 57 } 58 + } 59 + } 60 + 61 + private func throwScanError(_ error: ScanError) throws -> Never { 62 + switch error { 63 + case .unexpectedEndOfData: 64 + throw DecodingError.dataCorrupted( 65 + .init(codingPath: [], debugDescription: "Unexpected end of data.") 66 + ) 67 + case let .invalidMajorType(byte, offset): 68 + throw DecodingError.dataCorrupted(.init( 69 + codingPath: [], 70 + debugDescription: "Unexpected major type: \(String(byte, radix: 2)) at offset \(offset)" 71 + )) 72 + case let .invalidSize(byte, offset): 73 + throw DecodingError.dataCorrupted(.init( 74 + codingPath: [], 75 + debugDescription: "Unexpected size argument: \(String(byte, radix: 2)) at offset \(offset)" 76 + )) 77 + case let .expectedMajorType(offset): 78 + throw DecodingError.dataCorrupted(.init( 79 + codingPath: [], 80 + debugDescription: "Expected major type at offset \(offset)" 81 + )) 82 + case let .typeInIndeterminateString(type, offset): 83 + throw DecodingError.dataCorrupted(.init( 84 + codingPath: [], 85 + debugDescription: "Unexpected major type in indeterminate \(type) at offset \(offset)" 86 + )) 87 + case let .rejectedIndeterminateLength(type, offset): 88 + throw DecodingError.dataCorrupted(.init( 89 + codingPath: [], 90 + debugDescription: "Rejected indeterminate length type \(type) at offset \(offset)" 91 + )) 92 + case let .cannotRepresentInt(max, found, offset): 93 + throw DecodingError.dataCorrupted( 94 + .init( 95 + codingPath: [], 96 + debugDescription: "Failed to decode integer with maximum \(max), " 97 + + "found \(found) at \(offset)" 98 + ) 99 + ) 84 100 } 85 101 } 86 102 }
+44 -10
Sources/CBOR/Decoder/Containers/DataRegion.swift
··· 88 88 count >= numBytes 89 89 } 90 90 91 + @inline(__always) 92 + @inlinable 93 + func canRead(_ numBytes: Int, from index: Index) -> Bool { 94 + index + numBytes <= endIndex 95 + } 96 + 91 97 @inlinable 92 98 func readInt<T: FixedWidthInteger>(as: T.Type, argument: UInt8) throws -> T { 99 + try readInt(as: T.self, argument: argument, from: startIndex) 100 + } 101 + 102 + @inline(__always) 103 + @usableFromInline 104 + func checkIntConversion<T: FixedWidthInteger, F: FixedWidthInteger>(_ type: T.Type, val: F) throws { 105 + guard val <= T.max else { 106 + throw ScanError.cannotRepresentInt(max: UInt(T.max), found: UInt(val), offset: startIndex) 107 + } 108 + } 109 + 110 + @inlinable 111 + func readInt<T: FixedWidthInteger>(as: T.Type, argument: UInt8, from index: Index) throws -> T { 93 112 let byteCount = argument 94 - return switch byteCount { 113 + switch byteCount { 95 114 case let value where value < Constants.maxArgSize: 96 - T(value) 115 + let intVal = value 116 + try checkIntConversion(T.self, val: intVal) 117 + return T(intVal) 97 118 case 24: 98 - T(try read(as: UInt8.self)) 119 + let intVal = try read(as: UInt8.self, from: index) 120 + try checkIntConversion(T.self, val: intVal) 121 + return T(intVal) 99 122 case 25: 100 - T(try read(as: UInt16.self)) 123 + let intVal = try read(as: UInt16.self, from: index) 124 + try checkIntConversion(T.self, val: intVal) 125 + return T(intVal) 101 126 case 26: 102 - T(try read(as: UInt32.self)) 127 + let intVal = try read(as: UInt32.self, from: index) 128 + try checkIntConversion(T.self, val: intVal) 129 + return T(intVal) 103 130 case 27: 104 - T(try read(as: UInt64.self)) 131 + let intVal = try read(as: UInt64.self, from: index) 132 + try checkIntConversion(T.self, val: intVal) 133 + return T(intVal) 105 134 default: 106 - throw CBORScanner.ScanError.invalidSize(byte: byteCount, offset: startIndex) 135 + throw ScanError.invalidSize(byte: byteCount, offset: startIndex) 107 136 } 108 137 } 109 138 110 139 @inlinable 111 140 func read<F: FixedWidthInteger>(as: F.Type) throws -> F { 112 - guard canRead(F.byteCount) else { 113 - throw CBORScanner.ScanError.unexpectedEndOfData 141 + try read(as: F.self, from: startIndex) 142 + } 143 + 144 + @inlinable 145 + func read<F: FixedWidthInteger>(as: F.Type, from index: Index) throws -> F { 146 + guard canRead(F.byteCount, from: index) else { 147 + throw ScanError.unexpectedEndOfData 114 148 } 115 149 var val = F.zero 116 150 for idx in 0..<(F.byteCount) { 117 151 let shift = (F.byteCount - idx - 1) * 8 118 - val |= F(self[startIndex + idx]) << shift 152 + val |= F(self[index + idx]) << shift 119 153 } 120 154 return F(val) 121 155 }
+9 -3
Sources/CBOR/Decoder/Containers/SingleValueCBORDecodingContainer.swift
··· 52 52 try checkType(.uint, .nint) 53 53 let value = try data.readInt(as: T.self) 54 54 if data.type == .nint { 55 + guard T.min < 0 else { 56 + throw DecodingError.typeMismatch( 57 + Int.self, 58 + context.error("Found a negative integer while attempting to decode an unsigned int \(T.self).") 59 + ) 60 + } 55 61 return -1 - value 56 62 } 57 63 return value ··· 91 97 idx += 1 92 98 93 99 guard let byteCount = argument.byteCount() else { 94 - throw CBORScanner.ScanError.invalidSize(byte: argument, offset: data.globalIndex) 100 + throw ScanError.invalidSize(byte: argument, offset: data.globalIndex) 95 101 } 96 102 97 103 let utf8Start = idx + Int(byteCount) ··· 171 177 } 172 178 173 179 private func _decode(_: Data.Type) throws -> Data { 174 - try checkType(.string) 180 + try checkType(.bytes) 175 181 176 182 if data.argument == Constants.indeterminateArg { 177 183 return try decodeIndeterminateData() ··· 201 207 idx += 1 202 208 203 209 guard let byteCount = argument.byteCount() else { 204 - throw CBORScanner.ScanError.invalidSize(byte: argument, offset: data.globalIndex) 210 + throw ScanError.invalidSize(byte: argument, offset: data.globalIndex) 205 211 } 206 212 207 213 let substringStart = idx + Int(byteCount)
+36
Sources/CBOR/Decoder/Scanner/CBORScanner+DebugDescription.swift
··· 1 + // 2 + // CBORScanner+DebugDescription.swift 3 + // CBOR 4 + // 5 + // Created by Khan Winter on 8/30/25. 6 + // 7 + 8 + #if DEBUG 9 + extension CBORScanner: CustomDebugStringConvertible { 10 + @usableFromInline var debugDescription: String { 11 + var string = "" 12 + func indent(_ other: String, d: Int) { string += String(repeating: " ", count: d * 2) + other + "\n" } 13 + 14 + func gen(_ idx: Int, depth: Int) { 15 + let value = load(at: idx) 16 + switch value.type { 17 + case .map, .array: 18 + indent( 19 + "\(value.type), mapIdx: \(value.mapOffset), children: \(value.childCount!), bytes: \(value.count)", 20 + d: depth 21 + ) 22 + var idx = firstChildIndex(idx) 23 + for _ in 0..<value.childCount! { 24 + gen(idx, depth: depth + 1) 25 + idx = siblingIndex(idx) 26 + } 27 + default: 28 + indent("\(value.type), mapIdx: \(value.mapOffset), arg: \(value.argument)", d: depth) 29 + } 30 + } 31 + 32 + gen(0, depth: 0) 33 + return string 34 + } 35 + } 36 + #endif
+25
Sources/CBOR/Decoder/Scanner/CBORScanner+Utils.swift
··· 1 + // 2 + // CBORScanner+Utils.swift 3 + // CBOR 4 + // 5 + // Created by Khan Winter on 8/30/25. 6 + // 7 + 8 + extension CBORScanner { 9 + func popByteCount() throws -> Int { 10 + let byteCount = reader.popArgument() 11 + return switch byteCount { 12 + case let value where value < Constants.maxArgSize: 0 13 + case 24: 1 14 + case 25: 2 15 + case 26: 4 16 + case 27: 8 17 + default: 18 + throw ScanError.invalidSize(byte: byteCount, offset: reader.index - 1) 19 + } 20 + } 21 + 22 + func peekIsIndeterminate() -> Bool { 23 + (reader.peekArgument() ?? 0) == 0b1_1111 24 + } 25 + }
+27 -67
Sources/CBOR/Decoder/Scanner/CBORScanner.swift
··· 7 7 8 8 import Foundation 9 9 10 + @usableFromInline 11 + enum ScanError: Error { 12 + case unexpectedEndOfData 13 + case invalidMajorType(byte: UInt8, offset: Int) 14 + case invalidSize(byte: UInt8, offset: Int) 15 + case expectedMajorType(offset: Int) 16 + case typeInIndeterminateString(type: MajorType, offset: Int) 17 + case rejectedIndeterminateLength(type: MajorType, offset: Int) 18 + case cannotRepresentInt(max: UInt, found: UInt, offset: Int) 19 + } 20 + 10 21 /// # Why Scan? 11 22 /// I'd have loved to use a 'pop' method for decoding, where we only decode as data is requested. However, the way 12 23 /// Swift's decoding APIs work forces us to be able to be able to do random access for keys in maps, which requires ··· 21 32 /// take either indeterminate or specific lengths and decode them. 22 33 @usableFromInline 23 34 final class CBORScanner { 24 - @usableFromInline 25 - enum ScanError: Error { 26 - case unexpectedEndOfData 27 - case invalidMajorType(byte: UInt8, offset: Int) 28 - case invalidSize(byte: UInt8, offset: Int) 29 - case expectedMajorType(offset: Int) 30 - case typeInIndeterminateString(type: MajorType, offset: Int) 31 - case rejectedIndeterminateLength(type: MajorType, offset: Int) 32 - } 33 - 34 35 // MARK: - Results 35 36 36 37 /// After the scanner scans, this contains a map that allows the CBOR data to be scanned for values at arbitrary ··· 96 97 var results: Results 97 98 let options: DecodingOptions 98 99 100 + var isEmpty: Bool { 101 + results.map.isEmpty 102 + } 103 + 99 104 init(data: DataReader, options: DecodingOptions = DecodingOptions()) { 100 105 self.reader = data 101 106 self.results = Results(dataCount: data.count) ··· 199 204 case .map: 200 205 try scanMap() 201 206 case .simple: 202 - scanSimple(raw: raw) 207 + try scanSimple(raw: raw) 203 208 case .tagged: 204 - fatalError() 209 + throw ScanError.expectedMajorType(offset: 0) 205 210 } 206 211 } 207 212 ··· 217 222 218 223 // MARK: - Scan Simple 219 224 220 - private func scanSimple(raw: UInt8) { 225 + private func scanSimple(raw: UInt8) throws { 221 226 let idx = reader.index 222 227 results.recordSimple(reader.pop(), currentByteIndex: idx) 228 + guard reader.canRead(simpleLength(raw)) else { 229 + throw ScanError.unexpectedEndOfData 230 + } 223 231 reader.pop(simpleLength(raw)) 224 232 } 225 233 ··· 308 316 309 317 private func scanMap() throws { 310 318 guard peekIsIndeterminate() else { 311 - let size = try reader.readNextInt(as: Int.self) * 2 319 + let keyCount = try reader.readNextInt(as: Int.self) 320 + guard keyCount < Int.max / 2 else { 321 + throw ScanError.cannotRepresentInt(max: UInt(Int.max), found: UInt(keyCount) * 2, offset: reader.index) 322 + } 323 + 324 + let size = keyCount * 2 312 325 let mapIdx = results.recordMapStart(currentByteIndex: reader.index) 313 326 for _ in 0..<size { 314 327 try scanNext() ··· 334 347 results.recordEnd(childCount: count, resultLocation: mapIdx, currentByteIndex: reader.index) 335 348 } 336 349 } 337 - 338 - // MARK: - Utils 339 - 340 - extension CBORScanner { 341 - func popByteCount() throws -> Int { 342 - let byteCount = reader.popArgument() 343 - return switch byteCount { 344 - case let value where value < Constants.maxArgSize: 0 345 - case 24: 1 346 - case 25: 2 347 - case 26: 4 348 - case 27: 8 349 - default: 350 - throw ScanError.invalidSize(byte: byteCount, offset: reader.index - 1) 351 - } 352 - } 353 - 354 - func peekIsIndeterminate() -> Bool { 355 - (reader.peekArgument() ?? 0) == 0b1_1111 356 - } 357 - } 358 - 359 - // MARK: - Debug Description 360 - 361 - #if DEBUG 362 - extension CBORScanner: CustomDebugStringConvertible { 363 - @usableFromInline var debugDescription: String { 364 - var string = "" 365 - func indent(_ other: String, d: Int) { string += String(repeating: " ", count: d * 2) + other + "\n" } 366 - 367 - func gen(_ idx: Int, depth: Int) { 368 - let value = load(at: idx) 369 - switch value.type { 370 - case .map, .array: 371 - indent( 372 - "\(value.type), mapIdx: \(value.mapOffset), children: \(value.childCount!), bytes: \(value.count)", 373 - d: depth 374 - ) 375 - var idx = firstChildIndex(idx) 376 - for _ in 0..<value.childCount! { 377 - gen(idx, depth: depth + 1) 378 - idx = siblingIndex(idx) 379 - } 380 - default: 381 - indent("\(value.type), mapIdx: \(value.mapOffset), arg: \(value.argument)", d: depth) 382 - } 383 - } 384 - 385 - gen(0, depth: 0) 386 - return string 387 - } 388 - } 389 - #endif
+5 -27
Sources/CBOR/Decoder/Scanner/DataReader.swift
··· 86 86 peekType() == .simple && peekArgument() == 22 87 87 } 88 88 89 - @inline(__always) 90 - mutating func readInt<F: FixedWidthInteger>(as: F.Type) throws -> F { 91 - guard canRead(F.byteCount) else { 92 - throw CBORScanner.ScanError.unexpectedEndOfData 93 - } 94 - var val = F.zero 95 - for idx in 0..<(F.byteCount) { 96 - let shift = (F.byteCount - idx - 1) * 8 97 - val |= F(pop()) << shift 98 - } 99 - return F(val) 100 - } 101 - 102 89 /// Reads the next variable-sized integer off the data stack. 103 90 @inlinable 104 91 mutating func readNextInt<T: FixedWidthInteger>(as: T.Type) throws -> T { 105 - let byteCount = popArgument() 106 - return switch byteCount { 107 - case let value where value < Constants.maxArgSize: 108 - T(value) 109 - case 24: 110 - T(try readInt(as: UInt8.self)) 111 - case 25: 112 - T(try readInt(as: UInt16.self)) 113 - case 26: 114 - T(try readInt(as: UInt32.self)) 115 - case 27: 116 - T(try readInt(as: UInt64.self)) 117 - default: 118 - throw CBORScanner.ScanError.invalidSize(byte: byteCount, offset: index - 1) 92 + let arg = popArgument() 93 + let value = try data.readInt(as: T.self, argument: arg, from: data.startIndex + index) 94 + if let byteCount = arg.byteCount(), byteCount > 0 { 95 + pop(Int(byteCount)) 119 96 } 97 + return value 120 98 } 121 99 122 100 @inlinable
+198
Sources/Fuzzing/AnyDecodable.swift
··· 1 + // From https://github.com/Flight-School/AnyCodable/blob/master/Sources/AnyCodable/AnyDecodable.swift 2 + 3 + // swiftlint:disable cyclomatic_complexity 4 + // swiftlint:disable line_length 5 + // swiftlint:disable type_name 6 + 7 + #if canImport(Foundation) 8 + import Foundation 9 + #endif 10 + 11 + /** 12 + A type-erased `Decodable` value. 13 + 14 + The `AnyDecodable` type forwards decoding responsibilities 15 + to an underlying value, hiding its specific underlying type. 16 + 17 + You can decode mixed-type values in dictionaries 18 + and other collections that require `Decodable` conformance 19 + by declaring their contained type to be `AnyDecodable`: 20 + 21 + let json = """ 22 + { 23 + "boolean": true, 24 + "integer": 42, 25 + "double": 3.141592653589793, 26 + "string": "string", 27 + "array": [1, 2, 3], 28 + "nested": { 29 + "a": "alpha", 30 + "b": "bravo", 31 + "c": "charlie" 32 + }, 33 + "null": null 34 + } 35 + """.data(using: .utf8)! 36 + 37 + let decoder = JSONDecoder() 38 + let dictionary = try! decoder.decode([String: AnyDecodable].self, from: json) 39 + */ 40 + struct AnyDecodable: Decodable { 41 + let value: Any 42 + 43 + init<T>(_ value: T?) { 44 + self.value = value ?? () 45 + } 46 + } 47 + 48 + @usableFromInline 49 + protocol _AnyDecodable { 50 + var value: Any { get } 51 + init<T>(_ value: T?) 52 + } 53 + 54 + extension AnyDecodable: _AnyDecodable {} 55 + 56 + extension _AnyDecodable { 57 + init(from decoder: Decoder) throws { 58 + let container = try decoder.singleValueContainer() 59 + 60 + if container.decodeNil() { 61 + #if canImport(Foundation) 62 + self.init(NSNull()) 63 + #else 64 + self.init(Optional<Self>.none) 65 + #endif 66 + } else if let bool = try? container.decode(Bool.self) { 67 + self.init(bool) 68 + } else if let int = try? container.decode(Int.self) { 69 + self.init(int) 70 + } else if let uint = try? container.decode(UInt.self) { 71 + self.init(uint) 72 + } else if let double = try? container.decode(Double.self) { 73 + self.init(double) 74 + } else if let string = try? container.decode(String.self) { 75 + self.init(string) 76 + } else if let array = try? container.decode([AnyDecodable].self) { 77 + self.init(array.map { $0.value }) 78 + } else if let dictionary = try? container.decode([String: AnyDecodable].self) { 79 + self.init(dictionary.mapValues { $0.value }) 80 + } else { 81 + throw DecodingError.dataCorruptedError(in: container, debugDescription: "AnyDecodable value cannot be decoded") 82 + } 83 + } 84 + } 85 + 86 + extension AnyDecodable: Equatable { 87 + static func == (lhs: AnyDecodable, rhs: AnyDecodable) -> Bool { 88 + switch (lhs.value, rhs.value) { 89 + #if canImport(Foundation) 90 + case is (NSNull, NSNull), is (Void, Void): 91 + return true 92 + #endif 93 + case let (lhs as Bool, rhs as Bool): 94 + return lhs == rhs 95 + case let (lhs as Int, rhs as Int): 96 + return lhs == rhs 97 + case let (lhs as Int8, rhs as Int8): 98 + return lhs == rhs 99 + case let (lhs as Int16, rhs as Int16): 100 + return lhs == rhs 101 + case let (lhs as Int32, rhs as Int32): 102 + return lhs == rhs 103 + case let (lhs as Int64, rhs as Int64): 104 + return lhs == rhs 105 + case let (lhs as UInt, rhs as UInt): 106 + return lhs == rhs 107 + case let (lhs as UInt8, rhs as UInt8): 108 + return lhs == rhs 109 + case let (lhs as UInt16, rhs as UInt16): 110 + return lhs == rhs 111 + case let (lhs as UInt32, rhs as UInt32): 112 + return lhs == rhs 113 + case let (lhs as UInt64, rhs as UInt64): 114 + return lhs == rhs 115 + case let (lhs as Float, rhs as Float): 116 + return lhs == rhs 117 + case let (lhs as Double, rhs as Double): 118 + return lhs == rhs 119 + case let (lhs as String, rhs as String): 120 + return lhs == rhs 121 + case let (lhs as [String: AnyDecodable], rhs as [String: AnyDecodable]): 122 + return lhs == rhs 123 + case let (lhs as [AnyDecodable], rhs as [AnyDecodable]): 124 + return lhs == rhs 125 + default: 126 + return false 127 + } 128 + } 129 + } 130 + 131 + extension AnyDecodable: CustomStringConvertible { 132 + var description: String { 133 + switch value { 134 + case is Void: 135 + return String(describing: nil as Any?) 136 + case let value as CustomStringConvertible: 137 + return value.description 138 + default: 139 + return String(describing: value) 140 + } 141 + } 142 + } 143 + 144 + extension AnyDecodable: CustomDebugStringConvertible { 145 + var debugDescription: String { 146 + switch value { 147 + case let value as CustomDebugStringConvertible: 148 + return "AnyDecodable(\(value.debugDescription))" 149 + default: 150 + return "AnyDecodable(\(description))" 151 + } 152 + } 153 + } 154 + 155 + extension AnyDecodable: Hashable { 156 + func hash(into hasher: inout Hasher) { 157 + switch value { 158 + case let value as Bool: 159 + hasher.combine(value) 160 + case let value as Int: 161 + hasher.combine(value) 162 + case let value as Int8: 163 + hasher.combine(value) 164 + case let value as Int16: 165 + hasher.combine(value) 166 + case let value as Int32: 167 + hasher.combine(value) 168 + case let value as Int64: 169 + hasher.combine(value) 170 + case let value as UInt: 171 + hasher.combine(value) 172 + case let value as UInt8: 173 + hasher.combine(value) 174 + case let value as UInt16: 175 + hasher.combine(value) 176 + case let value as UInt32: 177 + hasher.combine(value) 178 + case let value as UInt64: 179 + hasher.combine(value) 180 + case let value as Float: 181 + hasher.combine(value) 182 + case let value as Double: 183 + hasher.combine(value) 184 + case let value as String: 185 + hasher.combine(value) 186 + case let value as [String: AnyDecodable]: 187 + hasher.combine(value) 188 + case let value as [AnyDecodable]: 189 + hasher.combine(value) 190 + default: 191 + break 192 + } 193 + } 194 + } 195 + 196 + // swiftlint:enable cyclomatic_complexity 197 + // swiftlint:enable line_length 198 + // swiftlint:enable type_name
+67
Sources/Fuzzing/main.swift
··· 1 + // 2 + // fuzz.swift 3 + // CBOR 4 + // 5 + // Created by Khan Winter on 8/29/25. 6 + // 7 + 8 + import CBOR 9 + import Foundation 10 + 11 + @_optimize(none) 12 + func blackhole(_ val: some Any) { } 13 + 14 + /// Fuzzing entry point 15 + @_cdecl("LLVMFuzzerTestOneInput") 16 + public func fuzz(_ start: UnsafeRawPointer, _ count: Int) -> CInt { 17 + let bytes = UnsafeRawBufferPointer(start: start, count: count) 18 + let data = Data(bytes) 19 + 20 + // Try decoding against a bunch of standard types. 21 + // Each attempt is independent — errors are ignored, crashes are what fuzzing is for. 22 + func tryDecode<T: Decodable>(_ type: T.Type) { 23 + do { 24 + blackhole(try CBORDecoder(rejectIndeterminateLengths: false).decode(T.self, from: data)) 25 + } catch { 26 + // ignore decode errors 27 + } 28 + } 29 + 30 + // Scalars 31 + tryDecode(Bool.self) 32 + tryDecode(Int.self) 33 + tryDecode(Int8.self) 34 + tryDecode(Int16.self) 35 + tryDecode(Int32.self) 36 + tryDecode(Int64.self) 37 + tryDecode(UInt.self) 38 + tryDecode(UInt8.self) 39 + tryDecode(UInt16.self) 40 + tryDecode(UInt32.self) 41 + tryDecode(UInt64.self) 42 + tryDecode(Float.self) 43 + tryDecode(Double.self) 44 + tryDecode(String.self) 45 + tryDecode(Data.self) 46 + 47 + // Optionals 48 + tryDecode(Optional<Int>.self) 49 + tryDecode(Optional<String>.self) 50 + tryDecode(Optional<Data>.self) 51 + 52 + // Collections 53 + tryDecode([Int].self) 54 + tryDecode([String].self) 55 + tryDecode([Data].self) 56 + tryDecode([String: Int].self) 57 + tryDecode([String: String].self) 58 + 59 + // Nested combinations 60 + tryDecode([[Int]].self) 61 + tryDecode([String: [String: Int]].self) 62 + 63 + // Any decodable 64 + tryDecode(AnyDecodable.self) 65 + 66 + return 0 67 + }
+27 -26
Tests/CBORTests/DecodableTests.swift
··· 16 16 struct DecodableTests { 17 17 @Test 18 18 func uint8() throws { 19 - var value = try CBORDecoder().decode(UInt8.self, from: [0]) 20 - #expect(value == 0) 21 - value = try CBORDecoder().decode(UInt8.self, from: [1]) 22 - #expect(value == 1) 23 - // Just below max arg size 24 - value = try CBORDecoder().decode(UInt8.self, from: [23]) 25 - #expect(value == 23) 19 + var value: UInt8 = 0 // try CBORDecoder().decode(UInt8.self, from: [0]) 20 + // #expect(value == 0) 21 + // value = try CBORDecoder().decode(UInt8.self, from: [1]) 22 + // #expect(value == 1) 23 + // // Just below max arg size 24 + // value = try CBORDecoder().decode(UInt8.self, from: [23]) 25 + // #expect(value == 23) 26 26 // Just above max arg size 27 27 value = try CBORDecoder().decode(UInt8.self, from: [24, 24]) 28 28 #expect(value == 24) 29 29 // Max Int 30 - value = try CBORDecoder().decode(UInt8.self, from: [24, UInt8.max]) 31 - #expect(value == UInt8.max) 30 + // value = try CBORDecoder().decode(UInt8.self, from: [24, UInt8.max]) 31 + // #expect(value == UInt8.max) 32 + // 33 + // #expect(throws: DecodingError.self) { try CBORDecoder().decode(UInt8.self, from: [128]) } 34 + } 32 35 33 - #expect(throws: DecodingError.self) { try CBORDecoder().decode(UInt8.self, from: [128]) } 36 + @Test 37 + func int8() throws { 38 + #expect(throws: DecodingError.self) { try CBORDecoder().decode(Int8.self, from: [24, 255]) } 34 39 } 35 40 36 41 @Test ··· 182 187 ]) 183 188 func indeterminateString(data: String, expected: String) throws { 184 189 let data = data.asHexData() 185 - let string = try CBORDecoder(options: DecodingOptions(rejectIndeterminateLengthStrings: false)) 190 + let string = try CBORDecoder(rejectIndeterminateLengths: false) 186 191 .decode(String.self, from: data) 187 192 #expect(string == expected) 188 193 } ··· 207 212 try data.withUnsafeBytes { 208 213 let data = $0[...] 209 214 let reader = DataReader(data: data) 210 - let scanner = CBORScanner(data: reader, options: DecodingOptions(rejectIndeterminateLengthArrays: false)) 215 + let scanner = CBORScanner(data: reader, options: DecodingOptions(rejectIndeterminateLengths: false)) 211 216 try scanner.scan() 212 217 213 218 let context = DecodingContext(scanner: scanner) ··· 239 244 240 245 @Test 241 246 func indeterminateArray() throws { 242 - // let array = "9F0203FF".asHexData() 243 - let options = DecodingOptions(rejectIndeterminateLengthArrays: false) 244 - // #expect(try CBORDecoder(options: options).decode([Int].self, from: array) == [2, 3]) 247 + let array = "9F0203FF".asHexData() 248 + #expect(try CBORDecoder(rejectIndeterminateLengths: false).decode([Int].self, from: array) == [2, 3]) 245 249 246 250 let twodArray = "9F9F0203FF9F0405FFFF".asHexData() 247 - try twodArray.withUnsafeBytes { 248 - let data = $0[...] 249 - let reader = DataReader(data: data) 250 - let scanner = CBORScanner(data: reader, options: DecodingOptions(rejectIndeterminateLengthArrays: false)) 251 - try scanner.scan() 252 - print(scanner.debugDescription) 253 - dump(scanner.results.map) 254 - } 255 - let result = try CBORDecoder(options: options).decode([[Int]].self, from: twodArray) 251 + let result = try CBORDecoder(rejectIndeterminateLengths: false).decode([[Int]].self, from: twodArray) 256 252 #expect(result == [[2, 3], [4, 5]]) 257 253 } 258 254 259 255 @Test 260 256 func rejectsIndeterminateArrayWhenConfigured() throws { 261 257 let array = "9FFF".asHexData() 262 - let options = DecodingOptions(rejectIndeterminateLengthArrays: true) 263 258 #expect(throws: DecodingError.self) { 264 - try CBORDecoder(options: options).decode([Int].self, from: array) 259 + try CBORDecoder(rejectIndeterminateLengths: true).decode([Int].self, from: array) 265 260 } 266 261 262 + } 263 + 264 + @Test 265 + func emptyData() throws { 266 + let data = Data() 267 + #expect(throws: DecodingError.self) { try CBORDecoder().decode(Data.self, from: data) } 267 268 } 268 269 }
+60
Tests/CBORTests/RoundTripTests.swift
··· 53 53 #expect(value == result) 54 54 } 55 55 } 56 + 57 + @Test 58 + func data() throws { 59 + let value = Data([0xde, 0xad, 0xbe, 0xef]) 60 + let encoded = try CBOREncoder().encode(value) 61 + let decoded = try CBORDecoder().decode(Data.self, from: encoded) 62 + #expect(value == decoded) 63 + } 64 + 65 + @Test 66 + func emptyData() throws { 67 + let value = Data() 68 + let encoded = try CBOREncoder().encode(value) 69 + let decoded = try CBORDecoder().decode(Data.self, from: encoded) 70 + #expect(value == decoded) 71 + } 72 + 73 + @Test 74 + func string() throws { 75 + let value = "Hello, CBOR 👋" 76 + let encoded = try CBOREncoder().encode(value) 77 + let decoded = try CBORDecoder().decode(String.self, from: encoded) 78 + #expect(value == decoded) 79 + } 80 + 81 + @Test 82 + func emptyString() throws { 83 + let value = "" 84 + let encoded = try CBOREncoder().encode(value) 85 + let decoded = try CBORDecoder().decode(String.self, from: encoded) 86 + #expect(value == decoded) 87 + } 88 + 89 + @Test 90 + func person() throws { 91 + let value = Person.mock 92 + let encoded = try CBOREncoder().encode(value) 93 + let decoded = try CBORDecoder().decode(Person.self, from: encoded) 94 + #expect(value.name == decoded.name) 95 + #expect(value.age == decoded.age) 96 + #expect(value.email == decoded.email) 97 + #expect(value.isActive == decoded.isActive) 98 + #expect(value.tags == decoded.tags) 99 + } 100 + 101 + @Test 102 + func company() throws { 103 + let value = Company.mock 104 + let encoded = try CBOREncoder().encode(value) 105 + let decoded = try CBORDecoder().decode(Company.self, from: encoded) 106 + #expect(value.name == decoded.name) 107 + #expect(value.founded == decoded.founded) 108 + #expect(value.employees.count == decoded.employees.count) 109 + #expect(value.metadata == decoded.metadata) 110 + 111 + // sanity check one employee too 112 + if let first = decoded.employees.first { 113 + #expect(first.name == Person.mock.name) 114 + } 115 + } 56 116 }
+4 -4
Tests/CBORTests/ScannerTests.swift
··· 34 34 let data = Array(repeating: UInt8.zero, count: count) 35 35 Data([argument] + data).withUnsafeBytes { 36 36 let data = $0[...] 37 - #expect(throws: CBORScanner.ScanError.self) { 37 + #expect(throws: ScanError.self) { 38 38 try CBORScanner(data: DataReader(data: data)).scan() 39 39 } 40 40 } ··· 59 59 let data = Data([MajorType.nint.bits | argument] + Array(repeating: UInt8.zero, count: count)) 60 60 data.withUnsafeBytes { 61 61 let data = $0[...] 62 - #expect(throws: CBORScanner.ScanError.self) { 62 + #expect(throws: ScanError.self) { 63 63 try CBORScanner(data: DataReader(data: data)).scan() 64 64 } 65 65 } ··· 77 77 let data = data.asHexData() 78 78 try data.withUnsafeBytes { 79 79 let data = $0[...] 80 - let options = DecodingOptions(rejectIndeterminateLengthMaps: false) 80 + let options = DecodingOptions(rejectIndeterminateLengths: false) 81 81 let scanner = CBORScanner(data: DataReader(data: data), options: options) 82 82 try scanner.scan() 83 83 let map = scanner.results.map ··· 114 114 let data = "9F9F0203FF9F0405FFFF".asHexData() 115 115 try data.withUnsafeBytes { 116 116 let data = $0[...] 117 - let options = DecodingOptions(rejectIndeterminateLengthArrays: false) 117 + let options = DecodingOptions(rejectIndeterminateLengths: false) 118 118 let scanner = CBORScanner(data: DataReader(data: data), options: options) 119 119 try scanner.scan() 120 120 let map = scanner.results.map