ByteBackpacker is a small utility written in pure Swift to pack value types into a
Byte
¹ array and unpack them back.
Additionally, there is a Data
(formerly NSData
) extension to convert Data
objects into a Byte
array.
¹ Byte
is a typealias
for UInt8
.
You have three options:
-
import PackageDescription let package = Package( name: "TestImport", dependencies: [ .Package(url: "https://github.com/michaeldorner/ByteBackpacker.git") ] )
-
Use Cocoapods:
pod 'ByteBackpacker'
-
Copy the
ByteBackpacker.swift
file (containing theByteBackpacker
class) to your project (not considered as good practice).
Although it can be used in the same way in Objective-C, I had clearly Swift projects in mind. The easiest way for Objective-C users is to embed the ByteBackpacker.framework
. Of course, Swift users can also do this, but actually I do not see any advantages.
Important for a proper usage: ByteBackpacker does only support value types (e.g. numbers, structs, ...), but no reference types (e.g. classes)! For further information see Discussion.
All examples can be seen running in the ByteBackpackerPlayground.playground
. Let's have a look on some general use cases:
let aDouble: Double = 1.0
let aByteArray: [Byte] = ByteBackpacker.pack(aDouble)
let option_1: Double = ByteBackpacker.unpack(aByteArray)
let option_2 = ByteBackpacker.unpack(aByteArray) as Double
let option_3 = ByteBackpacker.unpack(aByteArray, toType: Double.self)
var anotherDouble: Double = 2.0
let data = Data(bytes: &anotherDouble, count: MemoryLayout<Double>.size)
var byteArrayFromNSData = data.toByteArray()
let doubleFromByteArray = ByteBackpacker.unpack(byteArrayFromNSData, toType: Double.self)
let anotherByteArray: [Byte] = [0, 0, 0, 0, 0, 0, 8, 64]
let dataFromByteArray = Data(bytes: anotherByteArray)
Byte
is a typealias
for UInt8
.
ByteOrder
is an enum
for Little Endian and Big Endian. Furthermore, there is the option for asking the platform you are using for the native byte order of the system: ByteOrder.nativeByteOrder
. By default .nativeByteOrder
is applied for packing and unpacking.
For packing value types into a [Byte]
, use
open class func pack<T: Any>( _ value: T, byteOrder: ByteOrder = .nativeByteOrder) -> [Byte]
For unpacking a [Byte]
into a value type, use either
open class func unpack<T: Any>(_ valueByteArray: [Byte], byteOrder: ByteOrder = .nativeByteOrder) -> T
or otherwise, if you want to use type inference
open class func unpack<T: Any>(_ valueByteArray: [Byte], toType type: T.Type, byteOrder: ByteOrder = .nativeByteOrder) -> T
There is no way for specifying value types in Swift's generics (see here the discussion on stackoverflow). It would be awesome to specify our methods like func (un)pack<T: Any where T: ~AnyClass>(...)
to let the compiler check for value types. So far ByteBackpacker ensures the value type with assert(...)
.
An open question is how to test the assert(...)
for this value type check.
I would love to improve this project. Tell me your ideas, here in github, via mail or in codereview.stackexchange.com.
- Find a solution for making sure, that
T
is a value type, but not a reference type - Add documentation to the source code for a nice Xcode integration
- Find a solution for testing
assert()
Many thanks to
- Martin R for his suggestions in codereview.stackexchange.com
- iCodist for his update to Swift 3 and Xcode 8
- vaggos666 for his remarks to Swift 4
(Un)fortunately there is a lot of work going on Swift. This made larger changes to ByteBackpacker needed. The following table shows the compatibility.
Swift version | 2.0 | 3.0 | 4.0 and later |
---|---|---|---|
ByteBackpacker 1.0 | ✓ | ✗ | ✗ |
ByteBackpacker 1.1 | ✗ | ✓ | ✗ |
ByteBackpacker 1.2 and later | ✗ | ✓ | ✓ |
Hopefully the APIs will be stable now.
ByteBackpacker is released under the MIT license. See LICENSE for more details.