From bde94e877ebf60508480e5e23de09468ad671c92 Mon Sep 17 00:00:00 2001 From: Garth Vander Houwen Date: Sun, 10 Dec 2023 17:54:45 -0800 Subject: [PATCH] Update protos and related enums. --- Meshtastic/Enums/DeviceEnums.swift | 28 + Meshtastic/MeshtasticApp.swift | 68 +- .../Protobufs/meshtastic/config.pb.swift | 32 + Meshtastic/Protobufs/meshtastic/mesh.pb.swift | 580 ++++++++++-------- 4 files changed, 419 insertions(+), 289 deletions(-) diff --git a/Meshtastic/Enums/DeviceEnums.swift b/Meshtastic/Enums/DeviceEnums.swift index 052607ab..25938a50 100644 --- a/Meshtastic/Enums/DeviceEnums.swift +++ b/Meshtastic/Enums/DeviceEnums.swift @@ -17,6 +17,9 @@ enum DeviceRoles: Int, CaseIterable, Identifiable { case repeater = 4 case tracker = 5 case sensor = 6 + case tak = 7 + case clientHidden = 8 + case lostAndFound = 9 var id: Int { self.rawValue } var name: String { @@ -35,6 +38,12 @@ enum DeviceRoles: Int, CaseIterable, Identifiable { return "Tracker" case .sensor: return "Sensor" + case .tak: + return "TAK" + case .clientHidden: + return "Client Hidden" + case .lostAndFound: + return "Lost and Found" } } var description: String { @@ -53,6 +62,12 @@ enum DeviceRoles: Int, CaseIterable, Identifiable { return "device.role.tracker".localized case .sensor: return "device.role.sensor".localized + case .tak: + return "device.role.tak".localized + case .clientHidden: + return "device.role.clienthidden".localized + case .lostAndFound: + return "device.role.lostandfound".localized } } func protoEnumValue() -> Config.DeviceConfig.Role { @@ -72,6 +87,12 @@ enum DeviceRoles: Int, CaseIterable, Identifiable { return Config.DeviceConfig.Role.tracker case .sensor: return Config.DeviceConfig.Role.sensor + case .tak: + return Config.DeviceConfig.Role.tak + case .clientHidden: + return Config.DeviceConfig.Role.clientHidden + case .lostAndFound: + return Config.DeviceConfig.Role.lostAndFound } } } @@ -81,6 +102,7 @@ enum RebroadcastModes: Int, CaseIterable, Identifiable { case all = 0 case allSkipDecoding = 1 case localOnly = 2 + case knownOnly = 3 var id: Int { self.rawValue } @@ -92,6 +114,8 @@ enum RebroadcastModes: Int, CaseIterable, Identifiable { return "All Skip Decoding" case .localOnly: return "Local Only" + case .knownOnly: + return "Known Only" } } var description: String { @@ -102,6 +126,8 @@ enum RebroadcastModes: Int, CaseIterable, Identifiable { return "Same as behavior as ALL but skips packet decoding and simply rebroadcasts them. Only available in Repeater role. Setting this on any other roles will result in ALL behavior." case .localOnly: return "Ignores observed messages from foreign meshes that are open or those which it cannot decrypt. Only rebroadcasts message on the nodes local primary / secondary channels." + case .knownOnly: + return "Ignores observed messages from foreign meshes like Local Only, but takes it step further by also ignoring messages from nodes not already in the node's known list." } } func protoEnumValue() -> Config.DeviceConfig.RebroadcastMode { @@ -113,6 +139,8 @@ enum RebroadcastModes: Int, CaseIterable, Identifiable { return Config.DeviceConfig.RebroadcastMode.allSkipDecoding case .localOnly: return Config.DeviceConfig.RebroadcastMode.localOnly + case .knownOnly: + return Config.DeviceConfig.RebroadcastMode.knownOnly } } } diff --git a/Meshtastic/MeshtasticApp.swift b/Meshtastic/MeshtasticApp.swift index 9a43be75..852b2504 100644 --- a/Meshtastic/MeshtasticApp.swift +++ b/Meshtastic/MeshtasticApp.swift @@ -59,40 +59,42 @@ struct MeshtasticAppleApp: App { saveChannels = false print("User wants to import a MBTILES offline map file: \(self.incomingUrl?.absoluteString ?? "No Tiles link")") } + + if UserDefaults.mapUseLegacy { + /// we are expecting a .mbtiles map file that contains raster data + /// save it to the documents directory, and name it offline_map.mbtiles + let fileManager = FileManager.default + let documentsDirectory = fileManager.urls(for: .documentDirectory, in: .userDomainMask).first! + let destination = documentsDirectory.appendingPathComponent("offline_map.mbtiles", isDirectory: false) - // we are expecting a .mbtiles map file that contains raster data - // save it to the documents directory, and name it offline_map.mbtiles - let fileManager = FileManager.default - let documentsDirectory = fileManager.urls(for: .documentDirectory, in: .userDomainMask).first! - let destination = documentsDirectory.appendingPathComponent("offline_map.mbtiles", isDirectory: false) - - if !self.saveChannels { - - // tell the system we want the file please - guard url.startAccessingSecurityScopedResource() else { - return - } - - // do we need to delete an old one? - if fileManager.fileExists(atPath: destination.path) { - print("ℹ️ Found an old map file. Deleting it") - try? fileManager.removeItem(atPath: destination.path) - } - - do { - try fileManager.copyItem(at: url, to: destination) - } catch { - print("Copy MB Tile file failed. Error: \(error)") - } - - if fileManager.fileExists(atPath: destination.path) { - print("ℹ️ Saved the map file") - - // need to tell the map view that it needs to update and try loading the new overlay - UserDefaults.standard.set(Date().timeIntervalSince1970, forKey: "lastUpdatedLocalMapFile") - - } else { - print("💥 Didn't save the map file") + if !self.saveChannels { + + // tell the system we want the file please + guard url.startAccessingSecurityScopedResource() else { + return + } + + // do we need to delete an old one? + if fileManager.fileExists(atPath: destination.path) { + print("ℹ️ Found an old map file. Deleting it") + try? fileManager.removeItem(atPath: destination.path) + } + + do { + try fileManager.copyItem(at: url, to: destination) + } catch { + print("Copy MB Tile file failed. Error: \(error)") + } + + if fileManager.fileExists(atPath: destination.path) { + print("ℹ️ Saved the map file") + + // need to tell the map view that it needs to update and try loading the new overlay + UserDefaults.standard.set(Date().timeIntervalSince1970, forKey: "lastUpdatedLocalMapFile") + + } else { + print("💥 Didn't save the map file") + } } } }) diff --git a/Meshtastic/Protobufs/meshtastic/config.pb.swift b/Meshtastic/Protobufs/meshtastic/config.pb.swift index d04e9003..ef91027c 100644 --- a/Meshtastic/Protobufs/meshtastic/config.pb.swift +++ b/Meshtastic/Protobufs/meshtastic/config.pb.swift @@ -244,6 +244,21 @@ struct Config { /// Turns off many of the routine broadcasts to favor CoT packet stream /// from the Meshtastic ATAK plugin -> IMeshService -> Node case tak // = 7 + + /// + /// Client Hidden device role + /// Used for nodes that "only speak when spoken to" + /// Turns all of the routine broadcasts but allows for ad-hoc communication + /// Still rebroadcasts, but with local only rebroadcast mode (known meshes only) + /// Can be used for clandestine operation or to dramatically reduce airtime / power consumption + case clientHidden // = 8 + + /// + /// Lost and Found device role + /// Used to automatically send a text message to the mesh + /// with the current position of the device on a frequent interval: + /// "I'm lost! Position: lat / long" + case lostAndFound // = 9 case UNRECOGNIZED(Int) init() { @@ -260,6 +275,8 @@ struct Config { case 5: self = .tracker case 6: self = .sensor case 7: self = .tak + case 8: self = .clientHidden + case 9: self = .lostAndFound default: self = .UNRECOGNIZED(rawValue) } } @@ -274,6 +291,8 @@ struct Config { case .tracker: return 5 case .sensor: return 6 case .tak: return 7 + case .clientHidden: return 8 + case .lostAndFound: return 9 case .UNRECOGNIZED(let i): return i } } @@ -299,6 +318,11 @@ struct Config { /// Ignores observed messages from foreign meshes that are open or those which it cannot decrypt. /// Only rebroadcasts message on the nodes local primary / secondary channels. case localOnly // = 2 + + /// + /// Ignores observed messages from foreign meshes like LOCAL_ONLY, + /// but takes it step further by also ignoring messages from nodenums not in the node's known list (NodeDB) + case knownOnly // = 3 case UNRECOGNIZED(Int) init() { @@ -310,6 +334,7 @@ struct Config { case 0: self = .all case 1: self = .allSkipDecoding case 2: self = .localOnly + case 3: self = .knownOnly default: self = .UNRECOGNIZED(rawValue) } } @@ -319,6 +344,7 @@ struct Config { case .all: return 0 case .allSkipDecoding: return 1 case .localOnly: return 2 + case .knownOnly: return 3 case .UNRECOGNIZED(let i): return i } } @@ -1295,6 +1321,8 @@ extension Config.DeviceConfig.Role: CaseIterable { .tracker, .sensor, .tak, + .clientHidden, + .lostAndFound, ] } @@ -1304,6 +1332,7 @@ extension Config.DeviceConfig.RebroadcastMode: CaseIterable { .all, .allSkipDecoding, .localOnly, + .knownOnly, ] } @@ -1703,6 +1732,8 @@ extension Config.DeviceConfig.Role: SwiftProtobuf._ProtoNameProviding { 5: .same(proto: "TRACKER"), 6: .same(proto: "SENSOR"), 7: .same(proto: "TAK"), + 8: .same(proto: "CLIENT_HIDDEN"), + 9: .same(proto: "LOST_AND_FOUND"), ] } @@ -1711,6 +1742,7 @@ extension Config.DeviceConfig.RebroadcastMode: SwiftProtobuf._ProtoNameProviding 0: .same(proto: "ALL"), 1: .same(proto: "ALL_SKIP_DECODING"), 2: .same(proto: "LOCAL_ONLY"), + 3: .same(proto: "KNOWN_ONLY"), ] } diff --git a/Meshtastic/Protobufs/meshtastic/mesh.pb.swift b/Meshtastic/Protobufs/meshtastic/mesh.pb.swift index cc2388a8..b8ebf212 100644 --- a/Meshtastic/Protobufs/meshtastic/mesh.pb.swift +++ b/Meshtastic/Protobufs/meshtastic/mesh.pb.swift @@ -118,6 +118,14 @@ enum HardwareModel: SwiftProtobuf.Enum { /// RAK11310 (RP2040 + SX1262) case rak11310 // = 26 + /// + /// Makerfabs SenseLoRA Receiver (RP2040 + RFM96) + case senseloraRp2040 // = 27 + + /// + /// Makerfabs SenseLoRA Industrial Monitor (ESP32-S3 + RFM96) + case senseloraS3 // = 28 + /// /// --------------------------------------------------------------------------- /// Less common/prototype boards listed here (needs one more byte over the air) @@ -247,6 +255,8 @@ enum HardwareModel: SwiftProtobuf.Enum { case 19: self = .loraType case 25: self = .stationG1 case 26: self = .rak11310 + case 27: self = .senseloraRp2040 + case 28: self = .senseloraS3 case 32: self = .loraRelayV1 case 33: self = .nrf52840Dk case 34: self = .ppr @@ -299,6 +309,8 @@ enum HardwareModel: SwiftProtobuf.Enum { case .loraType: return 19 case .stationG1: return 25 case .rak11310: return 26 + case .senseloraRp2040: return 27 + case .senseloraS3: return 28 case .loraRelayV1: return 32 case .nrf52840Dk: return 33 case .ppr: return 34 @@ -356,6 +368,8 @@ extension HardwareModel: CaseIterable { .loraType, .stationG1, .rak11310, + .senseloraRp2040, + .senseloraS3, .loraRelayV1, .nrf52840Dk, .ppr, @@ -935,6 +949,10 @@ struct User { /// Also, "long_name" should be their licence number. var isLicensed: Bool = false + /// + /// Indicates that the user's role in the mesh + var role: Config.DeviceConfig.Role = .client + var unknownFields = SwiftProtobuf.UnknownStorage() init() {} @@ -1930,20 +1948,26 @@ struct FromRadio { /// /// The packet id, used to allow the phone to request missing read packets from the FIFO, /// see our bluetooth docs - var id: UInt32 = 0 + var id: UInt32 { + get {return _storage._id} + set {_uniqueStorage()._id = newValue} + } /// /// Log levels, chosen to match python logging conventions. - var payloadVariant: FromRadio.OneOf_PayloadVariant? = nil + var payloadVariant: OneOf_PayloadVariant? { + get {return _storage._payloadVariant} + set {_uniqueStorage()._payloadVariant = newValue} + } /// /// Log levels, chosen to match python logging conventions. var packet: MeshPacket { get { - if case .packet(let v)? = payloadVariant {return v} + if case .packet(let v)? = _storage._payloadVariant {return v} return MeshPacket() } - set {payloadVariant = .packet(newValue)} + set {_uniqueStorage()._payloadVariant = .packet(newValue)} } /// @@ -1951,10 +1975,10 @@ struct FromRadio { /// NOTE: This ID must not change - to keep (minimal) compatibility with <1.2 version of android apps. var myInfo: MyNodeInfo { get { - if case .myInfo(let v)? = payloadVariant {return v} + if case .myInfo(let v)? = _storage._payloadVariant {return v} return MyNodeInfo() } - set {payloadVariant = .myInfo(newValue)} + set {_uniqueStorage()._payloadVariant = .myInfo(newValue)} } /// @@ -1962,30 +1986,30 @@ struct FromRadio { /// starts over with the first node in our DB var nodeInfo: NodeInfo { get { - if case .nodeInfo(let v)? = payloadVariant {return v} + if case .nodeInfo(let v)? = _storage._payloadVariant {return v} return NodeInfo() } - set {payloadVariant = .nodeInfo(newValue)} + set {_uniqueStorage()._payloadVariant = .nodeInfo(newValue)} } /// /// Include a part of the config (was: RadioConfig radio) var config: Config { get { - if case .config(let v)? = payloadVariant {return v} + if case .config(let v)? = _storage._payloadVariant {return v} return Config() } - set {payloadVariant = .config(newValue)} + set {_uniqueStorage()._payloadVariant = .config(newValue)} } /// /// Set to send debug console output over our protobuf stream var logRecord: LogRecord { get { - if case .logRecord(let v)? = payloadVariant {return v} + if case .logRecord(let v)? = _storage._payloadVariant {return v} return LogRecord() } - set {payloadVariant = .logRecord(newValue)} + set {_uniqueStorage()._payloadVariant = .logRecord(newValue)} } /// @@ -1995,10 +2019,10 @@ struct FromRadio { /// NOTE: This ID must not change - to keep (minimal) compatibility with <1.2 version of android apps. var configCompleteID: UInt32 { get { - if case .configCompleteID(let v)? = payloadVariant {return v} + if case .configCompleteID(let v)? = _storage._payloadVariant {return v} return 0 } - set {payloadVariant = .configCompleteID(newValue)} + set {_uniqueStorage()._payloadVariant = .configCompleteID(newValue)} } /// @@ -2008,70 +2032,70 @@ struct FromRadio { /// NOTE: This ID must not change - to keep (minimal) compatibility with <1.2 version of android apps. var rebooted: Bool { get { - if case .rebooted(let v)? = payloadVariant {return v} + if case .rebooted(let v)? = _storage._payloadVariant {return v} return false } - set {payloadVariant = .rebooted(newValue)} + set {_uniqueStorage()._payloadVariant = .rebooted(newValue)} } /// /// Include module config var moduleConfig: ModuleConfig { get { - if case .moduleConfig(let v)? = payloadVariant {return v} + if case .moduleConfig(let v)? = _storage._payloadVariant {return v} return ModuleConfig() } - set {payloadVariant = .moduleConfig(newValue)} + set {_uniqueStorage()._payloadVariant = .moduleConfig(newValue)} } /// /// One packet is sent for each channel var channel: Channel { get { - if case .channel(let v)? = payloadVariant {return v} + if case .channel(let v)? = _storage._payloadVariant {return v} return Channel() } - set {payloadVariant = .channel(newValue)} + set {_uniqueStorage()._payloadVariant = .channel(newValue)} } /// /// Queue status info var queueStatus: QueueStatus { get { - if case .queueStatus(let v)? = payloadVariant {return v} + if case .queueStatus(let v)? = _storage._payloadVariant {return v} return QueueStatus() } - set {payloadVariant = .queueStatus(newValue)} + set {_uniqueStorage()._payloadVariant = .queueStatus(newValue)} } /// /// File Transfer Chunk var xmodemPacket: XModem { get { - if case .xmodemPacket(let v)? = payloadVariant {return v} + if case .xmodemPacket(let v)? = _storage._payloadVariant {return v} return XModem() } - set {payloadVariant = .xmodemPacket(newValue)} + set {_uniqueStorage()._payloadVariant = .xmodemPacket(newValue)} } /// /// Device metadata message var metadata: DeviceMetadata { get { - if case .metadata(let v)? = payloadVariant {return v} + if case .metadata(let v)? = _storage._payloadVariant {return v} return DeviceMetadata() } - set {payloadVariant = .metadata(newValue)} + set {_uniqueStorage()._payloadVariant = .metadata(newValue)} } /// /// MQTT Client Proxy Message (device sending to client / phone for publishing to MQTT) var mqttClientProxyMessage: MqttClientProxyMessage { get { - if case .mqttClientProxyMessage(let v)? = payloadVariant {return v} + if case .mqttClientProxyMessage(let v)? = _storage._payloadVariant {return v} return MqttClientProxyMessage() } - set {payloadVariant = .mqttClientProxyMessage(newValue)} + set {_uniqueStorage()._payloadVariant = .mqttClientProxyMessage(newValue)} } var unknownFields = SwiftProtobuf.UnknownStorage() @@ -2192,6 +2216,8 @@ struct FromRadio { } init() {} + + fileprivate var _storage = _StorageClass.defaultInstance } /// @@ -2519,6 +2545,8 @@ extension HardwareModel: SwiftProtobuf._ProtoNameProviding { 19: .same(proto: "LORA_TYPE"), 25: .same(proto: "STATION_G1"), 26: .same(proto: "RAK11310"), + 27: .same(proto: "SENSELORA_RP2040"), + 28: .same(proto: "SENSELORA_S3"), 32: .same(proto: "LORA_RELAY_V1"), 33: .same(proto: "NRF52840DK"), 34: .same(proto: "PPR"), @@ -2830,6 +2858,7 @@ extension User: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, 4: .same(proto: "macaddr"), 5: .standard(proto: "hw_model"), 6: .standard(proto: "is_licensed"), + 7: .same(proto: "role"), ] mutating func decodeMessage(decoder: inout D) throws { @@ -2844,6 +2873,7 @@ extension User: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, case 4: try { try decoder.decodeSingularBytesField(value: &self.macaddr) }() case 5: try { try decoder.decodeSingularEnumField(value: &self.hwModel) }() case 6: try { try decoder.decodeSingularBoolField(value: &self.isLicensed) }() + case 7: try { try decoder.decodeSingularEnumField(value: &self.role) }() default: break } } @@ -2868,6 +2898,9 @@ extension User: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, if self.isLicensed != false { try visitor.visitSingularBoolField(value: self.isLicensed, fieldNumber: 6) } + if self.role != .client { + try visitor.visitSingularEnumField(value: self.role, fieldNumber: 7) + } try unknownFields.traverse(visitor: &visitor) } @@ -2878,6 +2911,7 @@ extension User: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, if lhs.macaddr != rhs.macaddr {return false} if lhs.hwModel != rhs.hwModel {return false} if lhs.isLicensed != rhs.isLicensed {return false} + if lhs.role != rhs.role {return false} if lhs.unknownFields != rhs.unknownFields {return false} return true } @@ -3687,246 +3721,280 @@ extension FromRadio: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementation 14: .same(proto: "mqttClientProxyMessage"), ] + fileprivate class _StorageClass { + var _id: UInt32 = 0 + var _payloadVariant: FromRadio.OneOf_PayloadVariant? + + static let defaultInstance = _StorageClass() + + private init() {} + + init(copying source: _StorageClass) { + _id = source._id + _payloadVariant = source._payloadVariant + } + } + + fileprivate mutating func _uniqueStorage() -> _StorageClass { + if !isKnownUniquelyReferenced(&_storage) { + _storage = _StorageClass(copying: _storage) + } + return _storage + } + mutating func decodeMessage(decoder: inout D) throws { - while let fieldNumber = try decoder.nextFieldNumber() { - // The use of inline closures is to circumvent an issue where the compiler - // allocates stack space for every case branch when no optimizations are - // enabled. https://github.com/apple/swift-protobuf/issues/1034 - switch fieldNumber { - case 1: try { try decoder.decodeSingularUInt32Field(value: &self.id) }() - case 2: try { - var v: MeshPacket? - var hadOneofValue = false - if let current = self.payloadVariant { - hadOneofValue = true - if case .packet(let m) = current {v = m} + _ = _uniqueStorage() + try withExtendedLifetime(_storage) { (_storage: _StorageClass) in + while let fieldNumber = try decoder.nextFieldNumber() { + // The use of inline closures is to circumvent an issue where the compiler + // allocates stack space for every case branch when no optimizations are + // enabled. https://github.com/apple/swift-protobuf/issues/1034 + switch fieldNumber { + case 1: try { try decoder.decodeSingularUInt32Field(value: &_storage._id) }() + case 2: try { + var v: MeshPacket? + var hadOneofValue = false + if let current = _storage._payloadVariant { + hadOneofValue = true + if case .packet(let m) = current {v = m} + } + try decoder.decodeSingularMessageField(value: &v) + if let v = v { + if hadOneofValue {try decoder.handleConflictingOneOf()} + _storage._payloadVariant = .packet(v) + } + }() + case 3: try { + var v: MyNodeInfo? + var hadOneofValue = false + if let current = _storage._payloadVariant { + hadOneofValue = true + if case .myInfo(let m) = current {v = m} + } + try decoder.decodeSingularMessageField(value: &v) + if let v = v { + if hadOneofValue {try decoder.handleConflictingOneOf()} + _storage._payloadVariant = .myInfo(v) + } + }() + case 4: try { + var v: NodeInfo? + var hadOneofValue = false + if let current = _storage._payloadVariant { + hadOneofValue = true + if case .nodeInfo(let m) = current {v = m} + } + try decoder.decodeSingularMessageField(value: &v) + if let v = v { + if hadOneofValue {try decoder.handleConflictingOneOf()} + _storage._payloadVariant = .nodeInfo(v) + } + }() + case 5: try { + var v: Config? + var hadOneofValue = false + if let current = _storage._payloadVariant { + hadOneofValue = true + if case .config(let m) = current {v = m} + } + try decoder.decodeSingularMessageField(value: &v) + if let v = v { + if hadOneofValue {try decoder.handleConflictingOneOf()} + _storage._payloadVariant = .config(v) + } + }() + case 6: try { + var v: LogRecord? + var hadOneofValue = false + if let current = _storage._payloadVariant { + hadOneofValue = true + if case .logRecord(let m) = current {v = m} + } + try decoder.decodeSingularMessageField(value: &v) + if let v = v { + if hadOneofValue {try decoder.handleConflictingOneOf()} + _storage._payloadVariant = .logRecord(v) + } + }() + case 7: try { + var v: UInt32? + try decoder.decodeSingularUInt32Field(value: &v) + if let v = v { + if _storage._payloadVariant != nil {try decoder.handleConflictingOneOf()} + _storage._payloadVariant = .configCompleteID(v) + } + }() + case 8: try { + var v: Bool? + try decoder.decodeSingularBoolField(value: &v) + if let v = v { + if _storage._payloadVariant != nil {try decoder.handleConflictingOneOf()} + _storage._payloadVariant = .rebooted(v) + } + }() + case 9: try { + var v: ModuleConfig? + var hadOneofValue = false + if let current = _storage._payloadVariant { + hadOneofValue = true + if case .moduleConfig(let m) = current {v = m} + } + try decoder.decodeSingularMessageField(value: &v) + if let v = v { + if hadOneofValue {try decoder.handleConflictingOneOf()} + _storage._payloadVariant = .moduleConfig(v) + } + }() + case 10: try { + var v: Channel? + var hadOneofValue = false + if let current = _storage._payloadVariant { + hadOneofValue = true + if case .channel(let m) = current {v = m} + } + try decoder.decodeSingularMessageField(value: &v) + if let v = v { + if hadOneofValue {try decoder.handleConflictingOneOf()} + _storage._payloadVariant = .channel(v) + } + }() + case 11: try { + var v: QueueStatus? + var hadOneofValue = false + if let current = _storage._payloadVariant { + hadOneofValue = true + if case .queueStatus(let m) = current {v = m} + } + try decoder.decodeSingularMessageField(value: &v) + if let v = v { + if hadOneofValue {try decoder.handleConflictingOneOf()} + _storage._payloadVariant = .queueStatus(v) + } + }() + case 12: try { + var v: XModem? + var hadOneofValue = false + if let current = _storage._payloadVariant { + hadOneofValue = true + if case .xmodemPacket(let m) = current {v = m} + } + try decoder.decodeSingularMessageField(value: &v) + if let v = v { + if hadOneofValue {try decoder.handleConflictingOneOf()} + _storage._payloadVariant = .xmodemPacket(v) + } + }() + case 13: try { + var v: DeviceMetadata? + var hadOneofValue = false + if let current = _storage._payloadVariant { + hadOneofValue = true + if case .metadata(let m) = current {v = m} + } + try decoder.decodeSingularMessageField(value: &v) + if let v = v { + if hadOneofValue {try decoder.handleConflictingOneOf()} + _storage._payloadVariant = .metadata(v) + } + }() + case 14: try { + var v: MqttClientProxyMessage? + var hadOneofValue = false + if let current = _storage._payloadVariant { + hadOneofValue = true + if case .mqttClientProxyMessage(let m) = current {v = m} + } + try decoder.decodeSingularMessageField(value: &v) + if let v = v { + if hadOneofValue {try decoder.handleConflictingOneOf()} + _storage._payloadVariant = .mqttClientProxyMessage(v) + } + }() + default: break } - try decoder.decodeSingularMessageField(value: &v) - if let v = v { - if hadOneofValue {try decoder.handleConflictingOneOf()} - self.payloadVariant = .packet(v) - } - }() - case 3: try { - var v: MyNodeInfo? - var hadOneofValue = false - if let current = self.payloadVariant { - hadOneofValue = true - if case .myInfo(let m) = current {v = m} - } - try decoder.decodeSingularMessageField(value: &v) - if let v = v { - if hadOneofValue {try decoder.handleConflictingOneOf()} - self.payloadVariant = .myInfo(v) - } - }() - case 4: try { - var v: NodeInfo? - var hadOneofValue = false - if let current = self.payloadVariant { - hadOneofValue = true - if case .nodeInfo(let m) = current {v = m} - } - try decoder.decodeSingularMessageField(value: &v) - if let v = v { - if hadOneofValue {try decoder.handleConflictingOneOf()} - self.payloadVariant = .nodeInfo(v) - } - }() - case 5: try { - var v: Config? - var hadOneofValue = false - if let current = self.payloadVariant { - hadOneofValue = true - if case .config(let m) = current {v = m} - } - try decoder.decodeSingularMessageField(value: &v) - if let v = v { - if hadOneofValue {try decoder.handleConflictingOneOf()} - self.payloadVariant = .config(v) - } - }() - case 6: try { - var v: LogRecord? - var hadOneofValue = false - if let current = self.payloadVariant { - hadOneofValue = true - if case .logRecord(let m) = current {v = m} - } - try decoder.decodeSingularMessageField(value: &v) - if let v = v { - if hadOneofValue {try decoder.handleConflictingOneOf()} - self.payloadVariant = .logRecord(v) - } - }() - case 7: try { - var v: UInt32? - try decoder.decodeSingularUInt32Field(value: &v) - if let v = v { - if self.payloadVariant != nil {try decoder.handleConflictingOneOf()} - self.payloadVariant = .configCompleteID(v) - } - }() - case 8: try { - var v: Bool? - try decoder.decodeSingularBoolField(value: &v) - if let v = v { - if self.payloadVariant != nil {try decoder.handleConflictingOneOf()} - self.payloadVariant = .rebooted(v) - } - }() - case 9: try { - var v: ModuleConfig? - var hadOneofValue = false - if let current = self.payloadVariant { - hadOneofValue = true - if case .moduleConfig(let m) = current {v = m} - } - try decoder.decodeSingularMessageField(value: &v) - if let v = v { - if hadOneofValue {try decoder.handleConflictingOneOf()} - self.payloadVariant = .moduleConfig(v) - } - }() - case 10: try { - var v: Channel? - var hadOneofValue = false - if let current = self.payloadVariant { - hadOneofValue = true - if case .channel(let m) = current {v = m} - } - try decoder.decodeSingularMessageField(value: &v) - if let v = v { - if hadOneofValue {try decoder.handleConflictingOneOf()} - self.payloadVariant = .channel(v) - } - }() - case 11: try { - var v: QueueStatus? - var hadOneofValue = false - if let current = self.payloadVariant { - hadOneofValue = true - if case .queueStatus(let m) = current {v = m} - } - try decoder.decodeSingularMessageField(value: &v) - if let v = v { - if hadOneofValue {try decoder.handleConflictingOneOf()} - self.payloadVariant = .queueStatus(v) - } - }() - case 12: try { - var v: XModem? - var hadOneofValue = false - if let current = self.payloadVariant { - hadOneofValue = true - if case .xmodemPacket(let m) = current {v = m} - } - try decoder.decodeSingularMessageField(value: &v) - if let v = v { - if hadOneofValue {try decoder.handleConflictingOneOf()} - self.payloadVariant = .xmodemPacket(v) - } - }() - case 13: try { - var v: DeviceMetadata? - var hadOneofValue = false - if let current = self.payloadVariant { - hadOneofValue = true - if case .metadata(let m) = current {v = m} - } - try decoder.decodeSingularMessageField(value: &v) - if let v = v { - if hadOneofValue {try decoder.handleConflictingOneOf()} - self.payloadVariant = .metadata(v) - } - }() - case 14: try { - var v: MqttClientProxyMessage? - var hadOneofValue = false - if let current = self.payloadVariant { - hadOneofValue = true - if case .mqttClientProxyMessage(let m) = current {v = m} - } - try decoder.decodeSingularMessageField(value: &v) - if let v = v { - if hadOneofValue {try decoder.handleConflictingOneOf()} - self.payloadVariant = .mqttClientProxyMessage(v) - } - }() - default: break } } } func traverse(visitor: inout V) throws { - // The use of inline closures is to circumvent an issue where the compiler - // allocates stack space for every if/case branch local when no optimizations - // are enabled. https://github.com/apple/swift-protobuf/issues/1034 and - // https://github.com/apple/swift-protobuf/issues/1182 - if self.id != 0 { - try visitor.visitSingularUInt32Field(value: self.id, fieldNumber: 1) - } - switch self.payloadVariant { - case .packet?: try { - guard case .packet(let v)? = self.payloadVariant else { preconditionFailure() } - try visitor.visitSingularMessageField(value: v, fieldNumber: 2) - }() - case .myInfo?: try { - guard case .myInfo(let v)? = self.payloadVariant else { preconditionFailure() } - try visitor.visitSingularMessageField(value: v, fieldNumber: 3) - }() - case .nodeInfo?: try { - guard case .nodeInfo(let v)? = self.payloadVariant else { preconditionFailure() } - try visitor.visitSingularMessageField(value: v, fieldNumber: 4) - }() - case .config?: try { - guard case .config(let v)? = self.payloadVariant else { preconditionFailure() } - try visitor.visitSingularMessageField(value: v, fieldNumber: 5) - }() - case .logRecord?: try { - guard case .logRecord(let v)? = self.payloadVariant else { preconditionFailure() } - try visitor.visitSingularMessageField(value: v, fieldNumber: 6) - }() - case .configCompleteID?: try { - guard case .configCompleteID(let v)? = self.payloadVariant else { preconditionFailure() } - try visitor.visitSingularUInt32Field(value: v, fieldNumber: 7) - }() - case .rebooted?: try { - guard case .rebooted(let v)? = self.payloadVariant else { preconditionFailure() } - try visitor.visitSingularBoolField(value: v, fieldNumber: 8) - }() - case .moduleConfig?: try { - guard case .moduleConfig(let v)? = self.payloadVariant else { preconditionFailure() } - try visitor.visitSingularMessageField(value: v, fieldNumber: 9) - }() - case .channel?: try { - guard case .channel(let v)? = self.payloadVariant else { preconditionFailure() } - try visitor.visitSingularMessageField(value: v, fieldNumber: 10) - }() - case .queueStatus?: try { - guard case .queueStatus(let v)? = self.payloadVariant else { preconditionFailure() } - try visitor.visitSingularMessageField(value: v, fieldNumber: 11) - }() - case .xmodemPacket?: try { - guard case .xmodemPacket(let v)? = self.payloadVariant else { preconditionFailure() } - try visitor.visitSingularMessageField(value: v, fieldNumber: 12) - }() - case .metadata?: try { - guard case .metadata(let v)? = self.payloadVariant else { preconditionFailure() } - try visitor.visitSingularMessageField(value: v, fieldNumber: 13) - }() - case .mqttClientProxyMessage?: try { - guard case .mqttClientProxyMessage(let v)? = self.payloadVariant else { preconditionFailure() } - try visitor.visitSingularMessageField(value: v, fieldNumber: 14) - }() - case nil: break + try withExtendedLifetime(_storage) { (_storage: _StorageClass) in + // The use of inline closures is to circumvent an issue where the compiler + // allocates stack space for every if/case branch local when no optimizations + // are enabled. https://github.com/apple/swift-protobuf/issues/1034 and + // https://github.com/apple/swift-protobuf/issues/1182 + if _storage._id != 0 { + try visitor.visitSingularUInt32Field(value: _storage._id, fieldNumber: 1) + } + switch _storage._payloadVariant { + case .packet?: try { + guard case .packet(let v)? = _storage._payloadVariant else { preconditionFailure() } + try visitor.visitSingularMessageField(value: v, fieldNumber: 2) + }() + case .myInfo?: try { + guard case .myInfo(let v)? = _storage._payloadVariant else { preconditionFailure() } + try visitor.visitSingularMessageField(value: v, fieldNumber: 3) + }() + case .nodeInfo?: try { + guard case .nodeInfo(let v)? = _storage._payloadVariant else { preconditionFailure() } + try visitor.visitSingularMessageField(value: v, fieldNumber: 4) + }() + case .config?: try { + guard case .config(let v)? = _storage._payloadVariant else { preconditionFailure() } + try visitor.visitSingularMessageField(value: v, fieldNumber: 5) + }() + case .logRecord?: try { + guard case .logRecord(let v)? = _storage._payloadVariant else { preconditionFailure() } + try visitor.visitSingularMessageField(value: v, fieldNumber: 6) + }() + case .configCompleteID?: try { + guard case .configCompleteID(let v)? = _storage._payloadVariant else { preconditionFailure() } + try visitor.visitSingularUInt32Field(value: v, fieldNumber: 7) + }() + case .rebooted?: try { + guard case .rebooted(let v)? = _storage._payloadVariant else { preconditionFailure() } + try visitor.visitSingularBoolField(value: v, fieldNumber: 8) + }() + case .moduleConfig?: try { + guard case .moduleConfig(let v)? = _storage._payloadVariant else { preconditionFailure() } + try visitor.visitSingularMessageField(value: v, fieldNumber: 9) + }() + case .channel?: try { + guard case .channel(let v)? = _storage._payloadVariant else { preconditionFailure() } + try visitor.visitSingularMessageField(value: v, fieldNumber: 10) + }() + case .queueStatus?: try { + guard case .queueStatus(let v)? = _storage._payloadVariant else { preconditionFailure() } + try visitor.visitSingularMessageField(value: v, fieldNumber: 11) + }() + case .xmodemPacket?: try { + guard case .xmodemPacket(let v)? = _storage._payloadVariant else { preconditionFailure() } + try visitor.visitSingularMessageField(value: v, fieldNumber: 12) + }() + case .metadata?: try { + guard case .metadata(let v)? = _storage._payloadVariant else { preconditionFailure() } + try visitor.visitSingularMessageField(value: v, fieldNumber: 13) + }() + case .mqttClientProxyMessage?: try { + guard case .mqttClientProxyMessage(let v)? = _storage._payloadVariant else { preconditionFailure() } + try visitor.visitSingularMessageField(value: v, fieldNumber: 14) + }() + case nil: break + } } try unknownFields.traverse(visitor: &visitor) } static func ==(lhs: FromRadio, rhs: FromRadio) -> Bool { - if lhs.id != rhs.id {return false} - if lhs.payloadVariant != rhs.payloadVariant {return false} + if lhs._storage !== rhs._storage { + let storagesAreEqual: Bool = withExtendedLifetime((lhs._storage, rhs._storage)) { (_args: (_StorageClass, _StorageClass)) in + let _storage = _args.0 + let rhs_storage = _args.1 + if _storage._id != rhs_storage._id {return false} + if _storage._payloadVariant != rhs_storage._payloadVariant {return false} + return true + } + if !storagesAreEqual {return false} + } if lhs.unknownFields != rhs.unknownFields {return false} return true }