Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Parser cleanup (implement shortcut methods, use new parse oneOf) #509

Merged
merged 10 commits into from
Mar 31, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 7 additions & 7 deletions Sources/NIOIMAPCore/Parser/CommandParser.swift
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ public struct CommandParser: Parser {
}

private mutating func parseCommandStream0(buffer: inout ParseBuffer, tracker: StackTracker) throws -> CommandStream? {
try ParserLibrary.composite(buffer: &buffer, tracker: tracker) { buffer, tracker in
try PL.composite(buffer: &buffer, tracker: tracker) { buffer, tracker in
switch self.mode {
case .idle:
return try self.handleIdle(buffer: &buffer, tracker: tracker)
Expand All @@ -139,7 +139,7 @@ public struct CommandParser: Parser {

private mutating func handleStreamingBytes(buffer: inout ParseBuffer, tracker: StackTracker, remaining: Int) throws -> CommandStream {
assert(self.mode.isStreamingAppend)
let bytes = try ParserLibrary.parseBytes(buffer: &buffer, tracker: tracker, upTo: remaining)
let bytes = try PL.parseBytes(buffer: &buffer, tracker: tracker, upTo: remaining)

assert(bytes.readableBytes <= remaining)
if bytes.readableBytes == remaining {
Expand All @@ -153,7 +153,7 @@ public struct CommandParser: Parser {
private mutating func handleLines(buffer: inout ParseBuffer, tracker: StackTracker) throws -> CommandStream {
func parseCommand(buffer: inout ParseBuffer, tracker: StackTracker) throws -> CommandStream {
let command = try GrammarParser.parseTaggedCommand(buffer: &buffer, tracker: tracker)
try ParserLibrary.newline(buffer: &buffer, tracker: tracker)
try PL.parseNewline(buffer: &buffer, tracker: tracker)
if case .idleStart = command.command {
self.mode = .idle
}
Expand All @@ -168,11 +168,11 @@ public struct CommandParser: Parser {

func parseAuthenticationChallengeResponse(buffer: inout ParseBuffer, tracker: StackTracker) throws -> CommandStream {
let authenticationChallengeResponse = try GrammarParser.parseBase64(buffer: &buffer, tracker: tracker)
try ParserLibrary.newline(buffer: &buffer, tracker: tracker)
try PL.parseNewline(buffer: &buffer, tracker: tracker)
return .continuationResponse(authenticationChallengeResponse)
}

return try ParserLibrary.oneOf3(
return try PL.parseOneOf(
parseCommand,
parseAppend,
parseAuthenticationChallengeResponse,
Expand All @@ -195,7 +195,7 @@ public struct CommandParser: Parser {
} catch is ParserError {
let save = buffer
do {
try ParserLibrary.newline(buffer: &buffer, tracker: tracker)
try PL.parseNewline(buffer: &buffer, tracker: tracker)
self.mode = .lines
return .append(.finish)
} catch {
Expand Down Expand Up @@ -232,7 +232,7 @@ public struct CommandParser: Parser {
}

private mutating func handleStreamingCatenateBytes(buffer: inout ParseBuffer, tracker: StackTracker, remaining: Int) throws -> CommandStream {
let bytes = try ParserLibrary.parseBytes(buffer: &buffer, tracker: tracker, upTo: remaining)
let bytes = try PL.parseBytes(buffer: &buffer, tracker: tracker, upTo: remaining)

assert(bytes.readableBytes <= remaining)
if bytes.readableBytes == remaining {
Expand Down
74 changes: 39 additions & 35 deletions Sources/NIOIMAPCore/Parser/Grammar/GrammarParser+Append.swift
Original file line number Diff line number Diff line change
Expand Up @@ -26,47 +26,47 @@ import struct NIO.ByteBufferView
extension GrammarParser {
// append = "APPEND" SP mailbox 1*append-message
static func parseAppend(buffer: inout ParseBuffer, tracker: StackTracker) throws -> CommandStream {
try ParserLibrary.composite(buffer: &buffer, tracker: tracker) { buffer, tracker -> CommandStream in
try PL.composite(buffer: &buffer, tracker: tracker) { buffer, tracker -> CommandStream in
let tag = try self.parseTag(buffer: &buffer, tracker: tracker)
try ParserLibrary.fixedString(" APPEND ", buffer: &buffer, tracker: tracker)
try PL.parseFixedString(" APPEND ", buffer: &buffer, tracker: tracker)
let mailbox = try self.parseMailbox(buffer: &buffer, tracker: tracker)
return .append(.start(tag: tag, appendingTo: mailbox))
}
}

// append-data = literal / literal8 / append-data-ext
static func parseAppendData(buffer: inout ParseBuffer, tracker: StackTracker) throws -> AppendData {
try ParserLibrary.composite(buffer: &buffer, tracker: tracker) { buffer, tracker -> AppendData in
let withoutContentTransferEncoding = try ParserLibrary.optional(buffer: &buffer, tracker: tracker) { (buffer, tracker) in
try ParserLibrary.fixedString("~", buffer: &buffer, tracker: tracker)
try PL.composite(buffer: &buffer, tracker: tracker) { buffer, tracker -> AppendData in
let withoutContentTransferEncoding = try PL.parseOptional(buffer: &buffer, tracker: tracker) { (buffer, tracker) in
try PL.parseFixedString("~", buffer: &buffer, tracker: tracker)
}.map { () in true } ?? false
try ParserLibrary.fixedString("{", buffer: &buffer, tracker: tracker)
try PL.parseFixedString("{", buffer: &buffer, tracker: tracker)
let length = try Self.parseNumber(buffer: &buffer, tracker: tracker)
_ = try ParserLibrary.optional(buffer: &buffer, tracker: tracker) { (buffer, tracker) in
try ParserLibrary.fixedString("+", buffer: &buffer, tracker: tracker)
_ = try PL.parseOptional(buffer: &buffer, tracker: tracker) { (buffer, tracker) in
try PL.parseFixedString("+", buffer: &buffer, tracker: tracker)
}.map { () in false } ?? true
try ParserLibrary.fixedString("}", buffer: &buffer, tracker: tracker)
try ParserLibrary.newline(buffer: &buffer, tracker: tracker)
try PL.parseFixedString("}", buffer: &buffer, tracker: tracker)
try PL.parseNewline(buffer: &buffer, tracker: tracker)
return .init(byteCount: length, withoutContentTransferEncoding: withoutContentTransferEncoding)
}
}

// append-message = appents-opts SP append-data
static func parseAppendMessage(buffer: inout ParseBuffer, tracker: StackTracker) throws -> AppendMessage {
try ParserLibrary.composite(buffer: &buffer, tracker: tracker) { (buffer, tracker) -> AppendMessage in
try PL.composite(buffer: &buffer, tracker: tracker) { (buffer, tracker) -> AppendMessage in
let options = try self.parseAppendOptions(buffer: &buffer, tracker: tracker)
try ParserLibrary.parseSpaces(buffer: &buffer, tracker: tracker)
try PL.parseSpaces(buffer: &buffer, tracker: tracker)
let data = try self.parseAppendData(buffer: &buffer, tracker: tracker)
return .init(options: options, data: data)
}
}

// Like appendMessage, but with CATENATE at the start instead of regular append data.
static func parseCatenateMessage(buffer: inout ParseBuffer, tracker: StackTracker) throws -> AppendOptions {
try ParserLibrary.composite(buffer: &buffer, tracker: tracker) { (buffer, tracker) -> AppendOptions in
try PL.composite(buffer: &buffer, tracker: tracker) { (buffer, tracker) -> AppendOptions in
let options = try self.parseAppendOptions(buffer: &buffer, tracker: tracker)
try ParserLibrary.parseSpaces(buffer: &buffer, tracker: tracker)
try ParserLibrary.fixedString("CATENATE (", buffer: &buffer, tracker: tracker)
try PL.parseSpaces(buffer: &buffer, tracker: tracker)
try PL.parseFixedString("CATENATE (", buffer: &buffer, tracker: tracker)
return options
}
}
Expand All @@ -85,26 +85,28 @@ extension GrammarParser {
try .catenate(self.parseCatenateMessage(buffer: &buffer, tracker: tracker))
}

return try ParserLibrary.oneOf([
return try PL.parseOneOf(
parseCatenate,
parseAppend,
], buffer: &buffer, tracker: tracker)
buffer: &buffer,
tracker: tracker
)
}

// append-options = [SP flag-list] [SP date-time] *(SP append-ext)
static func parseAppendOptions(buffer: inout ParseBuffer, tracker: StackTracker) throws -> AppendOptions {
try ParserLibrary.composite(buffer: &buffer, tracker: tracker) { (buffer, tracker) in
let flagList = try ParserLibrary.optional(buffer: &buffer, tracker: tracker) { (buffer, tracker) -> [Flag] in
try ParserLibrary.parseSpaces(buffer: &buffer, tracker: tracker)
try PL.composite(buffer: &buffer, tracker: tracker) { (buffer, tracker) in
let flagList = try PL.parseOptional(buffer: &buffer, tracker: tracker) { (buffer, tracker) -> [Flag] in
try PL.parseSpaces(buffer: &buffer, tracker: tracker)
return try self.parseFlagList(buffer: &buffer, tracker: tracker)
} ?? []
let internalDate = try ParserLibrary.optional(buffer: &buffer, tracker: tracker) { (buffer, tracker) -> InternalDate in
try ParserLibrary.parseSpaces(buffer: &buffer, tracker: tracker)
let internalDate = try PL.parseOptional(buffer: &buffer, tracker: tracker) { (buffer, tracker) -> InternalDate in
try PL.parseSpaces(buffer: &buffer, tracker: tracker)
return try self.parseInternalDate(buffer: &buffer, tracker: tracker)
}
var kvs = KeyValues<String, ParameterValue>()
try ParserLibrary.parseZeroOrMore(buffer: &buffer, into: &kvs, tracker: tracker) { (buffer, tracker) -> KeyValue<String, ParameterValue> in
try ParserLibrary.parseSpaces(buffer: &buffer, tracker: tracker)
try PL.parseZeroOrMore(buffer: &buffer, into: &kvs, tracker: tracker) { (buffer, tracker) -> KeyValue<String, ParameterValue> in
try PL.parseSpaces(buffer: &buffer, tracker: tracker)
return try self.parseTaggedExtension(buffer: &buffer, tracker: tracker)
}
return .init(flagList: flagList, internalDate: internalDate, extensions: kvs)
Expand All @@ -120,36 +122,38 @@ extension GrammarParser {
static func parseCatenatePart(expectPrecedingSpace: Bool, buffer: inout ParseBuffer, tracker: StackTracker) throws -> CatenatePart {
func parseCatenateURL(buffer: inout ParseBuffer, tracker: StackTracker) throws -> CatenatePart {
if expectPrecedingSpace {
try ParserLibrary.parseSpaces(buffer: &buffer, tracker: tracker)
try PL.parseSpaces(buffer: &buffer, tracker: tracker)
}
try ParserLibrary.fixedString("URL ", buffer: &buffer, tracker: tracker)
try PL.parseFixedString("URL ", buffer: &buffer, tracker: tracker)
let url = try self.parseAString(buffer: &buffer, tracker: tracker)
return .url(url)
}

func parseCatenateText(buffer: inout ParseBuffer, tracker: StackTracker) throws -> CatenatePart {
if expectPrecedingSpace {
try ParserLibrary.parseSpaces(buffer: &buffer, tracker: tracker)
try PL.parseSpaces(buffer: &buffer, tracker: tracker)
}
try ParserLibrary.fixedString("TEXT {", buffer: &buffer, tracker: tracker)
try PL.parseFixedString("TEXT {", buffer: &buffer, tracker: tracker)
let length = try Self.parseNumber(buffer: &buffer, tracker: tracker)
_ = try ParserLibrary.optional(buffer: &buffer, tracker: tracker) { (buffer, tracker) in
try ParserLibrary.fixedString("+", buffer: &buffer, tracker: tracker)
_ = try PL.parseOptional(buffer: &buffer, tracker: tracker) { (buffer, tracker) in
try PL.parseFixedString("+", buffer: &buffer, tracker: tracker)
}.map { () in false } ?? true
try ParserLibrary.fixedString("}", buffer: &buffer, tracker: tracker)
try ParserLibrary.newline(buffer: &buffer, tracker: tracker)
try PL.parseFixedString("}", buffer: &buffer, tracker: tracker)
try PL.parseNewline(buffer: &buffer, tracker: tracker)
return .text(length)
}

func parseCatenateEnd(buffer: inout ParseBuffer, tracker: StackTracker) throws -> CatenatePart {
try ParserLibrary.fixedString(")", buffer: &buffer, tracker: tracker)
try PL.parseFixedString(")", buffer: &buffer, tracker: tracker)
return .end
}

return try ParserLibrary.oneOf([
return try PL.parseOneOf(
parseCatenateURL,
parseCatenateText,
parseCatenateEnd,
], buffer: &buffer, tracker: tracker)
buffer: &buffer,
tracker: tracker
)
}
}
Loading