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
at main 300 lines 18 kB view raw
1// 2// DecodableTests.swift 3// CBOR 4// 5// Created by Khan Winter on 8/20/25. 6// 7 8import Testing 9#if canImport(FoundationEssentials) 10import FoundationEssentials 11#else 12import Foundation 13#endif 14@testable import CBOR 15 16@Suite 17struct DecodableTests { 18 @Test 19 func uint8() throws { 20 var value: UInt8 = try CBORDecoder().decode(UInt8.self, from: [0]) 21 #expect(value == 0) 22 value = try CBORDecoder().decode(UInt8.self, from: [1]) 23 #expect(value == 1) 24 // Just below max arg size 25 value = try CBORDecoder().decode(UInt8.self, from: [23]) 26 #expect(value == 23) 27 // Just above max arg size 28// value = try CBORDecoder().decode(UInt8.self, from: [24, 24]) 29// #expect(value == 24) 30 // Max Int 31 value = try CBORDecoder().decode(UInt8.self, from: [24, UInt8.max]) 32 #expect(value == UInt8.max) 33 34 #expect(throws: DecodingError.self) { try CBORDecoder().decode(UInt8.self, from: [128]) } 35 } 36 37 @Test 38 func int8() throws { 39 #expect(throws: DecodingError.self) { try CBORDecoder().decode(Int8.self, from: [24, 255]) } 40 } 41 42 @Test 43 func uint16() throws { 44 var value = try CBORDecoder().decode(UInt16.self, from: [0]) 45 #expect(value == 0) 46 value = try CBORDecoder().decode(UInt16.self, from: [1]) 47 #expect(value == 1) 48 // Just below max arg size 49 value = try CBORDecoder().decode(UInt16.self, from: [23]) 50 #expect(value == 23) 51 // Just above max arg size 52 #expect(throws: DecodingError.self) { try CBORDecoder().decode(UInt16.self, from: [24, 24]) } 53 54 #expect(throws: DecodingError.self) { try CBORDecoder().decode(UInt16.self, from: [128]) } 55 56 #expect(throws: DecodingError.self) { try CBORDecoder().decode(UInt16.self, from: [25, 0, 1]) } 57 58 value = try CBORDecoder().decode(UInt16.self, from: [25, 1, 1]) 59 #expect(value == 257) 60 value = try CBORDecoder().decode(UInt16.self, from: [25, UInt8.max, UInt8.max]) 61 #expect(value == UInt16.max) 62 // Missing bytes from end 63 #expect(throws: DecodingError.self) { try CBORDecoder().decode(UInt16.self, from: [25]) } 64 #expect(throws: DecodingError.self) { try CBORDecoder().decode(UInt16.self, from: [25, 0]) } 65 } 66 67 @Test 68 func uint32() throws { 69 var value: UInt32 = try CBORDecoder().decode(UInt32.self, from: [0]) 70 #expect(value == 0) 71 value = try CBORDecoder().decode(UInt32.self, from: [1]) 72 #expect(value == 1) 73 // Just below max arg size 74 value = try CBORDecoder().decode(UInt32.self, from: [23]) 75 #expect(value == 23) 76 77 value = try CBORDecoder().decode(UInt32.self, from: [25, 1, 1]) 78 #expect(value == 257) 79 value = try CBORDecoder().decode(UInt32.self, from: [25, UInt8.max, UInt8.max]) 80 #expect(value == UInt16.max) 81 // Missing bytes from end 82 #expect(throws: DecodingError.self) { try CBORDecoder().decode(UInt32.self, from: [25]) } 83 #expect(throws: DecodingError.self) { try CBORDecoder().decode(UInt32.self, from: [25, 0]) } 84 85 #expect(throws: DecodingError.self) { try CBORDecoder().decode(UInt32.self, from: [26, 0, 0, 0, 0]) } 86 #expect(throws: DecodingError.self) { try CBORDecoder().decode(UInt32.self, from: [26, 0, 0, 0, 1]) } 87 #expect(throws: DecodingError.self) { try CBORDecoder().decode(UInt32.self, from: [26, 0, 0, 1, 1]) } 88 89 value = try CBORDecoder().decode(UInt32.self, from: [26, 0, 1, 1, 1]) 90 #expect(value == 65793) 91 92 value = try CBORDecoder().decode(UInt32.self, from: [26, UInt8.max, UInt8.max, UInt8.max, UInt8.max]) 93 #expect(value == UInt32.max) 94 // Missing bytes from end 95 #expect(throws: DecodingError.self) { try CBORDecoder().decode(UInt32.self, from: [26]) } 96 #expect(throws: DecodingError.self) { try CBORDecoder().decode(UInt32.self, from: [26, 0, 0, 0]) } 97 } 98 99 @Test 100 func uint64() throws { 101 var value: UInt64 = try CBORDecoder().decode(UInt64.self, from: [0]) 102 #expect(value == 0) 103 value = try CBORDecoder().decode(UInt64.self, from: [1]) 104 #expect(value == 1) 105 // Just below max arg size 106 value = try CBORDecoder().decode(UInt64.self, from: [23]) 107 #expect(value == 23) 108 109 value = try CBORDecoder().decode(UInt64.self, from: [25, 1, 1]) 110 #expect(value == 257) 111 value = try CBORDecoder().decode(UInt64.self, from: [25, UInt8.max, UInt8.max]) 112 #expect(value == UInt16.max) 113 // Missing bytes from end 114 #expect(throws: DecodingError.self) { try CBORDecoder().decode(UInt64.self, from: [25]) } 115 #expect(throws: DecodingError.self) { try CBORDecoder().decode(UInt64.self, from: [25, 0]) } 116 117 #expect(throws: DecodingError.self) { try CBORDecoder().decode(UInt64.self, from: [26, 0, 0, 0, 0]) } 118 #expect(throws: DecodingError.self) { try CBORDecoder().decode(UInt64.self, from: [26, 0, 0, 0, 1]) } 119 #expect(throws: DecodingError.self) { try CBORDecoder().decode(UInt64.self, from: [26, 0, 0, 1, 1]) } 120 121 value = try CBORDecoder().decode(UInt64.self, from: [26, 0, 1, 1, 1]) 122 #expect(value == 65793) 123 value = try CBORDecoder().decode(UInt64.self, from: [26, UInt8.max, UInt8.max, UInt8.max, UInt8.max]) 124 #expect(value == UInt32.max) 125 // Missing bytes from end 126 #expect(throws: DecodingError.self) { try CBORDecoder().decode(UInt64.self, from: [26]) } 127 #expect(throws: DecodingError.self) { try CBORDecoder().decode(UInt64.self, from: [26, 0, 0, 0]) } 128 129 #expect(throws: DecodingError.self) { 130 try CBORDecoder().decode(UInt64.self, from: [27, 0, 0, 0, 0, 0, 0, 0, 0]) 131 } 132 #expect(throws: DecodingError.self) { 133 try CBORDecoder().decode(UInt64.self, from: [27, 0, 0, 0, 0, 0, 0, 0, 1]) 134 } 135 #expect(throws: DecodingError.self) { 136 try CBORDecoder().decode(UInt64.self, from: [27, 0, 0, 0, 0, 0, 0, 1, 1]) 137 } 138 139 // Missing bytes from end 140 #expect(throws: DecodingError.self) { try CBORDecoder().decode(UInt64.self, from: [27]) } 141 #expect(throws: DecodingError.self) { 142 try CBORDecoder().decode(UInt64.self, from: [27, 0, 0, 0, 0, 0, 0, 0]) 143 } 144 } 145 146 @available(macOS 15.0, *) 147 @Test 148 func minInt() throws { 149 let data = "3bffffffffffffffff".asHexData() 150 let decoded = try CBORDecoder().decode(Int128.self, from: data) 151 #expect(decoded == -18446744073709551616) 152 } 153 154 @Test 155 func float() throws { 156 let expected: Float = 100000.0 157 let data = "fa47c35000".asHexData() 158 let decoded = try CBORDecoder().decode(Float.self, from: data) 159 #expect(decoded == expected) 160 } 161 162 @Test 163 func double() throws { 164 let expected: Double = 0.10035 165 let data = "FB3FB9B089A0275254".asHexData() 166 let decoded = try CBORDecoder().decode(Double.self, from: data) 167 #expect(decoded == expected) 168 } 169 170 @Test(arguments: [ 171 ("6b68656c6c6f20776f726c64", "hello world"), 172 ("60", ""), 173 ("66e29da4efb88f", "❤️"), 174 // swiftlint:disable:next line_length 175 ("782F68656C6C6F20776F726C642068656C6C6F20776F726C642068656C6C6F20776F726C642068656C6C6F20776F726C64", "hello world hello world hello world hello world") 176 ]) 177 func string(data: String, expected: String) throws { 178 let data = data.asHexData() 179 let string = try CBORDecoder().decode(String.self, from: data) 180 #expect(string == expected) 181 } 182 183 @Test(arguments: [ 184 ("7FFF", ""), 185 ("7F61416142FF", "AB") 186 ]) 187 func indeterminateString(data: String, expected: String) throws { 188 let data = data.asHexData() 189 let string = try CBORDecoder(rejectIndeterminateLengths: false) 190 .decode(String.self, from: data) 191 #expect(string == expected) 192 } 193 194 @Test 195 func emptyMap() throws { 196 let data = "A0".asHexData() 197 let dictionary = try CBORDecoder().decode([String: Int].self, from: data) 198 #expect(dictionary.isEmpty) 199 } 200 201 @Test 202 func simpleMap() throws { 203 let data = "A262414201614102".asHexData() 204 let dictionary = try CBORDecoder().decode([String: Int].self, from: data) 205 #expect(dictionary == ["AB": 1, "A": 2]) 206 } 207 208 @Test 209 func unkeyedContainerHasCountForIndeterminate() throws { 210 let data = "9F0203FF".asHexData() 211 try data.withUnsafeBytes { 212 let data = $0[...] 213 let reader = DataReader(data: data) 214 let options = DecodingOptions(rejectIndeterminateLengths: false) 215 let scanner = CBORScanner(data: reader, options: options) 216 let results = try scanner.scan() 217 218 let context = DecodingContext(options: options, results: results) 219 let container = SingleValueCBORDecodingContainer( 220 context: context, 221 data: results.load(at: 0) 222 ) 223 224 var unkeyedContainer = try container.unkeyedContainer() 225 #expect(unkeyedContainer.isAtEnd == false) 226 #expect(unkeyedContainer.count == 2) 227 #expect(unkeyedContainer.currentIndex == 0) 228 229 let key1 = try unkeyedContainer.decode(Int.self) 230 let key2 = try unkeyedContainer.decode(Int.self) 231 #expect(key1 == 2) 232 #expect(key2 == 3) 233 234 #expect(unkeyedContainer.isAtEnd) 235 #expect(unkeyedContainer.currentIndex == 2) 236 } 237 } 238 239 @Test 240 func array() throws { 241 let twentyItems = "940101010101010101010101010101010101010101".asHexData() 242 #expect(try CBORDecoder().decode([Int].self, from: twentyItems) == Array(repeating: 1, count: 20)) 243 } 244 245 @Test 246 func indeterminateArray() throws { 247 let array = "9F0203FF".asHexData() 248 #expect(try CBORDecoder(rejectIndeterminateLengths: false).decode([Int].self, from: array) == [2, 3]) 249 250 let twodArray = "9F9F0203FF9F0405FFFF".asHexData() 251 let result = try CBORDecoder(rejectIndeterminateLengths: false).decode([[Int]].self, from: twodArray) 252 #expect(result == [[2, 3], [4, 5]]) 253 } 254 255 @Test 256 func rejectsIndeterminateArrayWhenConfigured() throws { 257 let array = "9FFF".asHexData() 258 #expect(throws: DecodingError.self) { 259 try CBORDecoder(rejectIndeterminateLengths: true).decode([Int].self, from: array) 260 } 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) } 268 } 269 270 @Test 271 func date() throws { 272 let data = "C11A5C295C00".asHexData() 273 let expected = Date(timeIntervalSince1970: 1546214400.0) 274 let value = try CBORDecoder().decode(Date.self, from: data) 275 #expect(value == expected) 276 } 277 278 @Test(arguments: [ 279 ("F90000", 0), 280 ("F93C00", 1.0), 281 ("F9BE00", -1.5), 282 ("F97C00", .infinity), 283 ("F93E32", 1.548828125), 284 ("F9F021", -8456) 285 ]) 286 func float16(data: String, value: Float) throws { 287 let data = data.asHexData() 288 let decoded = try CBORDecoder().decode(Float.self, from: data) 289 #expect(decoded == value) 290 } 291 292 @Test 293 func recursionLimit() { 294 #expect(throws: DecodingError.self) { 295 // swiftlint:disable:next line_length 296 let data = "a260818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818180652474797065726170702e62736b792e666565642e70736f74".asHexData() 297 return try CBORDecoder().decode(AnyDecodable.self, from: data) 298 } 299 } 300}