CDRCodable

Build

一个用于 Swift Codable 类型的 OMG 通用数据表示 (CDR) (PLAIN_CDR) 编码器和解码器。

现在可以与 FastRTPSSwift 一起使用,它是 eProsima FastDDS 库的 Swift 封装。

使用 msg2swift 从 ROS .msg 文件自动生成 Swift 模型。

要求

用法

编码消息

import CDRCodable

let encoder = CDREncoder()
let value = try! encoder.encode("hello")
// Data([6, 0, 0, 0, 0x68, 0x65, 0x6C, 0x6C, 0x6F, 0, 0, 0])

解码消息

import CDRCodable

let decoder = CDRDecoder()
let data = Data([3, 0, 0, 0, 1, 0, 2, 0, 3, 0])
let value = try! decoder.decode([Int16].self, from: data)
// [1, 2, 3]

安装

Swift 包管理器

Package.swift 中将 CDRCodable 包添加到您的目标依赖项中

.package(url: "https://github.com/DimaRU/CDRCodable", from: "1.0.0"),

支持的 IDL/ROS 类型

1. 原始类型

下表显示了 CDRCodable 支持的基本 IDL 类型以及它们如何映射到 Swift 和 C++11。

Swift C++11 ROS IDL
Int8 char int8 char
UInt8 uint8_t uint8 octet
Int16 int16_t int16 short
UInt16 uint16_t uint16 unsigned short
Int32 int32_t int32 long
UInt32 uint32_t uint32 unsigned long
Int64 int64_t int64 long long
UInt64 uint64_t uint64 unsigned long long
Float float float32 float
Double double float64 double
Bool bool bool boolean
String std::string string string

2. 数组

从 1.1.1 版本开始,CDRCodable 支持固定大小的数组。 CodingKeys 的高 16 位用于此目的。 将 CodingKeys 声明为 Int,并在高 16 位中写入所需的数组大小,并且属性必须声明为 Array。 低 16 位不使用。 注意:对 CodingKeys 进行编号时要小心! 使用 msg2swift 自动创建 CodingKeys。 sensor_msgs/CameraInfo 的 CodingKeys 声明示例

//
// CameraInfo.swift
//
// This file was generated from ROS message file using msg2swift.
//

struct CameraInfo: Codable {
    let header: Header
    let height: UInt32
    let width: UInt32
    let distortionModel: String
    let d: [Double]
    let k: [Double]
    let r: [Double]
    let p: [Double]
    let binningX: UInt32
    let binningY: UInt32
    let roi: RegionOfInterest

    enum CodingKeys: Int, CodingKey {
        case header = 1
        case height = 2
        case width = 3
        case distortionModel = 4
        case d = 5
        case k = 0x90006
        case r = 0x90007
        case p = 0xc0008
        case binningX = 9
        case binningY = 10
        case roi = 11
    }
}

3. 序列

CDRCodable 支持序列,序列在 Swift Array 和 C++ std::vector 容器之间映射。 下表表示 Swift、C++11 和 IDL 之间的映射关系。

Swift C++11 IDL
Data std::vector<uint8_t> sequence<octet>
Array<Int8> std::vector<char> sequence<char>
Array<UInt8> std::vector<uint8_t> sequence<octet>
Array<Int16> std::vector<int16_t> sequence<short>
Array<UInt16> std::vector<uint16_t> sequence<unsigned short>
Array<Int32> std::vector<int32_t> sequence<long>
Array<UInt32> std::vector<uint32_t> sequence<unsigned long>
Array<Int64> std::vector<int64_t> sequence<long long>
Array<UInt64> std::vector<uint64_t> sequence<unsigned long long>
Array<Float> std::vector<float> sequence<float>
Array<Double> std::vector<double> sequence<double>
Array<Bool> std::vector<bool> sequence<boolean>
Array<String> std::vector<std::string> sequence<string>

4. 枚举

Swift IDL
enum e: Int32 enum e

示例:IDL 定义

enum ESubsystemState
{
    UNKNOWN         = 0,
    INITIALIZED     = 1,
    POSTING         = 2,
    ACTIVE          = 3,
    STANDBY         = 4,
    RECOVERY        = 5,
    DISABLED        = 6
};

Swift

enum ESubsystemState: Int32, Codable {
    case unknown         = 0
    case initialized     = 1
    case posting         = 2
    case active          = 3
    case standby         = 4
    case recovery        = 5
    case disabled        = 6
}

5. 联合体

CDRCodable 不直接支持联合类型,需要自定义编码。 例子

IDL 定义

union ControlUnion switch (unsigned long)
{
    case CONTROL_TYPE_S8:
        char value_int8;
    case CONTROL_TYPE_S16:
        short value_int16;
    case CONTROL_TYPE_S32:
        long value_int32;
    case CONTROL_TYPE_S64:
        long long value_int64;
    case CONTROL_TYPE_U8:
        octet value_uint8;
    case CONTROL_TYPE_U16:
        unsigned short value_uint16;
    case CONTROL_TYPE_U32:
        unsigned long value_uint32;
    case CONTROL_TYPE_U64:
        unsigned long long value_uint64;
    case CONTROL_TYPE_BITMASK:
        unsigned long value_bitmask;
    case CONTROL_TYPE_BUTTON:
        boolean value_button;
    case CONTROL_TYPE_BOOLEAN:
        boolean value_boolean;
    case CONTROL_TYPE_STRING:
        string<128> value_string;
    case CONTROL_TYPE_STRING_MENU:
        unsigned long value_string_menu;
    case CONTROL_TYPE_INT_MENU:
        unsigned long value_int_menu;
};

Swift

enum ControlUnion: UInt32, Codable {
    case S8(value: Int8) = 0
    case S16(value: Int16)
    case S32(value: Int32)
    case S64(value: Int64)
    case U8(value: UInt8)
    case U16(value: UInt16)
    case U32(value: UInt32)
    case U64(value: UInt64)
    case Bitmask(bitmask: UInt32)
    case Button(button: Bool)
    case Boolean(value: Bool)
    case StringValue(value: String)
    case StringMenu(stringMenu: UInt32)
    case IntMenu(intMenu: UInt32)
    
    init(from decoder: Decoder) throws {
        var container = try decoder.singleValueContainer()
        let selector = try container.decode(UInt32.self)
        switch selector {
            case 0:
                let value = try container.decode(Int8.self)
                self = .S8(value: value)
            case 1:
                let value = try container.decode(Int16.self)
                self = .S16(value: value)
            case 2:
                let value = try container.decode(Int32.self)
                self = .S32(value: value)
            case 3:
                let value = try container.decode(Int64.self)
                self = .S64(value: value)
            case 4:
                let value = try container.decode(UInt8.self)
                self = .U8(value: value)
            case 5:
                let value = try container.decode(UInt16.self)
                self = .U16(value: value)
            case 6:
                let value = try container.decode(UInt32.self)
                self = .U32(value: value)
            case 7:
                let value = try container.decode(UInt64.self)
                self = .U64(value: value)
            case 8:
                let value = try container.decode(UInt32.self)
                self = .Bitmask(bitmask: value)
            case 9:
                let value = try container.decode(Bool.self)
                self = .Button(button: value)
            case 10:
                let value = try container.decode(Bool.self)
                self = .Boolean(value: value)
            case 11:
                let value = try container.decode(String.self)
                self = .StringValue(value: value)
            case 12:
                let value = try container.decode(UInt32.self)
                self = .StringMenu(stringMenu: value)
            case 13:
                let value = try container.decode(UInt32.self)
                self = .IntMenu(intMenu: value)
            default:
                let error = DecodingError.dataCorruptedError(in: container, debugDescription: "Illegal union selector \(selector)")
                throw error
        }
    }
    
    func encode(to encoder: Encoder) throws {
        var container = encoder.singleValueContainer()
        try container.encode(self.rawValue)
        switch self {
        case .S8(value: let value): try container.encode(value)
        case .S16(value: let value): try container.encode(value)
        case .S32(value: let value): try container.encode(value)
        case .S64(value: let value): try container.encode(value)
        case .U8(value: let value): try container.encode(value)
        case .U16(value: let value): try container.encode(value)
        case .U32(value: let value): try container.encode(value)
        case .U64(value: let value): try container.encode(value)
        case .Bitmask(bitmask: let bitmask): try container.encode(bitmask)
        case .Button(button: let button): try container.encode(button)
        case .Boolean(value: let value): try container.encode(value)
        case .StringValue(value: let value): try container.encode(value)
        case .StringMenu(stringMenu: let stringMenu): try container.encode(stringMenu)
        case .IntMenu(intMenu: let intMenu): try container.encode(intMenu)
        }
    }
}

6. 结构体

struct 可以编码为 Swift structclass。 例子

IDL 定义

struct ControlTarget
{
    string id;
    
    float pitch;
    float yaw;
    float thrust;
    float lift;
};
struct ControlTarget: Codable
{
    let id: String

    let pitch: Float
    let yaw: Float
    let thrust: Float
    let lift: Float
}

许可证

MIT