@@ -11,7 +11,7 @@ import ucrt
1111// MARK: - CBOR Type
1212
1313/// A CBOR value
14- public indirect enum CBOR : Equatable , Sendable {
14+ public enum CBOR : Equatable , Sendable {
1515 /// A positive unsigned integer
1616 case unsignedInt( UInt64 )
1717 /// A negative integer
@@ -25,7 +25,7 @@ public indirect enum CBOR: Equatable, Sendable {
2525 /// A map of CBOR key-value pairs
2626 case map( [ CBORMapPair ] )
2727 /// A tagged CBOR value
28- case tagged( UInt64 , CBOR )
28+ indirect case tagged( UInt64 , CBOR )
2929 /// A simple value
3030 case simple( UInt8 )
3131 /// A boolean value
@@ -38,9 +38,13 @@ public indirect enum CBOR: Equatable, Sendable {
3838 case float( Double )
3939
4040 /// Encodes the CBOR value to bytes
41+ public func encode( into output: inout [ UInt8 ] ) {
42+ _encode ( self , into: & output)
43+ }
44+
4145 public func encode( ) -> [ UInt8 ] {
4246 var output : [ UInt8 ] = [ ]
43- _encode ( self , into: & output)
47+ encode ( into: & output)
4448 return output
4549 }
4650
@@ -80,6 +84,7 @@ public struct CBORMapPair: Equatable, Sendable {
8084/// - Parameters:
8185/// - value: The CBOR value to encode
8286/// - output: The output buffer to write the encoded bytes to
87+ @inline ( __always)
8388private func _encode( _ value: CBOR , into output: inout [ UInt8 ] ) {
8489 switch value {
8590 case . unsignedInt( let u) :
@@ -207,16 +212,16 @@ private func _decode(reader: inout CBORReader) throws(CBORError) -> CBOR {
207212
208213 case 2 : // byte string
209214 let length = try readUIntValue ( additional: additional, reader: & reader)
210- guard length <= UInt64 ( Int . max ) else {
211- throw CBORError . lengthTooLarge ( length)
215+ guard length <= reader . maximumStringLength else {
216+ throw CBORError . lengthTooLarge ( length, maximum : reader . maximumStringLength )
212217 }
213218
214- return . byteString( try reader. readBytes ( Int ( length) ) )
219+ return . byteString( Array ( try reader. readBytes ( Int ( length) ) ) )
215220
216221 case 3 : // text string
217222 let length = try readUIntValue ( additional: additional, reader: & reader)
218- guard length <= UInt64 ( Int . max ) else {
219- throw CBORError . lengthTooLarge ( length)
223+ guard length <= reader . maximumStringLength else {
224+ throw CBORError . lengthTooLarge ( length, maximum : reader . maximumStringLength )
220225 }
221226
222227 let bytes = try reader. readBytes ( Int ( length) )
@@ -229,25 +234,25 @@ private func _decode(reader: inout CBORReader) throws(CBORError) -> CBOR {
229234
230235 case 4 : // array
231236 let count = try readUIntValue ( additional: additional, reader: & reader)
232- guard count <= UInt64 ( Int . max ) else {
233- throw CBORError . lengthTooLarge ( count)
237+ guard count <= reader . maximumElementCount else {
238+ throw CBORError . lengthTooLarge ( count, maximum : reader . maximumElementCount )
234239 }
235240
236241 var items : [ CBOR ] = [ ]
237- for _ in 0 ..< Int ( count) {
242+ for _ in 0 ..< count {
238243 items. append ( try _decode ( reader: & reader) )
239244 }
240245
241246 return . array( items)
242247
243248 case 5 : // map
244249 let count = try readUIntValue ( additional: additional, reader: & reader)
245- guard count <= UInt64 ( Int . max ) else {
246- throw CBORError . lengthTooLarge ( count)
250+ guard count <= reader . maximumElementCount else {
251+ throw CBORError . lengthTooLarge ( count, maximum : reader . maximumElementCount )
247252 }
248253
249254 var pairs : [ CBORMapPair ] = [ ]
250- for _ in 0 ..< Int ( count) {
255+ for _ in 0 ..< count {
251256 let key = try _decode ( reader: & reader)
252257 let value = try _decode ( reader: & reader)
253258 pairs. append ( CBORMapPair ( key: key, value: value) )
@@ -270,8 +275,7 @@ private func _decode(reader: inout CBORReader) throws(CBORError) -> CBOR {
270275 let simple = try reader. readByte ( )
271276 return . simple( simple)
272277 case 25 : // IEEE 754 Half-Precision Float (16 bits)
273- let bytes = try reader. readBytes ( 2 )
274- let bits = UInt16 ( bytes [ 0 ] ) << 8 | UInt16 ( bytes [ 1 ] )
278+ let bits = try reader. readBigEndianInteger ( UInt16 . self)
275279 // Convert half-precision to double
276280 let sign = ( bits & 0x8000 ) != 0
277281 let exponent = Int ( ( bits & 0x7C00 ) >> 10 )
@@ -289,15 +293,12 @@ private func _decode(reader: inout CBORReader) throws(CBORError) -> CBOR {
289293 return . float( sign ? - value : value)
290294
291295 case 26 : // IEEE 754 Single-Precision Float (32 bits)
292- let bytes = try reader. readBytes ( 4 )
293- let bits = UInt32 ( bytes [ 0 ] ) << 24 | UInt32 ( bytes [ 1 ] ) << 16 | UInt32 ( bytes [ 2 ] ) << 8 | UInt32 ( bytes [ 3 ] )
296+ let bits = try reader. readBigEndianInteger ( UInt32 . self)
294297 let float = Float ( bitPattern: bits)
295298 return . float( Double ( float) )
296299
297300 case 27 : // IEEE 754 Double-Precision Float (64 bits)
298- let bytes = try reader. readBytes ( 8 )
299- let bits = UInt64 ( bytes [ 0 ] ) << 56 | UInt64 ( bytes [ 1 ] ) << 48 | UInt64 ( bytes [ 2 ] ) << 40 | UInt64 ( bytes [ 3 ] ) << 32 |
300- UInt64 ( bytes [ 4 ] ) << 24 | UInt64 ( bytes [ 5 ] ) << 16 | UInt64 ( bytes [ 6 ] ) << 8 | UInt64 ( bytes [ 7 ] )
301+ let bits = try reader. readBigEndianInteger ( UInt64 . self)
301302 let double = Double ( bitPattern: bits)
302303 return . float( double)
303304
@@ -315,26 +316,20 @@ private func _decode(reader: inout CBORReader) throws(CBORError) -> CBOR {
315316
316317/// Reads an unsigned integer value based on the additional information.
317318private func readUIntValue( additional: UInt8 , reader: inout CBORReader ) throws ( CBORError) -> UInt64 {
318- // Check for indefinite length first
319- if additional == 31 {
320- throw CBORError . indefiniteLengthNotSupported
321- }
322-
323- if additional < 24 {
319+ switch additional {
320+ case 0 ... 23 :
324321 return UInt64 ( additional)
325- } else if additional == 24 {
322+ case 24 :
326323 return UInt64 ( try reader. readByte ( ) )
327- } else if additional == 25 {
328- let bytes = try reader. readBytes ( 2 )
329- return UInt64 ( bytes [ 0 ] ) << 8 | UInt64 ( bytes [ 1 ] )
330- } else if additional == 26 {
331- let bytes = try reader. readBytes ( 4 )
332- return UInt64 ( bytes [ 0 ] ) << 24 | UInt64 ( bytes [ 1 ] ) << 16 | UInt64 ( bytes [ 2 ] ) << 8 | UInt64 ( bytes [ 3 ] )
333- } else if additional == 27 {
334- let bytes = try reader. readBytes ( 8 )
335- return UInt64 ( bytes [ 0 ] ) << 56 | UInt64 ( bytes [ 1 ] ) << 48 | UInt64 ( bytes [ 2 ] ) << 40 | UInt64 ( bytes [ 3 ] ) << 32 |
336- UInt64 ( bytes [ 4 ] ) << 24 | UInt64 ( bytes [ 5 ] ) << 16 | UInt64 ( bytes [ 6 ] ) << 8 | UInt64 ( bytes [ 7 ] )
337- } else {
324+ case 25 :
325+ return try UInt64 ( reader. readBigEndianInteger ( UInt16 . self) )
326+ case 26 :
327+ return try UInt64 ( reader. readBigEndianInteger ( UInt32 . self) )
328+ case 27 :
329+ return try reader. readBigEndianInteger ( UInt64 . self)
330+ case 31 :
331+ throw CBORError . indefiniteLengthNotSupported
332+ default :
338333 throw CBORError . invalidInitialByte ( additional)
339334 }
340335}
0 commit comments