Skip to content

PureSwift/TLVCoding

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

164 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

TLVCoding

Swift

TLV8 (Type-Length-Value) Coder library, compatible with Embedded Swift.

Types are encoded and decoded explicitly via TLVCodable — either with conformances generated by the @TLVCodable macro, or written by hand. The library does not depend on Codable runtime machinery or Foundation, so it can be used on bare-metal targets.

Usage

Macro-generated conformance

import TLVCoding

@TLVCodable
struct ProvisioningState: Equatable {

    var state: State

    var result: Result

    enum CodingKeys: UInt8, TLVCodingKey {
        case state  = 0x01
        case result = 0x02
    }
}

let value = ProvisioningState(state: .provisioning, result: .success)
let data = value.tlvData // Data([0x01, 0x01, 0x01, 0x02, 0x01, 0x01])
let decoded = ProvisioningState(tlvData: data)

If no CodingKeys enum is declared, one is generated with sequential type codes in property declaration order.

Hand-written conformance

The same conformance can be written manually (e.g. for Embedded Swift or custom binary layouts):

extension ProvisioningState: TLVCodable {

    init?(tlvData: Data) {
        guard let container = TLVContainer(data: tlvData),
              let state = container.decode(State.self, forKey: CodingKeys.state),
              let result = container.decode(Result.self, forKey: CodingKeys.result)
              else { return nil }
        self.state = state
        self.result = result
    }

    var tlvData: Data {
        var container = TLVContainer()
        container.encode(state, forKey: CodingKeys.state)
        container.encode(result, forKey: CodingKeys.result)
        return container.data
    }
}

Types with a custom binary layout can skip TLVContainer entirely and produce their payload directly:

extension Version: TLVCodable {

    init?(tlvData: Data) {
        guard tlvData.count == 3 else { return nil }
        self.major = tlvData[0]
        self.minor = tlvData[1]
        self.patch = tlvData[2]
    }

    var tlvData: Data {
        Data([major, minor, patch])
    }
}

Embedded Swift

Macros are disabled under Embedded Swift (write conformances by hand) and the swift-syntax dependency can be skipped entirely with the SWIFTPM_ENABLE_MACROS environment variable:

SWIFTPM_ENABLE_MACROS=0 swift build --target TLVCoding \
    --triple armv7em-none-none-eabi \
    -Xswiftc -enable-experimental-feature -Xswiftc Embedded \
    -Xswiftc -wmo

On platforms without Foundation, a minimal Data type is provided by the library.

See Also

  • CoreModel - Swift ORM with the same explicit coding and macro design
  • BluetoothLinux - Pure Swift Linux Bluetooth Stack
  • GATT - Bluetooth Generic Attribute Profile (GATT) for Swift

About

TLV8 (Type-Length-Value) Coder library

Topics

Resources

License

Stars

28 stars

Watchers

2 watching

Forks

Packages

 
 
 

Contributors