一个用于 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]
在 Package.swift
中将 CDRCodable 包添加到您的目标依赖项中
.package(url: "https://github.com/DimaRU/CDRCodable", from: "1.0.0"),
下表显示了 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 |
从 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
}
}
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> |
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
}
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)
}
}
}
struct
可以编码为 Swift struct
或 class
。 例子
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