Files
VibeCoding/webrtc_controller_ios/web_rtc_controller_ios/Control/ControlMessage.swift

180 lines
7.2 KiB
Swift
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import Foundation
/// RTCDataChannel
/// control_message.proto (proto3) protobuf
/// SwiftProtobuf
/// x/y/x1/y1/x2/y2 0.0 ~ 1.0
struct ControlMessage {
enum Action: Int {
case unknown = 0
case touch = 1
case swipe = 2
case key = 3
case longPress = 4
case motionEvent = 5
case setResolution = 6 //
case reportResolution = 7 //
case setStreamMode = 8 //
case reportStreamMode = 9 //
}
var action: Action = .unknown // field 1, varint
var x: Double = 0 // field 2, fixed64
var y: Double = 0 // field 3, fixed64
var x1: Double = 0 // field 4, fixed64
var y1: Double = 0 // field 5, fixed64
var x2: Double = 0 // field 6, fixed64
var y2: Double = 0 // field 7, fixed64
var duration: Int64 = 0 // field 8, varint
var keyCode: Int32 = 0 // field 9, varint
var keyAction: Int32 = 0 // field 10, varint (0= 1=)
var motionAction: Int32 = 0 // field 11, varint (0=DOWN 1=UP 2=MOVE 3=CANCEL)
var width: Int32 = 0 // field 12, varint
var height: Int32 = 0 // field 13, varint
var fps: Int32 = 0 // field 14, varint
var streamMode: Int32 = 0 // field 15, varint (0=WebRTC 1=)
// MARK: - Encode
func serializedData() -> Data {
var w = ProtoWriter()
w.writeVarintField(1, UInt64(action.rawValue))
w.writeDoubleField(2, x)
w.writeDoubleField(3, y)
w.writeDoubleField(4, x1)
w.writeDoubleField(5, y1)
w.writeDoubleField(6, x2)
w.writeDoubleField(7, y2)
w.writeVarintField(8, UInt64(bitPattern: duration))
w.writeVarintField(9, UInt64(bitPattern: Int64(keyCode)))
w.writeVarintField(10, UInt64(bitPattern: Int64(keyAction)))
w.writeVarintField(11, UInt64(bitPattern: Int64(motionAction)))
w.writeVarintField(12, UInt64(bitPattern: Int64(width)))
w.writeVarintField(13, UInt64(bitPattern: Int64(height)))
w.writeVarintField(14, UInt64(bitPattern: Int64(fps)))
w.writeVarintField(15, UInt64(bitPattern: Int64(streamMode)))
return w.data
}
// MARK: - Decode
static func parse(from data: Data) -> ControlMessage? {
var msg = ControlMessage()
var r = ProtoReader(data: data)
while let (field, wire) = r.readTag() {
switch (field, wire) {
case (1, 0):
guard let v = r.readVarint() else { return nil }
msg.action = Action(rawValue: Int(v)) ?? .unknown
case (2, 1): guard let v = r.readDouble() else { return nil }; msg.x = v
case (3, 1): guard let v = r.readDouble() else { return nil }; msg.y = v
case (4, 1): guard let v = r.readDouble() else { return nil }; msg.x1 = v
case (5, 1): guard let v = r.readDouble() else { return nil }; msg.y1 = v
case (6, 1): guard let v = r.readDouble() else { return nil }; msg.x2 = v
case (7, 1): guard let v = r.readDouble() else { return nil }; msg.y2 = v
case (8, 0): guard let v = r.readVarint() else { return nil }; msg.duration = Int64(bitPattern: v)
case (9, 0): guard let v = r.readVarint() else { return nil }; msg.keyCode = Int32(truncatingIfNeeded: Int64(bitPattern: v))
case (10, 0): guard let v = r.readVarint() else { return nil }; msg.keyAction = Int32(truncatingIfNeeded: Int64(bitPattern: v))
case (11, 0): guard let v = r.readVarint() else { return nil }; msg.motionAction = Int32(truncatingIfNeeded: Int64(bitPattern: v))
case (12, 0): guard let v = r.readVarint() else { return nil }; msg.width = Int32(truncatingIfNeeded: Int64(bitPattern: v))
case (13, 0): guard let v = r.readVarint() else { return nil }; msg.height = Int32(truncatingIfNeeded: Int64(bitPattern: v))
case (14, 0): guard let v = r.readVarint() else { return nil }; msg.fps = Int32(truncatingIfNeeded: Int64(bitPattern: v))
case (15, 0): guard let v = r.readVarint() else { return nil }; msg.streamMode = Int32(truncatingIfNeeded: Int64(bitPattern: v))
default:
// wire type
if !r.skip(wireType: wire) { return nil }
}
}
return msg
}
}
// MARK: - protobuf
private struct ProtoWriter {
var data = Data()
mutating func writeVarint(_ value: UInt64) {
var v = value
while v >= 0x80 {
data.append(UInt8((v & 0x7F) | 0x80))
v >>= 7
}
data.append(UInt8(v))
}
/// proto3(0)
mutating func writeVarintField(_ field: Int, _ value: UInt64) {
guard value != 0 else { return }
writeVarint(UInt64(field << 3 | 0))
writeVarint(value)
}
mutating func writeDoubleField(_ field: Int, _ value: Double) {
guard value != 0 else { return }
writeVarint(UInt64(field << 3 | 1))
var bits = value.bitPattern.littleEndian
withUnsafeBytes(of: &bits) { data.append(contentsOf: $0) }
}
}
private struct ProtoReader {
let data: Data
var offset: Int
init(data: Data) {
self.data = data
self.offset = data.startIndex
}
mutating func readTag() -> (Int, Int)? {
guard offset < data.endIndex, let key = readVarint() else { return nil }
return (Int(key >> 3), Int(key & 0x7))
}
mutating func readVarint() -> UInt64? {
var result: UInt64 = 0
var shift: UInt64 = 0
while offset < data.endIndex {
let byte = data[offset]
offset += 1
result |= UInt64(byte & 0x7F) << shift
if byte & 0x80 == 0 { return result }
shift += 7
if shift >= 64 { return nil }
}
return nil
}
mutating func readDouble() -> Double? {
guard offset + 8 <= data.endIndex else { return nil }
var bits: UInt64 = 0
for i in (0..<8).reversed() {
bits = (bits << 8) | UInt64(data[offset + i])
}
offset += 8
return Double(bitPattern: bits)
}
mutating func skip(wireType: Int) -> Bool {
switch wireType {
case 0: return readVarint() != nil
case 1:
guard offset + 8 <= data.endIndex else { return false }
offset += 8
return true
case 2:
guard let len = readVarint(), offset + Int(len) <= data.endIndex else { return false }
offset += Int(len)
return true
case 5:
guard offset + 4 <= data.endIndex else { return false }
offset += 4
return true
default:
return false
}
}
}