diff --git a/Sources/NIOIMAPCore/Grammar/Command/Command.swift b/Sources/NIOIMAPCore/Grammar/Command/Command.swift index 7bd76aabe..138a7e3c9 100644 --- a/Sources/NIOIMAPCore/Grammar/Command/Command.swift +++ b/Sources/NIOIMAPCore/Grammar/Command/Command.swift @@ -473,12 +473,17 @@ extension CommandEncodeBuffer { } private mutating func writeCommandKind_uidBatches(batchSize: Int, batchRange: ClosedRange?) -> Int { - self.buffer.writeString("UIDBATCHES \(batchSize)") + self.buffer.writeIfExists(batchRange) { - let range = UnknownMessageIdentifier(exactly: $0.lowerBound)!...UnknownMessageIdentifier(exactly: $0.upperBound)! - return self.buffer - .writeString(" ") + self.buffer - .writeMessageIdentifierRange(range) - } + self.buffer.writeString("UIDBATCHES \(batchSize)") + + self.buffer.writeIfExists(batchRange) { + let range = + UnknownMessageIdentifier(exactly: $0.lowerBound)!...UnknownMessageIdentifier( + exactly: $0.upperBound + )! + return self.buffer + .writeString(" ") + + self.buffer + .writeMessageIdentifierRange(range) + } } private mutating func writeCommandKind_custom(name: String, payloads: [Command.CustomCommandPayload]) -> Int { diff --git a/Sources/NIOIMAPCore/Grammar/Response/UIDBatchesResponse.swift b/Sources/NIOIMAPCore/Grammar/Response/UIDBatchesResponse.swift index 30dd7ba6f..8bae00cc2 100644 --- a/Sources/NIOIMAPCore/Grammar/Response/UIDBatchesResponse.swift +++ b/Sources/NIOIMAPCore/Grammar/Response/UIDBatchesResponse.swift @@ -36,11 +36,11 @@ public struct UIDBatchesResponse: Hashable, Sendable { extension EncodeBuffer { @discardableResult mutating func writeUIDBatchesResponse(_ response: UIDBatchesResponse) -> Int { self.writeString(#"UIDBATCHES (TAG "\#(response.correlator)")"#) - + self.write(if: !response.batches.isEmpty) { - self.writeString(" ") + - self.writeArray(response.batches, separator: ",", parenthesis: false) { range, buffer -> Int in - buffer.writeMessageIdentifierRange(range, descending: true) + + self.write(if: !response.batches.isEmpty) { + self.writeString(" ") + + self.writeArray(response.batches, separator: ",", parenthesis: false) { range, buffer -> Int in + buffer.writeMessageIdentifierRange(range, descending: true) + } } - } } } diff --git a/Sources/NIOIMAPCore/Grammar/UID/MessageIdentifierRange.swift b/Sources/NIOIMAPCore/Grammar/UID/MessageIdentifierRange.swift index 247661ec6..93326909e 100644 --- a/Sources/NIOIMAPCore/Grammar/UID/MessageIdentifierRange.swift +++ b/Sources/NIOIMAPCore/Grammar/UID/MessageIdentifierRange.swift @@ -166,12 +166,15 @@ extension MessageIdentifierRange { // MARK: - Encoding extension EncodeBuffer { - @discardableResult mutating func writeMessageIdentifierRange(_ range: MessageIdentifierRange, descending: Bool = false) -> Int { + @discardableResult mutating func writeMessageIdentifierRange( + _ range: MessageIdentifierRange, + descending: Bool = false + ) -> Int { let a = descending ? range.range.upperBound : range.range.lowerBound let b = descending ? range.range.lowerBound : range.range.upperBound return self.writeMessageIdentifier(a) - + self.write(if: range.range.lowerBound < range.range.upperBound) { - self.writeString(":") + self.writeMessageIdentifier(b) - } + + self.write(if: range.range.lowerBound < range.range.upperBound) { + self.writeString(":") + self.writeMessageIdentifier(b) + } } } diff --git a/Sources/NIOIMAPCore/Parser/Grammar/GrammarParser+Mailbox.swift b/Sources/NIOIMAPCore/Parser/Grammar/GrammarParser+Mailbox.swift index 457a7033e..e20fb7714 100644 --- a/Sources/NIOIMAPCore/Parser/Grammar/GrammarParser+Mailbox.swift +++ b/Sources/NIOIMAPCore/Parser/Grammar/GrammarParser+Mailbox.swift @@ -52,13 +52,16 @@ extension GrammarParser { return .lsub(try self.parseMailboxList(buffer: &buffer, tracker: tracker)) } - func parseMailboxData_extendedSearch(buffer: inout ParseBuffer, tracker: StackTracker) throws -> MailboxData { + func parseMailboxData_extendedSearch(buffer: inout ParseBuffer, tracker: StackTracker) throws -> MailboxData + { let response = try self.parseExtendedSearchResponse(buffer: &buffer, tracker: tracker) return .extendedSearch(response) } - - func parseMailboxData_search_combined(buffer: inout ParseBuffer, tracker: StackTracker) throws -> MailboxData { + func parseMailboxData_search_combined( + buffer: inout ParseBuffer, + tracker: StackTracker + ) throws -> MailboxData { func parseMailboxData_search(buffer: inout ParseBuffer, tracker: StackTracker) throws -> MailboxData { let nums = try PL.parseZeroOrMore(buffer: &buffer, tracker: tracker) { (buffer, tracker) -> UnknownMessageIdentifier in @@ -72,7 +75,8 @@ extension GrammarParser { return .search(nums) } - func parseMailboxData_searchSort(buffer: inout ParseBuffer, tracker: StackTracker) throws -> MailboxData { + func parseMailboxData_searchSort(buffer: inout ParseBuffer, tracker: StackTracker) throws -> MailboxData + { try PL.parseSpaces(buffer: &buffer, tracker: tracker) var array = [try self.parseNZNumber(buffer: &buffer, tracker: tracker)] try PL.parseZeroOrMore( @@ -111,7 +115,10 @@ extension GrammarParser { .namespace(try self.parseNamespaceResponse(buffer: &buffer, tracker: tracker)) } - func parseMailboxData_uidBatchesResponse(buffer: inout ParseBuffer, tracker: StackTracker) throws -> MailboxData { + func parseMailboxData_uidBatchesResponse( + buffer: inout ParseBuffer, + tracker: StackTracker + ) throws -> MailboxData { .uidBatches(try self.parseUIDBatchesResponse(buffer: &buffer, tracker: tracker)) } diff --git a/Sources/NIOIMAPCore/Parser/Grammar/GrammarParser.swift b/Sources/NIOIMAPCore/Parser/Grammar/GrammarParser.swift index 520bd9cab..f5aa7b294 100644 --- a/Sources/NIOIMAPCore/Parser/Grammar/GrammarParser.swift +++ b/Sources/NIOIMAPCore/Parser/Grammar/GrammarParser.swift @@ -1841,10 +1841,11 @@ extension GrammarParser { try PL.parseFixedString(#"(TAG ""#, buffer: &buffer, tracker: tracker) let tag = try self.parseTag(buffer: &buffer, tracker: tracker) try PL.parseFixedString("\")", buffer: &buffer, tracker: tracker) - let batches = try PL.parseOptional(buffer: &buffer, tracker: tracker) { buffer, tracker -> [UIDRange] in - try PL.parseSpaces(buffer: &buffer, tracker: tracker) - return try parseUIDRangeArray(buffer: &buffer, tracker: tracker) - } ?? [] + let batches = + try PL.parseOptional(buffer: &buffer, tracker: tracker) { buffer, tracker -> [UIDRange] in + try PL.parseSpaces(buffer: &buffer, tracker: tracker) + return try parseUIDRangeArray(buffer: &buffer, tracker: tracker) + } ?? [] return UIDBatchesResponse(correlator: tag, batches: batches) } } diff --git a/Tests/NIOIMAPCoreTests/Grammar/CommandType/CommandType+Tests.swift b/Tests/NIOIMAPCoreTests/Grammar/CommandType/CommandType+Tests.swift index e09a4375b..368b0711c 100644 --- a/Tests/NIOIMAPCoreTests/Grammar/CommandType/CommandType+Tests.swift +++ b/Tests/NIOIMAPCoreTests/Grammar/CommandType/CommandType+Tests.swift @@ -123,7 +123,10 @@ extension CommandType_Tests { ), (.compress(.deflate), CommandEncodingOptions(), ["COMPRESS DEFLATE"], #line), (.uidBatches(batchSize: 2_000), CommandEncodingOptions(), ["UIDBATCHES 2000"], #line), - (.uidBatches(batchSize: 1_000, batchRange: 10...20), CommandEncodingOptions(), ["UIDBATCHES 1000 10:20"], #line), + ( + .uidBatches(batchSize: 1_000, batchRange: 10...20), CommandEncodingOptions(), ["UIDBATCHES 1000 10:20"], + #line + ), // Custom diff --git a/Tests/NIOIMAPCoreTests/Grammar/Mailbox/MailboxData+Tests.swift b/Tests/NIOIMAPCoreTests/Grammar/Mailbox/MailboxData+Tests.swift index 9ffc77805..028c8725f 100644 --- a/Tests/NIOIMAPCoreTests/Grammar/Mailbox/MailboxData+Tests.swift +++ b/Tests/NIOIMAPCoreTests/Grammar/Mailbox/MailboxData+Tests.swift @@ -61,12 +61,17 @@ extension MailboxDataTests { (.search([1, 2, 3, 4, 5]), "SEARCH 1 2 3 4 5", #line), (.search([20, 23], ModificationSequenceValue(917_162_500)), "SEARCH 20 23 (MODSEQ 917162500)", #line), ( - .uidBatches(UIDBatchesResponse(correlator: "A143", batches: [ - 99_695...215_295, - 20_350...99_696, - 7_829...20_351, - 1...7830, - ])), + .uidBatches( + UIDBatchesResponse( + correlator: "A143", + batches: [ + 99_695...215_295, + 20_350...99_696, + 7_829...20_351, + 1...7830, + ] + ) + ), #"UIDBATCHES (TAG "A143") 215295:99695,99696:20350,20351:7829,7830:1"#, #line ), ( diff --git a/Tests/NIOIMAPCoreTests/Parser/Grammar/GrammarParser+Mailbox+Tests.swift b/Tests/NIOIMAPCoreTests/Parser/Grammar/GrammarParser+Mailbox+Tests.swift index eff8685ff..86ae7ef5b 100644 --- a/Tests/NIOIMAPCoreTests/Parser/Grammar/GrammarParser+Mailbox+Tests.swift +++ b/Tests/NIOIMAPCoreTests/Parser/Grammar/GrammarParser+Mailbox+Tests.swift @@ -40,11 +40,13 @@ extension GrammarParser_Mailbox_Tests { ), ( #"LSUB () "." #news.comp.mail.misc"#, "\r\n", - .lsub(MailboxInfo( - attributes: [], - path: try! .init(name: MailboxName("#news.comp.mail.misc"), pathSeparator: "."), - extensions: [:] - )), + .lsub( + MailboxInfo( + attributes: [], + path: try! .init(name: MailboxName("#news.comp.mail.misc"), pathSeparator: "."), + extensions: [:] + ) + ), #line ), ( @@ -52,7 +54,10 @@ extension GrammarParser_Mailbox_Tests { .extendedSearch(.init(correlator: nil, kind: .sequenceNumber, returnData: [.min(1), .max(2)])), #line ), - ("ESEARCH", "\r", .extendedSearch(.init(correlator: nil, kind: .sequenceNumber, returnData: [])), #line), + ( + "ESEARCH", "\r", .extendedSearch(.init(correlator: nil, kind: .sequenceNumber, returnData: [])), + #line + ), ("1234 EXISTS", "\r\n", .exists(1234), #line), ("5678 RECENT", "\r\n", .recent(5678), #line), ("STATUS INBOX ()", "\r\n", .status(.inbox, .init()), #line), @@ -83,7 +88,8 @@ extension GrammarParser_Mailbox_Tests { ( "SEARCH 1 (MODSEQ 2)", "\r\n", .searchSort(.init(identifiers: [1], modificationSequence: 2)), - #line), + #line + ), ( "NAMESPACE NIL NIL NIL", "\r\n", .namespace(.init(userNamespace: [], otherUserNamespace: [], sharedNamespace: [])), diff --git a/Tests/NIOIMAPCoreTests/Parser/IMAPParserTests.swift b/Tests/NIOIMAPCoreTests/Parser/IMAPParserTests.swift index ba8b45d2d..bc9d2bfee 100644 --- a/Tests/NIOIMAPCoreTests/Parser/IMAPParserTests.swift +++ b/Tests/NIOIMAPCoreTests/Parser/IMAPParserTests.swift @@ -1483,9 +1483,15 @@ extension ParserUnitTests { self.iterateTests( testFunction: GrammarParser().parseUIDBatchesResponse, validInputs: [ - (#" (TAG "A143") 215295:99695,99696:20350,20351:7829,7830:1"#, "\r", .init(correlator: "A143", batches: [ - 99695...215295, 20350...99696, 7829...20351, 1...7830, - ]), #line), + ( + #" (TAG "A143") 215295:99695,99696:20350,20351:7829,7830:1"#, "\r", + .init( + correlator: "A143", + batches: [ + 99695...215295, 20350...99696, 7829...20351, 1...7830, + ] + ), #line + ), (#" (TAG "A143")"#, "\r", .init(correlator: "A143", batches: []), #line), (#" (TAG "A143") 99695"#, "\r", .init(correlator: "A143", batches: [99695...99695]), #line), (#" (TAG "A143") 20350:20350"#, "\r", .init(correlator: "A143", batches: [20350...20350]), #line),