From 110f088971b9eb3db5c88712504eedacd115a23b Mon Sep 17 00:00:00 2001 From: "Hermiteer, LLC" Date: Fri, 21 Jun 2024 14:24:35 -0700 Subject: [PATCH] Added optional metadata string to IRCMessage Changed IRCMessageParser to look for message metadata --- Sources/NIOIRC/IRCDispatcher.swift | 15 +++++--- Sources/NIOIRC/IRCMessageParser.swift | 51 +++++++++++++++++++++++---- Sources/NIOIRC/IRCMessageTarget.swift | 6 ++-- Sources/NIOIRC/Model/IRCMessage.swift | 22 +++++++++--- 4 files changed, 76 insertions(+), 18 deletions(-) diff --git a/Sources/NIOIRC/IRCDispatcher.swift b/Sources/NIOIRC/IRCDispatcher.swift index 6f01464..7070c6d 100644 --- a/Sources/NIOIRC/IRCDispatcher.swift +++ b/Sources/NIOIRC/IRCDispatcher.swift @@ -64,7 +64,8 @@ public protocol IRCDispatcher { message : String) throws func doMessage (sender : IRCUserID?, recipients : [ IRCMessageRecipient ], - message : String) throws + message : String, + metadata : String?) throws func doIsOnline (_ nicks : [ IRCNickName ]) throws func doList (_ channels : [ IRCChannelName ]?, @@ -103,7 +104,9 @@ public extension IRCDispatcher { let sender = message.origin != nil ? IRCUserID(message.origin!) : nil try doMessage(sender: sender, - recipients: recipients, message: payload) + recipients: recipients, + message: payload, + metadata: message.metadata) case .NOTICE(let recipients, let message): try doNotice(recipients: recipients, message: message) @@ -205,8 +208,11 @@ public extension IRCDispatcher { func doNotice(recipients: [ IRCMessageRecipient ], message: String) throws { throw InternalDispatchError.notImplemented(function: #function) } - func doMessage(sender: IRCUserID?, recipients: [ IRCMessageRecipient ], - message: String) throws + + func doMessage(sender: IRCUserID?, + recipients: [ IRCMessageRecipient ], + message: String, + metadata: String) throws { throw InternalDispatchError.notImplemented(function: #function) } @@ -214,6 +220,7 @@ public extension IRCDispatcher { func doIsOnline(_ nicks: [ IRCNickName ]) throws { throw InternalDispatchError.notImplemented(function: #function) } + func doList(_ channels : [ IRCChannelName ]?, _ target: String?) throws { throw InternalDispatchError.notImplemented(function: #function) } diff --git a/Sources/NIOIRC/IRCMessageParser.swift b/Sources/NIOIRC/IRCMessageParser.swift index 7ff575f..79aa733 100644 --- a/Sources/NIOIRC/IRCMessageParser.swift +++ b/Sources/NIOIRC/IRCMessageParser.swift @@ -105,6 +105,7 @@ public struct IRCMessageParser { // [':' SOURCE]? ' ' COMMAND [' ' ARGS]? [' :' LAST-ARG]? let cSpace : UInt8 = 32 let cColon : UInt8 = 58 + let cAt : UInt8 = 64 let c0 : UInt8 = 48 + 0 let c9 : UInt8 = 48 + 9 guard !line.isEmpty else { throw Error.syntaxError } @@ -135,13 +136,37 @@ public struct IRCMessageParser { return String(data: Data(slice), encoding: .utf8) // Sigh, the pain. } + /* parse metadata */ + + let metadataSource : Swift.Slice? + + if cursor[cursor.startIndex] == cAt { + let startIndex = cursor.startIndex.advanced(by: 1) + let spaceIdx = line.firstIndex(of: cSpace) + + guard let endSourceIdx = spaceIdx, endSourceIdx > startIndex else { + throw Error.invalidPrefix(Data(line)) + } + + metadataSource = cursor[startIndex..? - + if cursor[cursor.startIndex] == cColon { +// let spaceIdx = cursor.firstIndex(of: cSpace) let startIndex = cursor.startIndex.advanced(by: 1) - let spaceIdx = line.firstIndex(of: cSpace) +// let spaceIdx = line.firstIndex(of: cSpace) + let spaceIdx = cursor.firstIndex(of: cSpace) guard let endSourceIdx = spaceIdx, endSourceIdx > startIndex else { throw Error.invalidPrefix(Data(line)) @@ -159,7 +184,9 @@ public struct IRCMessageParser { /* parse command name */ - guard !cursor.isEmpty else { throw Error.invalidCommand(Data(line)) } + guard !cursor.isEmpty else { + throw Error.invalidCommand(Data(line)) + } guard isLetter(cursor[cursor.startIndex]) || isDigit(cursor[cursor.startIndex]) else { throw Error.invalidCommand(Data(line)) @@ -239,6 +266,16 @@ public struct IRCMessageParser { /* construct */ + let metadataString: String? + if let metadataSource = metadataSource { + guard let string = makeString(from: metadataSource) else { + throw Error.invalidPrefix(Data(line)) + } + metadataString = string + } else { + metadataString = nil + } + let origin: String? if let source = source { guard let sourceString = makeString(from: source) else { @@ -252,10 +289,12 @@ public struct IRCMessageParser { switch commandKey { case .string(let s): - return IRCMessage(origin: origin, + return IRCMessage(metadata: metadataString, + origin: origin, command: try IRCCommand(s, arguments: args)) case .int(let i): - return IRCMessage(origin: origin, + return IRCMessage(metadata: metadataString, + origin: origin, command: try IRCCommand(i, arguments: args)) } } diff --git a/Sources/NIOIRC/IRCMessageTarget.swift b/Sources/NIOIRC/IRCMessageTarget.swift index 77b4d6f..75f416c 100644 --- a/Sources/NIOIRC/IRCMessageTarget.swift +++ b/Sources/NIOIRC/IRCMessageTarget.swift @@ -52,7 +52,7 @@ public extension IRCMessageTarget { .map { $0.replacingOccurrences(of: "\r", with: "") } let messages = lines.map { - IRCMessage(origin: origin, command: .PRIVMSG(recipients, $0)) + IRCMessage(metadata: nil, origin: origin, command: .PRIVMSG(recipients, $0)) } sendMessages(messages, promise: nil) } @@ -65,14 +65,14 @@ public extension IRCMessageTarget { .map { $0.replacingOccurrences(of: "\r", with: "") } let messages = lines.map { - IRCMessage(origin: origin, command: .NOTICE(recipients, $0)) + IRCMessage(metadata: nil, origin: origin, command: .NOTICE(recipients, $0)) } sendMessages(messages, promise: nil) } @inlinable func sendRawReply(_ code: IRCCommandCode, _ args: String...) { - sendMessage(IRCMessage(origin: origin, command: .numeric(code, args))) + sendMessage(IRCMessage(metadata: nil, origin: origin, command: .numeric(code, args))) } } diff --git a/Sources/NIOIRC/Model/IRCMessage.swift b/Sources/NIOIRC/Model/IRCMessage.swift index c7f7c0e..b9345ba 100644 --- a/Sources/NIOIRC/Model/IRCMessage.swift +++ b/Sources/NIOIRC/Model/IRCMessage.swift @@ -23,16 +23,22 @@ import struct Foundation.Data public struct IRCMessage : Codable, CustomStringConvertible { public enum CodingKeys: String, CodingKey { - case origin, target, command, arguments + case metadata, origin, target, command, arguments } @inlinable - public init(origin: String? = nil, target: String? = nil, + public init(metadata: String? = nil, origin: String? = nil, target: String? = nil, command: IRCCommand) { - self._storage = _Storage(origin: origin, target: target, command: command) + self._storage = _Storage(metadata: metadata, origin: origin, target: target, command: command) } + @inlinable + public var metadata : String? { + set { copyStorageIfNeeded(); _storage.metadata = newValue } + get { return _storage.metadata } + } + /** * True origin of message. Do not set in clients. * @@ -67,6 +73,7 @@ public struct IRCMessage : Codable, CustomStringConvertible { @inlinable public var description: String { var ms = "