diff options
| author | Ruben Beltran del Rio <jj@r.bdr.sh> | 2025-12-14 16:52:57 +0100 |
|---|---|---|
| committer | Ruben Beltran del Rio <jj@r.bdr.sh> | 2025-12-14 17:05:21 +0100 |
| commit | d56e777025f3bda29feaec22c125b0e7ab975e0c (patch) | |
| tree | 19295b051c9e32c17e32a4954fc0cdca3d4e0be5 | |
| parent | 0b90075f76b6f2df77c01c303322323b1395641a (diff) | |
Format, make map equatable
24 files changed, 604 insertions, 562 deletions
@@ -22,6 +22,7 @@ benchmark: swift package benchmark --target ParseBenchmarkTarget format: + swift-format --in-place --recursive Sources Tests swiftlint --fix Sources Tests lint: diff --git a/Sources/WmapParser/ComponentParser.swift b/Sources/WmapParser/ComponentParser.swift index 66979eb..79f5493 100644 --- a/Sources/WmapParser/ComponentParser.swift +++ b/Sources/WmapParser/ComponentParser.swift @@ -1,81 +1,83 @@ extension WmapParser { - /// Parses a component with its coordinates. - static func parseComponent<T: Collection>(_ bytes: T, _ start: Int, _ end: Int) -> Component? - where T.Element == UInt8, T.Index == Int { - guard let (label, parenthesisIndex) = extractComponentLabel(bytes, start, end) else { - return nil - } + /// Parses a component with its coordinates. + static func parseComponent<T: Collection>(_ bytes: T, _ start: Int, _ end: Int) -> Component? + where T.Element == UInt8, T.Index == Int { + guard let (label, parenthesisIndex) = extractComponentLabel(bytes, start, end) else { + return nil + } - guard - let (coordinates, endIndex) = parseCoordinates( - bytes, parenthesisIndex + 1, end) - else { - return nil - } + guard + let (coordinates, endIndex) = parseCoordinates( + bytes, parenthesisIndex + 1, end) + else { + return nil + } - let shape = extractComponentShape(bytes, endIndex, end) + let shape = extractComponentShape(bytes, endIndex, end) - return Component(label: label, coordinates: coordinates, shape: shape) - } + return Component(label: label, coordinates: coordinates, shape: shape) + } - /// Looks for a component label by taking the string before the first open - /// parenthesis. - @inline(__always) - private static func extractComponentLabel<T: Collection>(_ bytes: T, _ start: Int, _ end: Int) -> ( + /// Looks for a component label by taking the string before the first open + /// parenthesis. + @inline(__always) + private static func extractComponentLabel<T: Collection>(_ bytes: T, _ start: Int, _ end: Int) + -> ( String, Int )? - where T.Element == UInt8, T.Index == Int { - var index = start - while index < end { - if bytes[index] == kOpenParenthesis { - guard index > start else { return nil } - guard let label = extractTrimmedString(bytes, start, index) else { return nil } - return (label, index) - } - index += 1 + where T.Element == UInt8, T.Index == Int { + var index = start + while index < end { + if bytes[index] == kOpenParenthesis { + guard index > start else { return nil } + guard let label = extractTrimmedString(bytes, start, index) else { return nil } + return (label, index) } - return nil + index += 1 } + return nil + } - /// Extracts a shape by looking for a shape label in square brackets. - /// If missing, incomplete or invalid, it returns a circle - @inline(__always) - private static func extractComponentShape<T: Collection>(_ bytes: T, _ start: Int, _ end: Int) -> Shape - where T.Element == UInt8, T.Index == Int { - var index = skipWhitespace(bytes, end, start) + /// Extracts a shape by looking for a shape label in square brackets. + /// If missing, incomplete or invalid, it returns a circle + @inline(__always) + private static func extractComponentShape<T: Collection>(_ bytes: T, _ start: Int, _ end: Int) + -> Shape + where T.Element == UInt8, T.Index == Int { + var index = skipWhitespace(bytes, end, start) - guard index < end && bytes[index] == kOpenSquareBracket else { return .circle } + guard index < end && bytes[index] == kOpenSquareBracket else { return .circle } - index += 1 - let shapeStart = index - while index < end && bytes[index] != kCloseSquareBracket { index += 1 } + index += 1 + let shapeStart = index + while index < end && bytes[index] != kCloseSquareBracket { index += 1 } - guard index > shapeStart && index < end else { return .circle } + guard index > shapeStart && index < end else { return .circle } - let shapeName = bytes[shapeStart..<index] - return parseShapeFromBytes(shapeName) - } + let shapeName = bytes[shapeStart..<index] + return parseShapeFromBytes(shapeName) + } - /// Given the contents of a shape label, return the right type. - @inline(__always) - private static func parseShapeFromBytes<T: Collection>(_ shapeName: T) -> Shape - where T.Element == UInt8, T.Index == Int { - var trimStart = shapeName.startIndex - var trimEnd = shapeName.endIndex + /// Given the contents of a shape label, return the right type. + @inline(__always) + private static func parseShapeFromBytes<T: Collection>(_ shapeName: T) -> Shape + where T.Element == UInt8, T.Index == Int { + var trimStart = shapeName.startIndex + var trimEnd = shapeName.endIndex - trimStart = skipWhitespace(shapeName, trimEnd, trimStart) - trimEnd = shaveWhitespace(shapeName, trimStart, trimEnd) + trimStart = skipWhitespace(shapeName, trimEnd, trimStart) + trimEnd = shaveWhitespace(shapeName, trimStart, trimEnd) - let trimmedName = shapeName[trimStart..<trimEnd] + let trimmedName = shapeName[trimStart..<trimEnd] - // "x" - if matchesKeyword(trimmedName, [120]) { return .xMark } - // "square" - if matchesKeyword(trimmedName, [115, 113, 117, 97, 114, 101]) { return .square } - // "triangle" - if matchesKeyword(trimmedName, [116, 114, 105, 97, 110, 103, 108, 101]) { return .triangle } + // "x" + if matchesKeyword(trimmedName, [120]) { return .xMark } + // "square" + if matchesKeyword(trimmedName, [115, 113, 117, 97, 114, 101]) { return .square } + // "triangle" + if matchesKeyword(trimmedName, [116, 114, 105, 97, 110, 103, 108, 101]) { return .triangle } - return .circle - } + return .circle + } } diff --git a/Sources/WmapParser/Constants.swift b/Sources/WmapParser/Constants.swift index e659c03..8646243 100644 --- a/Sources/WmapParser/Constants.swift +++ b/Sources/WmapParser/Constants.swift @@ -1,37 +1,37 @@ extension WmapParser { - // Whitespace - static let kNewline = 10 - static let kCarriageReturn = 13 - static let kTab = 9 - static let kSpace = 32 + // Whitespace + static let kNewline = 10 + static let kCarriageReturn = 13 + static let kTab = 9 + static let kSpace = 32 - // Punctuation - static let kOpenParenthesis = 40 - static let kCloseParenthesis = 41 - static let kPlus = 43 - static let kComma = 44 - static let kDash = 45 - static let kPeriod = 46 - static let kGreaterThan = 62 - static let kOpenSquareBracket = 91 - static let kCloseSquareBracket = 93 + // Punctuation + static let kOpenParenthesis = 40 + static let kCloseParenthesis = 41 + static let kPlus = 43 + static let kComma = 44 + static let kDash = 45 + static let kPeriod = 46 + static let kGreaterThan = 62 + static let kOpenSquareBracket = 91 + static let kCloseSquareBracket = 93 - // Letters - static let kCapitalA = 65 - static let kCapitalZ = 90 - static let kCapsToLowercaseDistance: UInt8 = 32 + // Letters + static let kCapitalA = 65 + static let kCapitalZ = 90 + static let kCapsToLowercaseDistance: UInt8 = 32 - // Numbers - static let kZero = 48 - static let kNine = 57 + // Numbers + static let kZero = 48 + static let kNine = 57 - // Keywords. ASCII representations of the keywords. - static let kInertiaKeyword: [UInt8] = [105, 110, 101, 114, 116, 105, 97] - static let kEvolutionKeyword: [UInt8] = [101, 118, 111, 108, 117, 116, 105, 111, 110] - static let kNoteKeyword: [UInt8] = [110, 111, 116, 101] - static let kGroupKeyword: [UInt8] = [103, 114, 111, 117, 112] - static let kIKeyword: [UInt8] = [105] - static let kIIKeyword: [UInt8] = [105, 105] - static let kIIIKeyword: [UInt8] = [105, 105, 105] - static let kIVKeyword: [UInt8] = [105, 118] + // Keywords. ASCII representations of the keywords. + static let kInertiaKeyword: [UInt8] = [105, 110, 101, 114, 116, 105, 97] + static let kEvolutionKeyword: [UInt8] = [101, 118, 111, 108, 117, 116, 105, 111, 110] + static let kNoteKeyword: [UInt8] = [110, 111, 116, 101] + static let kGroupKeyword: [UInt8] = [103, 114, 111, 117, 112] + static let kIKeyword: [UInt8] = [105] + static let kIIKeyword: [UInt8] = [105, 105] + static let kIIIKeyword: [UInt8] = [105, 105, 105] + static let kIVKeyword: [UInt8] = [105, 118] } diff --git a/Sources/WmapParser/DataStructures/Component.swift b/Sources/WmapParser/DataStructures/Component.swift index 5ef2716..48dac78 100644 --- a/Sources/WmapParser/DataStructures/Component.swift +++ b/Sources/WmapParser/DataStructures/Component.swift @@ -1,8 +1,8 @@ extension WmapParser { - /// A component in the map. - public struct Component: Sendable, Equatable { - public let label: String - public let coordinates: MapPoint - public let shape: Shape - } + /// A component in the map. + public struct Component: Sendable, Equatable { + public let label: String + public let coordinates: MapPoint + public let shape: Shape + } } diff --git a/Sources/WmapParser/DataStructures/Dependency.swift b/Sources/WmapParser/DataStructures/Dependency.swift index 5f0089c..c2f4163 100644 --- a/Sources/WmapParser/DataStructures/Dependency.swift +++ b/Sources/WmapParser/DataStructures/Dependency.swift @@ -1,8 +1,8 @@ extension WmapParser { -/// A dependency between two components. -public struct Dependency: Sendable, Equatable { - public let fromComponent: String - public let toComponent: String - public let isDirected: Bool -} + /// A dependency between two components. + public struct Dependency: Sendable, Equatable { + public let fromComponent: String + public let toComponent: String + public let isDirected: Bool + } } diff --git a/Sources/WmapParser/DataStructures/Evolution.swift b/Sources/WmapParser/DataStructures/Evolution.swift index 07fbf2a..d5b0ee3 100644 --- a/Sources/WmapParser/DataStructures/Evolution.swift +++ b/Sources/WmapParser/DataStructures/Evolution.swift @@ -1,7 +1,7 @@ extension WmapParser { -/// Evolution associated with a component. -public struct Evolution: Sendable, Equatable { - public let component: String - public let value: Double -} + /// Evolution associated with a component. + public struct Evolution: Sendable, Equatable { + public let component: String + public let value: Double + } } diff --git a/Sources/WmapParser/DataStructures/Group.swift b/Sources/WmapParser/DataStructures/Group.swift index 5dabc11..9a18d92 100644 --- a/Sources/WmapParser/DataStructures/Group.swift +++ b/Sources/WmapParser/DataStructures/Group.swift @@ -1,6 +1,6 @@ extension WmapParser { - /// A group of components. - public struct Group: Sendable, Equatable { - public let components: [String] - } + /// A group of components. + public struct Group: Sendable, Equatable { + public let components: [String] + } } diff --git a/Sources/WmapParser/DataStructures/Inertia.swift b/Sources/WmapParser/DataStructures/Inertia.swift index 146ad70..30cace2 100644 --- a/Sources/WmapParser/DataStructures/Inertia.swift +++ b/Sources/WmapParser/DataStructures/Inertia.swift @@ -1,6 +1,6 @@ extension WmapParser { - /// Inertia associated with a component. - public struct Inertia: Sendable, Equatable { - public let component: String - } + /// Inertia associated with a component. + public struct Inertia: Sendable, Equatable { + public let component: String + } } diff --git a/Sources/WmapParser/DataStructures/Map.swift b/Sources/WmapParser/DataStructures/Map.swift index dbb3c7d..776ba18 100644 --- a/Sources/WmapParser/DataStructures/Map.swift +++ b/Sources/WmapParser/DataStructures/Map.swift @@ -1,12 +1,12 @@ extension WmapParser { -/// A parsed wardley map. -public struct Map: Sendable { - public let components: [Component] - public let dependencies: [Dependency] - public let notes: [Note] - public let stages: [Stage] - public let groups: [Group] - public let inertias: [Inertia] - public let evolutions: [Evolution] -} + /// A parsed wardley map. + public struct Map: Sendable, Equatable { + public let components: [Component] + public let dependencies: [Dependency] + public let notes: [Note] + public let stages: [Stage] + public let groups: [Group] + public let inertias: [Inertia] + public let evolutions: [Evolution] + } } diff --git a/Sources/WmapParser/DataStructures/MapPoint.swift b/Sources/WmapParser/DataStructures/MapPoint.swift index c0eb971..7fedc00 100644 --- a/Sources/WmapParser/DataStructures/MapPoint.swift +++ b/Sources/WmapParser/DataStructures/MapPoint.swift @@ -1,7 +1,7 @@ extension WmapParser { - /// A point in the map - public struct MapPoint: Sendable, Equatable { - let xCoordinate: Double - let yCoordinate: Double - } + /// A point in the map + public struct MapPoint: Sendable, Equatable { + let xCoordinate: Double + let yCoordinate: Double + } } diff --git a/Sources/WmapParser/DataStructures/Note.swift b/Sources/WmapParser/DataStructures/Note.swift index de87979..b6184a9 100644 --- a/Sources/WmapParser/DataStructures/Note.swift +++ b/Sources/WmapParser/DataStructures/Note.swift @@ -1,7 +1,7 @@ extension WmapParser { -/// A note. -public struct Note: Sendable, Equatable { - public let text: String - public let coordinates: MapPoint -} + /// A note. + public struct Note: Sendable, Equatable { + public let text: String + public let coordinates: MapPoint + } } diff --git a/Sources/WmapParser/DataStructures/Shape.swift b/Sources/WmapParser/DataStructures/Shape.swift index 146b0e6..4870670 100644 --- a/Sources/WmapParser/DataStructures/Shape.swift +++ b/Sources/WmapParser/DataStructures/Shape.swift @@ -1,10 +1,10 @@ extension WmapParser { -/// Any of the potential shapes in a component. -@frozen -public enum Shape: Sendable, Equatable { - case circle - case xMark - case square - case triangle -} + /// Any of the potential shapes in a component. + @frozen + public enum Shape: Sendable, Equatable { + case circle + case xMark + case square + case triangle + } } diff --git a/Sources/WmapParser/DataStructures/Stage.swift b/Sources/WmapParser/DataStructures/Stage.swift index e0a99f1..87efdc1 100644 --- a/Sources/WmapParser/DataStructures/Stage.swift +++ b/Sources/WmapParser/DataStructures/Stage.swift @@ -1,7 +1,7 @@ extension WmapParser { -/// An override for the width of an evolution stage. -public struct Stage: Sendable, Equatable { - public let stage: StageNumber - public let value: Double -} + /// An override for the width of an evolution stage. + public struct Stage: Sendable, Equatable { + public let stage: StageNumber + public let value: Double + } } diff --git a/Sources/WmapParser/DataStructures/StageNumber.swift b/Sources/WmapParser/DataStructures/StageNumber.swift index 603e06b..b308742 100644 --- a/Sources/WmapParser/DataStructures/StageNumber.swift +++ b/Sources/WmapParser/DataStructures/StageNumber.swift @@ -1,10 +1,10 @@ extension WmapParser { -/// The potential stages of evolution. -@frozen -public enum StageNumber: Sendable, Equatable { - case stageI - case stageII - case stageIII - case stageIV -} + /// The potential stages of evolution. + @frozen + public enum StageNumber: Sendable, Equatable { + case stageI + case stageII + case stageIII + case stageIV + } } diff --git a/Sources/WmapParser/DependencyParser.swift b/Sources/WmapParser/DependencyParser.swift index 891be01..2567bfe 100644 --- a/Sources/WmapParser/DependencyParser.swift +++ b/Sources/WmapParser/DependencyParser.swift @@ -1,52 +1,57 @@ extension WmapParser { - /// Looks for -- or ->. If found, returns where this arrow starts. - @inline(__always) - static func hasDependency<T: Collection>(_ bytes: T, _ start: Int, _ end: Int) -> Int? - where T.Element == UInt8, T.Index == Int { - var index = start - while index < end { - if bytes[index] == kOpenParenthesis { return nil } - if bytes[index] == kDash && index + 1 < end { - let next = bytes[index + 1] - if next == kGreaterThan || next == kDash { return index } - } - index += 1 + /// Looks for -- or ->. If found, returns where this arrow starts. + @inline(__always) + static func hasDependency<T: Collection>(_ bytes: T, _ start: Int, _ end: Int) -> Int? + where T.Element == UInt8, T.Index == Int { + var index = start + while index < end { + if bytes[index] == kOpenParenthesis { return nil } + if bytes[index] == kDash && index + 1 < end { + let next = bytes[index + 1] + if next == kGreaterThan || next == kDash { return index } } - return nil + index += 1 } + return nil + } - /// Finds a dependency and whether it's directed. It assumes we previously - /// checked for the location of our separator to speed things up. - static func parseDependency<T: Collection>(_ bytes: T, _ start: Int, _ end: Int, _ separatorIndex: Int) - -> Dependency? - where T.Element == UInt8, T.Index == Int { - guard let isDirected = extractIsDirected(bytes, separatorIndex, end) else { - return nil - } - - guard let fromComponent = extractTrimmedString(bytes, start, separatorIndex) else { - return nil - } + /// Finds a dependency and whether it's directed. It assumes we previously + /// checked for the location of our separator to speed things up. + static func parseDependency<T: Collection>( + _ bytes: T, _ start: Int, _ end: Int, _ separatorIndex: Int + ) + -> Dependency? + where T.Element == UInt8, T.Index == Int { + guard let isDirected = extractIsDirected(bytes, separatorIndex, end) else { + return nil + } - guard let toComponent = extractTrimmedString(bytes, separatorIndex + 2, end) else { - return nil - } + guard let fromComponent = extractTrimmedString(bytes, start, separatorIndex) else { + return nil + } - return Dependency(fromComponent: fromComponent, toComponent: toComponent, isDirected: isDirected) + guard let toComponent = extractTrimmedString(bytes, separatorIndex + 2, end) else { + return nil } - /// Checks the second character of the separator to see if it's directed. - /// It assumes we already checked for -- or ->, so it only checks for - /// Whether it's greaterThan or not. - @inline(__always) - private static func extractIsDirected<T: Collection>(_ bytes: T, _ separatorIndex: Int, _ end: Int) - -> Bool? - where T.Element == UInt8, T.Index == Int { - let followingCharacter = separatorIndex + 1 - guard followingCharacter < end else { return nil } - if bytes[followingCharacter] == kGreaterThan { - return true - } - return false + return Dependency( + fromComponent: fromComponent, toComponent: toComponent, isDirected: isDirected) + } + + /// Checks the second character of the separator to see if it's directed. + /// It assumes we already checked for -- or ->, so it only checks for + /// Whether it's greaterThan or not. + @inline(__always) + private static func extractIsDirected<T: Collection>( + _ bytes: T, _ separatorIndex: Int, _ end: Int + ) + -> Bool? + where T.Element == UInt8, T.Index == Int { + let followingCharacter = separatorIndex + 1 + guard followingCharacter < end else { return nil } + if bytes[followingCharacter] == kGreaterThan { + return true } + return false + } } diff --git a/Sources/WmapParser/KeywordParser.swift b/Sources/WmapParser/KeywordParser.swift index b560d6a..25f0ecd 100644 --- a/Sources/WmapParser/KeywordParser.swift +++ b/Sources/WmapParser/KeywordParser.swift @@ -1,186 +1,188 @@ extension WmapParser { - /// Checks which keyword we're dealing with and routes it to the right parser. - static func parseKeywordLine<T: Collection>( - _ bytes: T, _ start: Int, _ end: Int, - _ context: inout KeywordParserContext - ) where T.Element == UInt8, T.Index == Int { - guard let (keyword, rest) = extractKeyword(bytes, start, end) else { return } + /// Checks which keyword we're dealing with and routes it to the right parser. + static func parseKeywordLine<T: Collection>( + _ bytes: T, _ start: Int, _ end: Int, + _ context: inout KeywordParserContext + ) where T.Element == UInt8, T.Index == Int { + guard let (keyword, rest) = extractKeyword(bytes, start, end) else { return } - if matchesKeyword(keyword, kInertiaKeyword), let inertia = parseInertia(bytes, rest, end) { - context.inertias.append(inertia) - } else if matchesKeyword(keyword, kEvolutionKeyword), - let evolution = parseEvolution(bytes, rest, end) { - context.evolutions.append(evolution) - } else if matchesKeyword(keyword, kNoteKeyword), let note = parseNote(bytes, rest, end) { - context.notes.append(note) - } else if matchesKeyword(keyword, kGroupKeyword), let group = parseGroup(bytes, rest, end) { - context.groups.append(group) - } else if let stageNumber = isStageKeyword(keyword), - let stage = parseStage(bytes, stageNumber, rest, end) { - context.stages.append(stage) - } + if matchesKeyword(keyword, kInertiaKeyword), let inertia = parseInertia(bytes, rest, end) { + context.inertias.append(inertia) + } else if matchesKeyword(keyword, kEvolutionKeyword), + let evolution = parseEvolution(bytes, rest, end) { + context.evolutions.append(evolution) + } else if matchesKeyword(keyword, kNoteKeyword), let note = parseNote(bytes, rest, end) { + context.notes.append(note) + } else if matchesKeyword(keyword, kGroupKeyword), let group = parseGroup(bytes, rest, end) { + context.groups.append(group) + } else if let stageNumber = isStageKeyword(keyword), + let stage = parseStage(bytes, stageNumber, rest, end) { + context.stages.append(stage) } + } - /// Extracts a keyword from inside brackets. + the index of the rest of the - /// line. - @inline(__always) - static func extractKeyword<T: Collection>(_ bytes: T, _ start: Int, _ end: Int) -> (T.SubSequence, Int)? - where T.Element == UInt8, T.Index == Int { - var index = start + 1 // Skip '[' - let keywordStart = index + /// Extracts a keyword from inside brackets. + the index of the rest of the + /// line. + @inline(__always) + static func extractKeyword<T: Collection>(_ bytes: T, _ start: Int, _ end: Int) -> ( + T.SubSequence, Int + )? + where T.Element == UInt8, T.Index == Int { + var index = start + 1 // Skip '[' + let keywordStart = index - while index < end && bytes[index] != kCloseSquareBracket { index += 1 } // Find ']' - if index >= end { return nil } + while index < end && bytes[index] != kCloseSquareBracket { index += 1 } // Find ']' + if index >= end { return nil } - let keywordEnd = index - index += 1 + let keywordEnd = index + index += 1 - // Skip whitespace after ']' - index = skipWhitespace(bytes, end, index) + // Skip whitespace after ']' + index = skipWhitespace(bytes, end, index) - return (bytes[keywordStart..<keywordEnd], index) - } + return (bytes[keywordStart..<keywordEnd], index) + } - /// Checks the four potential values for the stage keyword. - @inline(__always) - static func isStageKeyword<T: Collection>(_ keyword: T) -> StageNumber? - where T.Element == UInt8, T.Index == Int { - if matchesKeyword(keyword, kIKeyword) { - return .stageI - } - if matchesKeyword(keyword, kIIKeyword) { - return .stageII - } - if matchesKeyword(keyword, kIIIKeyword) { - return .stageIII - } - if matchesKeyword(keyword, kIVKeyword) { - return .stageIV - } - return nil - } + /// Checks the four potential values for the stage keyword. + @inline(__always) + static func isStageKeyword<T: Collection>(_ keyword: T) -> StageNumber? + where T.Element == UInt8, T.Index == Int { + if matchesKeyword(keyword, kIKeyword) { + return .stageI + } + if matchesKeyword(keyword, kIIKeyword) { + return .stageII + } + if matchesKeyword(keyword, kIIIKeyword) { + return .stageIII + } + if matchesKeyword(keyword, kIVKeyword) { + return .stageIV + } + return nil + } - /// Compares a collection of bytes against a list of bytes. - /// Short-Circuits by length, only two have the same length (ii and iv) - @inline(__always) - static func matchesKeyword<T: Collection>(_ keyword: T, _ expected: [UInt8]) -> Bool - where T.Element == UInt8, T.Index == Int { - guard keyword.count == expected.count else { return false } - var keywordIndex = keyword.startIndex - for index in 0..<expected.count { - let currentKeyword = keyword[keywordIndex] - let expectedKeyword = expected[index] + /// Compares a collection of bytes against a list of bytes. + /// Short-Circuits by length, only two have the same length (ii and iv) + @inline(__always) + static func matchesKeyword<T: Collection>(_ keyword: T, _ expected: [UInt8]) -> Bool + where T.Element == UInt8, T.Index == Int { + guard keyword.count == expected.count else { return false } + var keywordIndex = keyword.startIndex + for index in 0..<expected.count { + let currentKeyword = keyword[keywordIndex] + let expectedKeyword = expected[index] - let lowercasedKeyword = - (currentKeyword >= kCapitalA && currentKeyword <= kCapitalZ) - ? currentKeyword + kCapsToLowercaseDistance : currentKeyword - if lowercasedKeyword != expectedKeyword { return false } - keywordIndex += 1 - } - return true - } + let lowercasedKeyword = + (currentKeyword >= kCapitalA && currentKeyword <= kCapitalZ) + ? currentKeyword + kCapsToLowercaseDistance : currentKeyword + if lowercasedKeyword != expectedKeyword { return false } + keywordIndex += 1 + } + return true + } - /// Parses the stage. Assumes we got the stage number in the keyword check - /// to avoid checking twice. - static func parseStage<T: Collection>( - _ bytes: T, _ stageNumber: StageNumber, _ start: Int, _ end: Int - ) -> Stage? - where T.Element == UInt8, T.Index == Int { - guard let value = parseDouble(bytes, start, end) else { return nil } + /// Parses the stage. Assumes we got the stage number in the keyword check + /// to avoid checking twice. + static func parseStage<T: Collection>( + _ bytes: T, _ stageNumber: StageNumber, _ start: Int, _ end: Int + ) -> Stage? + where T.Element == UInt8, T.Index == Int { + guard let value = parseDouble(bytes, start, end) else { return nil } - return Stage(stage: stageNumber, value: value) - } + return Stage(stage: stageNumber, value: value) + } - /// Parses the note coordinates and text. - static func parseNote<T: Collection>(_ bytes: T, _ start: Int, _ end: Int) -> Note? - where T.Element == UInt8, T.Index == Int { - var index = skipWhitespace(bytes, end, start) + /// Parses the note coordinates and text. + static func parseNote<T: Collection>(_ bytes: T, _ start: Int, _ end: Int) -> Note? + where T.Element == UInt8, T.Index == Int { + var index = skipWhitespace(bytes, end, start) - guard index < end && bytes[index] == kOpenParenthesis else { return nil } - index += 1 + guard index < end && bytes[index] == kOpenParenthesis else { return nil } + index += 1 - guard let (coordinates, endIndex) = parseCoordinates(bytes, index, end) else { - return nil - } - index = skipWhitespace(bytes, end, endIndex) + guard let (coordinates, endIndex) = parseCoordinates(bytes, index, end) else { + return nil + } + index = skipWhitespace(bytes, end, endIndex) - let textEnd = shaveWhitespace(bytes, index, end) + let textEnd = shaveWhitespace(bytes, index, end) - // Why not String(data:encoding:)? This is much faster. - // swiftlint:disable:next optional_data_string_conversion - let text = String(decoding: bytes[index..<textEnd], as: UTF8.self) - return Note(text: text, coordinates: coordinates) - } + // Why not String(data:encoding:)? This is much faster. + // swiftlint:disable:next optional_data_string_conversion + let text = String(decoding: bytes[index..<textEnd], as: UTF8.self) + return Note(text: text, coordinates: coordinates) + } - /// Parses the comma separated labels for a group - static func parseGroup<T: Collection>(_ bytes: T, _ start: Int, _ end: Int) -> Group? - where T.Element == UInt8, T.Index == Int { - var components = [String]() - var index = start - var componentStart = start + /// Parses the comma separated labels for a group + static func parseGroup<T: Collection>(_ bytes: T, _ start: Int, _ end: Int) -> Group? + where T.Element == UInt8, T.Index == Int { + var components = [String]() + var index = start + var componentStart = start - while index <= end { - if index == end || bytes[index] == kComma { - let trimStart = skipWhitespace(bytes, index, componentStart) - let trimEnd = shaveWhitespace(bytes, trimStart, index) + while index <= end { + if index == end || bytes[index] == kComma { + let trimStart = skipWhitespace(bytes, index, componentStart) + let trimEnd = shaveWhitespace(bytes, trimStart, index) - if trimStart < trimEnd { - // Why not String(data:encoding:)? This is much faster. - // swiftlint:disable:next optional_data_string_conversion - let component = String(decoding: bytes[trimStart..<trimEnd], as: UTF8.self) - components.append(component) - } + if trimStart < trimEnd { + // Why not String(data:encoding:)? This is much faster. + // swiftlint:disable:next optional_data_string_conversion + let component = String(decoding: bytes[trimStart..<trimEnd], as: UTF8.self) + components.append(component) + } - componentStart = index + 1 - } - index += 1 - } + componentStart = index + 1 + } + index += 1 + } - return components.isEmpty ? nil : Group(components: components) - } + return components.isEmpty ? nil : Group(components: components) + } - /// Parses the component label for inertia - static func parseInertia<T: Collection>(_ bytes: T, _ start: Int, _ end: Int) -> Inertia? - where T.Element == UInt8, T.Index == Int { - let trimStart = skipWhitespace(bytes, end, start) - let trimEnd = shaveWhitespace(bytes, trimStart, end) + /// Parses the component label for inertia + static func parseInertia<T: Collection>(_ bytes: T, _ start: Int, _ end: Int) -> Inertia? + where T.Element == UInt8, T.Index == Int { + let trimStart = skipWhitespace(bytes, end, start) + let trimEnd = shaveWhitespace(bytes, trimStart, end) - guard trimStart < trimEnd else { return nil } + guard trimStart < trimEnd else { return nil } - // Why not String(data:encoding:)? This is much faster. - // swiftlint:disable:next optional_data_string_conversion - let component = String(decoding: bytes[trimStart..<trimEnd], as: UTF8.self) - return Inertia(component: component) - } + // Why not String(data:encoding:)? This is much faster. + // swiftlint:disable:next optional_data_string_conversion + let component = String(decoding: bytes[trimStart..<trimEnd], as: UTF8.self) + return Inertia(component: component) + } - /// Parses the component label and value for inertia - static func parseEvolution<T: Collection>(_ bytes: T, _ start: Int, _ end: Int) -> Evolution? - where T.Element == UInt8, T.Index == Int { - var signIndex: Int? - var sign = 1.0 + /// Parses the component label and value for inertia + static func parseEvolution<T: Collection>(_ bytes: T, _ start: Int, _ end: Int) -> Evolution? + where T.Element == UInt8, T.Index == Int { + var signIndex: Int? + var sign = 1.0 - var index = start - while index < end { - if bytes[index] == kPlus || bytes[index] == kDash { - signIndex = index - sign = bytes[index] == 45 ? -1.0 : 1.0 - break - } - index += 1 - } + var index = start + while index < end { + if bytes[index] == kPlus || bytes[index] == kDash { + signIndex = index + sign = bytes[index] == 45 ? -1.0 : 1.0 + break + } + index += 1 + } - guard let signIndex, signIndex > start else { return nil } + guard let signIndex, signIndex > start else { return nil } - let trimStart = skipWhitespace(bytes, signIndex, start) - let trimEnd = shaveWhitespace(bytes, trimStart, signIndex) + let trimStart = skipWhitespace(bytes, signIndex, start) + let trimEnd = shaveWhitespace(bytes, trimStart, signIndex) - guard trimStart < trimEnd else { return nil } + guard trimStart < trimEnd else { return nil } - // Why not String(data:encoding:)? This is much faster. - // swiftlint:disable:next optional_data_string_conversion - let component = String(decoding: bytes[trimStart..<trimEnd], as: UTF8.self) - guard let value = parseDouble(bytes, signIndex + 1, end) else { return nil } + // Why not String(data:encoding:)? This is much faster. + // swiftlint:disable:next optional_data_string_conversion + let component = String(decoding: bytes[trimStart..<trimEnd], as: UTF8.self) + guard let value = parseDouble(bytes, signIndex + 1, end) else { return nil } - return Evolution(component: component, value: sign * value) - } + return Evolution(component: component, value: sign * value) + } } diff --git a/Sources/WmapParser/ParserContext/KeywordParserContext.swift b/Sources/WmapParser/ParserContext/KeywordParserContext.swift index c3a77a7..bfafad2 100644 --- a/Sources/WmapParser/ParserContext/KeywordParserContext.swift +++ b/Sources/WmapParser/ParserContext/KeywordParserContext.swift @@ -1,9 +1,9 @@ extension WmapParser { - struct KeywordParserContext { - var stages: [Stage] - var notes: [Note] - var groups: [Group] - var inertias: [Inertia] - var evolutions: [Evolution] - } + struct KeywordParserContext { + var stages: [Stage] + var notes: [Note] + var groups: [Group] + var inertias: [Inertia] + var evolutions: [Evolution] + } } diff --git a/Sources/WmapParser/ParserContext/LineParserContext.swift b/Sources/WmapParser/ParserContext/LineParserContext.swift index c823383..67b156c 100644 --- a/Sources/WmapParser/ParserContext/LineParserContext.swift +++ b/Sources/WmapParser/ParserContext/LineParserContext.swift @@ -1,7 +1,7 @@ extension WmapParser { - struct LineParserContext { - var components: [Component] - var dependencies: [Dependency] - var keywordContext: KeywordParserContext - } + struct LineParserContext { + var components: [Component] + var dependencies: [Dependency] + var keywordContext: KeywordParserContext + } } diff --git a/Sources/WmapParser/Utils.swift b/Sources/WmapParser/Utils.swift index d79578b..4886eb3 100644 --- a/Sources/WmapParser/Utils.swift +++ b/Sources/WmapParser/Utils.swift @@ -1,138 +1,142 @@ extension WmapParser { - /// Check if a byte is a digit - @inline(__always) - static func isDigit(_ byte: UInt8) -> Bool { - byte >= kZero && byte <= kNine - } + /// Check if a byte is a digit + @inline(__always) + static func isDigit(_ byte: UInt8) -> Bool { + byte >= kZero && byte <= kNine + } - /// Looks for x and y separated by a comma. - static func parseCoordinates<T: Collection>(_ bytes: T, _ start: Int, _ end: Int) -> ( - MapPoint, Int - )? - where T.Element == UInt8, T.Index == Int { - var index = skipWhitespace(bytes, end, start) + /// Looks for x and y separated by a comma. + static func parseCoordinates<T: Collection>(_ bytes: T, _ start: Int, _ end: Int) -> ( + MapPoint, Int + )? + where T.Element == UInt8, T.Index == Int { + var index = skipWhitespace(bytes, end, start) - guard let (xCoordinate, nextIndex) = parseSingleCoordinate(bytes, index, end) else { - return nil - } - index = nextIndex + guard let (xCoordinate, nextIndex) = parseSingleCoordinate(bytes, index, end) else { + return nil + } + index = nextIndex - guard expectComma(bytes, &index, end) else { return nil } + guard expectComma(bytes, &index, end) else { return nil } - guard let (yCoordinate, nextIndex) = parseSingleCoordinate(bytes, index, end) else { - return nil - } - index = nextIndex + guard let (yCoordinate, nextIndex) = parseSingleCoordinate(bytes, index, end) else { + return nil + } + index = nextIndex - guard expectClosingParen(bytes, &index, end) else { return nil } + guard expectClosingParen(bytes, &index, end) else { return nil } - return (MapPoint(xCoordinate: xCoordinate, yCoordinate: yCoordinate), index) - } + return (MapPoint(xCoordinate: xCoordinate, yCoordinate: yCoordinate), index) + } - /// Checks if a candidate for a coordinate is a digit, and parses it. - @inline(__always) - static func parseSingleCoordinate<T: Collection>(_ bytes: T, _ start: Int, _ end: Int) -> (Double, Int)? - where T.Element == UInt8, T.Index == Int { - var index = start - while index < end && (isDigit(bytes[index]) || bytes[index] == 46) { index += 1 } - guard index > start else { return nil } - guard let value = parseDouble(bytes, start, index) else { return nil } - return (value, index) - } + /// Checks if a candidate for a coordinate is a digit, and parses it. + @inline(__always) + static func parseSingleCoordinate<T: Collection>(_ bytes: T, _ start: Int, _ end: Int) -> ( + Double, Int + )? + where T.Element == UInt8, T.Index == Int { + var index = start + while index < end && (isDigit(bytes[index]) || bytes[index] == 46) { index += 1 } + guard index > start else { return nil } + guard let value = parseDouble(bytes, start, index) else { return nil } + return (value, index) + } - /// Advances the index until we find a comma. - @inline(__always) - static func expectComma<T: Collection>(_ bytes: T, _ index: inout Int, _ end: Int) -> Bool - where T.Element == UInt8, T.Index == Int { - index = skipWhitespace(bytes, end, index) - guard index < end && bytes[index] == kComma else { return false } - index += 1 - index = skipWhitespace(bytes, end, index) - return true - } + /// Advances the index until we find a comma. + @inline(__always) + static func expectComma<T: Collection>(_ bytes: T, _ index: inout Int, _ end: Int) -> Bool + where T.Element == UInt8, T.Index == Int { + index = skipWhitespace(bytes, end, index) + guard index < end && bytes[index] == kComma else { return false } + index += 1 + index = skipWhitespace(bytes, end, index) + return true + } - /// Advances the index until we find a closing parenthesis - @inline(__always) - static func expectClosingParen<T: Collection>(_ bytes: T, _ index: inout Int, _ end: Int) -> Bool - where T.Element == UInt8, T.Index == Int { - index = skipWhitespace(bytes, end, index) - guard index < end && bytes[index] == kCloseParenthesis else { return false } - index += 1 - return true - } + /// Advances the index until we find a closing parenthesis + @inline(__always) + static func expectClosingParen<T: Collection>(_ bytes: T, _ index: inout Int, _ end: Int) -> Bool + where T.Element == UInt8, T.Index == Int { + index = skipWhitespace(bytes, end, index) + guard index < end && bytes[index] == kCloseParenthesis else { return false } + index += 1 + return true + } - /// Parses a double - @inline(__always) - static func parseDouble<T: Collection>(_ bytes: T, _ start: Int, _ end: Int) -> Double? - where T.Element == UInt8, T.Index == Int { - var index = skipWhitespace(bytes, end, start) + /// Parses a double + @inline(__always) + static func parseDouble<T: Collection>(_ bytes: T, _ start: Int, _ end: Int) -> Double? + where T.Element == UInt8, T.Index == Int { + var index = skipWhitespace(bytes, end, start) - let numStart = index - while index < end && (isDigit(bytes[index]) || bytes[index] == kPeriod) { index += 1 } + let numStart = index + while index < end && (isDigit(bytes[index]) || bytes[index] == kPeriod) { index += 1 } - guard index > numStart else { return nil } + guard index > numStart else { return nil } - // Why not String(data:encoding:)? This is much faster. - // swiftlint:disable:next optional_data_string_conversion - let str = String(decoding: bytes[numStart..<index], as: UTF8.self) - return Double(str) - } + // Why not String(data:encoding:)? This is much faster. + // swiftlint:disable:next optional_data_string_conversion + let str = String(decoding: bytes[numStart..<index], as: UTF8.self) + return Double(str) + } - /// Advances an index by looking for whitespace left-to-right - static func skipWhitespace<T: Collection>(_ bytes: T, _ end: Int, _ start: Int) -> Int - where T.Element == UInt8, T.Index == Int { - var index = start - while index < end && (bytes[index] == kSpace || bytes[index] == kTab) { index += 1 } - return index - } + /// Advances an index by looking for whitespace left-to-right + static func skipWhitespace<T: Collection>(_ bytes: T, _ end: Int, _ start: Int) -> Int + where T.Element == UInt8, T.Index == Int { + var index = start + while index < end && (bytes[index] == kSpace || bytes[index] == kTab) { index += 1 } + return index + } - /// Decreases an index by looking for whitespace right-to-left - static func shaveWhitespace<T: Collection>(_ bytes: T, _ start: Int, _ end: Int) -> Int - where T.Element == UInt8, T.Index == Int { - var index = end - while index > start && (bytes[index - 1] == kSpace || bytes[index - 1] == kTab) { index -= 1 } - return index - } + /// Decreases an index by looking for whitespace right-to-left + static func shaveWhitespace<T: Collection>(_ bytes: T, _ start: Int, _ end: Int) -> Int + where T.Element == UInt8, T.Index == Int { + var index = end + while index > start && (bytes[index - 1] == kSpace || bytes[index - 1] == kTab) { index -= 1 } + return index + } - /// Given the bytes buffer, finds the next non-empty line. - @inline(__always) - static func extractLine<T: Collection>(_ bytes: T, _ index: inout Int, _ length: Int) -> ( - Int, Int - )? - where T.Element == UInt8, T.Index == Int { - while index < length && (bytes[index] == kNewline || bytes[index] == kCarriageReturn) { - index += 1 - } - let lineStart = index + /// Given the bytes buffer, finds the next non-empty line. + @inline(__always) + static func extractLine<T: Collection>(_ bytes: T, _ index: inout Int, _ length: Int) -> ( + Int, Int + )? + where T.Element == UInt8, T.Index == Int { + while index < length && (bytes[index] == kNewline || bytes[index] == kCarriageReturn) { + index += 1 + } + let lineStart = index - while index < length && bytes[index] != kNewline && bytes[index] != kCarriageReturn { index += 1 } - if lineStart == index { return nil } + while index < length && bytes[index] != kNewline && bytes[index] != kCarriageReturn { + index += 1 + } + if lineStart == index { return nil } - var start = lineStart - var end = index + var start = lineStart + var end = index - start = skipWhitespace(bytes, end, start) - end = shaveWhitespace(bytes, start, end) + start = skipWhitespace(bytes, end, start) + end = shaveWhitespace(bytes, start, end) - if start == end { return nil } + if start == end { return nil } - return (start, end) - } + return (start, end) + } - /// Trims a byte collection and returns a string - @inline(__always) - static func extractTrimmedString<T: Collection>(_ bytes: T, _ start: Int, _ end: Int) -> String? - where T.Element == UInt8, T.Index == Int { - var trimStart = start - var trimEnd = end + /// Trims a byte collection and returns a string + @inline(__always) + static func extractTrimmedString<T: Collection>(_ bytes: T, _ start: Int, _ end: Int) -> String? + where T.Element == UInt8, T.Index == Int { + var trimStart = start + var trimEnd = end - trimStart = skipWhitespace(bytes, trimEnd, trimStart) - trimEnd = shaveWhitespace(bytes, trimStart, trimEnd) + trimStart = skipWhitespace(bytes, trimEnd, trimStart) + trimEnd = shaveWhitespace(bytes, trimStart, trimEnd) - guard trimStart < trimEnd else { return nil } + guard trimStart < trimEnd else { return nil } - // Why not String(data:encoding:)? This is much faster. - // swiftlint:disable:next optional_data_string_conversion - return String(decoding: bytes[trimStart..<trimEnd], as: UTF8.self) - } + // Why not String(data:encoding:)? This is much faster. + // swiftlint:disable:next optional_data_string_conversion + return String(decoding: bytes[trimStart..<trimEnd], as: UTF8.self) + } } diff --git a/Sources/WmapParser/WmapParser.swift b/Sources/WmapParser/WmapParser.swift index 41843b3..ef203ec 100644 --- a/Sources/WmapParser/WmapParser.swift +++ b/Sources/WmapParser/WmapParser.swift @@ -2,75 +2,76 @@ import Foundation public struct WmapParser { - // Public API ////////////////////////////////////////////////////////////////// + // Public API ////////////////////////////////////////////////////////////////// - /// Parses a wmap source string. - public static func parse(_ source: String) -> Map { - source.utf8.withContiguousStorageIfAvailable { bytes in - parseBytes(bytes) - } ?? parseBytes(Array(source.utf8)) - } - - // Parsers ///////////////////////////////////////////////////////////////////// + /// Parses a wmap source string. + public static func parse(_ source: String) -> Map { + source.utf8.withContiguousStorageIfAvailable { bytes in + parseBytes(bytes) + } ?? parseBytes(Array(source.utf8)) + } - /// Main parsing function, we work on bytes as it's faster. - private static func parseBytes<T: Collection>(_ bytes: T) -> Map where T.Element == UInt8, T.Index == Int { - let estimatedLines = bytes.count / 30 + // Parsers ///////////////////////////////////////////////////////////////////// - var context = LineParserContext( - components: [], - dependencies: [], - keywordContext: KeywordParserContext( - stages: [], - notes: [], - groups: [], - inertias: [], - evolutions: [] - ) - ) + /// Main parsing function, we work on bytes as it's faster. + private static func parseBytes<T: Collection>(_ bytes: T) -> Map + where T.Element == UInt8, T.Index == Int { + let estimatedLines = bytes.count / 30 - context.components.reserveCapacity(estimatedLines) - context.dependencies.reserveCapacity(estimatedLines) - context.keywordContext.notes.reserveCapacity(estimatedLines / 10) - context.keywordContext.stages.reserveCapacity(4) - context.keywordContext.groups.reserveCapacity(estimatedLines / 20) - context.keywordContext.inertias.reserveCapacity(estimatedLines / 20) - context.keywordContext.evolutions.reserveCapacity(estimatedLines / 20) + var context = LineParserContext( + components: [], + dependencies: [], + keywordContext: KeywordParserContext( + stages: [], + notes: [], + groups: [], + inertias: [], + evolutions: [] + ) + ) - var index = 0 - let length = bytes.count + context.components.reserveCapacity(estimatedLines) + context.dependencies.reserveCapacity(estimatedLines) + context.keywordContext.notes.reserveCapacity(estimatedLines / 10) + context.keywordContext.stages.reserveCapacity(4) + context.keywordContext.groups.reserveCapacity(estimatedLines / 20) + context.keywordContext.inertias.reserveCapacity(estimatedLines / 20) + context.keywordContext.evolutions.reserveCapacity(estimatedLines / 20) - while index < length { - guard let (start, end) = extractLine(bytes, &index, length) else { continue } - parseLine(bytes, start, end, &context) - } + var index = 0 + let length = bytes.count - return Map( - components: context.components, - dependencies: context.dependencies, - notes: context.keywordContext.notes, - stages: context.keywordContext.stages, - groups: context.keywordContext.groups, - inertias: context.keywordContext.inertias, - evolutions: context.keywordContext.evolutions - ) + while index < length { + guard let (start, end) = extractLine(bytes, &index, length) else { continue } + parseLine(bytes, start, end, &context) } - /// Given a trimmed line, checks if it's a keyword, dependency or component - /// and parses it. - @inline(__always) - private static func parseLine<T: Collection>( - _ bytes: T, _ start: Int, _ end: Int, - _ context: inout LineParserContext - ) where T.Element == UInt8, T.Index == Int { - if bytes[start] == kOpenSquareBracket { - parseKeywordLine(bytes, start, end, &context.keywordContext) - } else if let separatorIndex = hasDependency(bytes, start, end) { - if let dependency = parseDependency(bytes, start, end, separatorIndex) { - context.dependencies.append(dependency) - } - } else if let component = parseComponent(bytes, start, end) { - context.components.append(component) - } - } + return Map( + components: context.components, + dependencies: context.dependencies, + notes: context.keywordContext.notes, + stages: context.keywordContext.stages, + groups: context.keywordContext.groups, + inertias: context.keywordContext.inertias, + evolutions: context.keywordContext.evolutions + ) + } + + /// Given a trimmed line, checks if it's a keyword, dependency or component + /// and parses it. + @inline(__always) + private static func parseLine<T: Collection>( + _ bytes: T, _ start: Int, _ end: Int, + _ context: inout LineParserContext + ) where T.Element == UInt8, T.Index == Int { + if bytes[start] == kOpenSquareBracket { + parseKeywordLine(bytes, start, end, &context.keywordContext) + } else if let separatorIndex = hasDependency(bytes, start, end) { + if let dependency = parseDependency(bytes, start, end, separatorIndex) { + context.dependencies.append(dependency) + } + } else if let component = parseComponent(bytes, start, end) { + context.components.append(component) + } + } } diff --git a/Tests/WmapParserTests/ComponentParserTests.swift b/Tests/WmapParserTests/ComponentParserTests.swift index 1f3a451..624f433 100644 --- a/Tests/WmapParserTests/ComponentParserTests.swift +++ b/Tests/WmapParserTests/ComponentParserTests.swift @@ -9,7 +9,8 @@ import Testing #expect( result.components.first == WmapParser.Component( - label: "Dominoes", coordinates: WmapParser.MapPoint(xCoordinate: 0.9, yCoordinate: 0.5), shape: .circle + label: "Dominoes", coordinates: WmapParser.MapPoint(xCoordinate: 0.9, yCoordinate: 0.5), + shape: .circle ) ) } @@ -33,7 +34,8 @@ import Testing #expect( result.components.first == WmapParser.Component( - label: "API", coordinates: WmapParser.MapPoint(xCoordinate: 0.5, yCoordinate: 0.6), shape: .xMark) + label: "API", coordinates: WmapParser.MapPoint(xCoordinate: 0.5, yCoordinate: 0.6), + shape: .xMark) ) } @@ -56,7 +58,8 @@ import Testing #expect( result.components.first == WmapParser.Component( - label: "Process", coordinates: WmapParser.MapPoint(xCoordinate: 0.2, yCoordinate: 0.9), shape: .circle) + label: "Process", coordinates: WmapParser.MapPoint(xCoordinate: 0.2, yCoordinate: 0.9), + shape: .circle) ) } @@ -79,7 +82,8 @@ import Testing #expect( result.components.first == WmapParser.Component( - label: "Item", coordinates: WmapParser.MapPoint(xCoordinate: 0.5, yCoordinate: 0.123), shape: .circle) + label: "Item", coordinates: WmapParser.MapPoint(xCoordinate: 0.5, yCoordinate: 0.123), + shape: .circle) ) } @@ -90,7 +94,8 @@ import Testing #expect( result.components.first == WmapParser.Component( - label: "Item", coordinates: WmapParser.MapPoint(xCoordinate: 1.0, yCoordinate: 0.0), shape: .circle) + label: "Item", coordinates: WmapParser.MapPoint(xCoordinate: 1.0, yCoordinate: 0.0), + shape: .circle) ) } @@ -101,7 +106,8 @@ import Testing #expect( result.components.first == WmapParser.Component( - label: "RubberGaskets", coordinates: WmapParser.MapPoint(xCoordinate: 0.5, yCoordinate: 0.5), + label: "RubberGaskets", + coordinates: WmapParser.MapPoint(xCoordinate: 0.5, yCoordinate: 0.5), shape: .circle) ) } @@ -113,7 +119,8 @@ import Testing #expect( result.components.first == WmapParser.Component( - label: "Big Lawnmowers", coordinates: WmapParser.MapPoint(xCoordinate: 0.5, yCoordinate: 0.5), + label: "Big Lawnmowers", + coordinates: WmapParser.MapPoint(xCoordinate: 0.5, yCoordinate: 0.5), shape: .circle) ) } diff --git a/Tests/WmapParserTests/DependenciesParserTests.swift b/Tests/WmapParserTests/DependenciesParserTests.swift index 356d5d3..4911ce0 100644 --- a/Tests/WmapParserTests/DependenciesParserTests.swift +++ b/Tests/WmapParserTests/DependenciesParserTests.swift @@ -29,7 +29,8 @@ import Testing #expect(result.dependencies.count == 1) #expect( result.dependencies.first - == WmapParser.Dependency(fromComponent: "SaRcAsM", toComponent: "Seriousness.", isDirected: true) + == WmapParser.Dependency( + fromComponent: "SaRcAsM", toComponent: "Seriousness.", isDirected: true) ) } diff --git a/Tests/WmapParserTests/NotesParserTests.swift b/Tests/WmapParserTests/NotesParserTests.swift index ae99c75..9e906dc 100644 --- a/Tests/WmapParserTests/NotesParserTests.swift +++ b/Tests/WmapParserTests/NotesParserTests.swift @@ -8,7 +8,9 @@ import Testing #expect(result.notes.count == 1) #expect( result.notes.first - == WmapParser.Note(text: "This is a note", coordinates: WmapParser.MapPoint(xCoordinate: 0.5, yCoordinate: 0.5)) + == WmapParser.Note( + text: "This is a note", coordinates: WmapParser.MapPoint(xCoordinate: 0.5, yCoordinate: 0.5) + ) ) } @@ -18,7 +20,8 @@ import Testing #expect(result.notes.count == 1) #expect( result.notes.first - == WmapParser.Note(text: "Text", coordinates: WmapParser.MapPoint(xCoordinate: 0.1, yCoordinate: 0.2)) + == WmapParser.Note( + text: "Text", coordinates: WmapParser.MapPoint(xCoordinate: 0.1, yCoordinate: 0.2)) ) } @@ -28,7 +31,9 @@ import Testing #expect(result.notes.count == 1) #expect( result.notes.first - == WmapParser.Note(text: "Important NOTE", coordinates: WmapParser.MapPoint(xCoordinate: 0.77, yCoordinate: 0.19)) + == WmapParser.Note( + text: "Important NOTE", + coordinates: WmapParser.MapPoint(xCoordinate: 0.77, yCoordinate: 0.19)) ) } @@ -37,9 +42,10 @@ import Testing let result = WmapParser.parse(source) #expect(result.notes.count == 1) #expect( - result.notes.first == WmapParser.Note( + result.notes.first + == WmapParser.Note( text: "", coordinates: WmapParser.MapPoint(xCoordinate: 0.5, yCoordinate: 0.5) - ) + ) ) } diff --git a/Tests/WmapParserTests/WmapParserTests.swift b/Tests/WmapParserTests/WmapParserTests.swift index f5dfe38..baf114f 100644 --- a/Tests/WmapParserTests/WmapParserTests.swift +++ b/Tests/WmapParserTests/WmapParserTests.swift @@ -13,12 +13,14 @@ import Testing #expect( result.components.first == WmapParser.Component( - label: "Water", coordinates: WmapParser.MapPoint(xCoordinate: 0.9, yCoordinate: 0.5), shape: .circle) + label: "Water", coordinates: WmapParser.MapPoint(xCoordinate: 0.9, yCoordinate: 0.5), + shape: .circle) ) #expect( result.components[1] == WmapParser.Component( - label: "Bucket", coordinates: WmapParser.MapPoint(xCoordinate: 0.8, yCoordinate: 0.4), shape: .xMark) + label: "Bucket", coordinates: WmapParser.MapPoint(xCoordinate: 0.8, yCoordinate: 0.4), + shape: .xMark) ) #expect(result.dependencies.count == 1) #expect( @@ -34,13 +36,15 @@ import Testing #expect( result.components.first == WmapParser.Component( - label: "Penguins", coordinates: WmapParser.MapPoint(xCoordinate: 0.9, yCoordinate: 0.5), shape: .circle + label: "Penguins", coordinates: WmapParser.MapPoint(xCoordinate: 0.9, yCoordinate: 0.5), + shape: .circle ) ) #expect( result.components[1] == WmapParser.Component( - label: "I Use Arch BTW", coordinates: WmapParser.MapPoint(xCoordinate: 0.8, yCoordinate: 0.4), + label: "I Use Arch BTW", + coordinates: WmapParser.MapPoint(xCoordinate: 0.8, yCoordinate: 0.4), shape: .xMark) ) } @@ -52,7 +56,8 @@ import Testing #expect( result.components.first == WmapParser.Component( - label: "Clippy", coordinates: WmapParser.MapPoint(xCoordinate: 0.9, yCoordinate: 0.5), shape: .circle) + label: "Clippy", coordinates: WmapParser.MapPoint(xCoordinate: 0.9, yCoordinate: 0.5), + shape: .circle) ) #expect( result.components[1] @@ -69,12 +74,14 @@ import Testing #expect( result.components.first == WmapParser.Component( - label: "SE/30", coordinates: WmapParser.MapPoint(xCoordinate: 0.9, yCoordinate: 0.5), shape: .circle) + label: "SE/30", coordinates: WmapParser.MapPoint(xCoordinate: 0.9, yCoordinate: 0.5), + shape: .circle) ) #expect( result.components[1] == WmapParser.Component( - label: "Performa", coordinates: WmapParser.MapPoint(xCoordinate: 0.8, yCoordinate: 0.4), shape: .xMark) + label: "Performa", coordinates: WmapParser.MapPoint(xCoordinate: 0.8, yCoordinate: 0.4), + shape: .xMark) ) } @@ -89,7 +96,8 @@ import Testing #expect( result.components.first == WmapParser.Component( - label: "The Void", coordinates: WmapParser.MapPoint(xCoordinate: 0.9, yCoordinate: 0.5), shape: .circle + label: "The Void", coordinates: WmapParser.MapPoint(xCoordinate: 0.9, yCoordinate: 0.5), + shape: .circle ) ) #expect( @@ -171,12 +179,14 @@ import Testing #expect( result.components.first == WmapParser.Component( - label: "Hello", coordinates: WmapParser.MapPoint(xCoordinate: 0.9, yCoordinate: 0.5), shape: .circle) + label: "Hello", coordinates: WmapParser.MapPoint(xCoordinate: 0.9, yCoordinate: 0.5), + shape: .circle) ) #expect( result.components[1] == WmapParser.Component( - label: "It's OK", coordinates: WmapParser.MapPoint(xCoordinate: 0.8, yCoordinate: 0.4), shape: .circle) + label: "It's OK", coordinates: WmapParser.MapPoint(xCoordinate: 0.8, yCoordinate: 0.4), + shape: .circle) ) #expect(result.dependencies.count == 1) #expect( @@ -267,17 +277,20 @@ import Testing #expect( result.components.first == WmapParser.Component( - label: "Tea", coordinates: WmapParser.MapPoint(xCoordinate: 0.9, yCoordinate: 0.5), shape: .circle) + label: "Tea", coordinates: WmapParser.MapPoint(xCoordinate: 0.9, yCoordinate: 0.5), + shape: .circle) ) #expect( result.components[1] == WmapParser.Component( - label: "Cup", coordinates: WmapParser.MapPoint(xCoordinate: 0.8, yCoordinate: 0.4), shape: .circle) + label: "Cup", coordinates: WmapParser.MapPoint(xCoordinate: 0.8, yCoordinate: 0.4), + shape: .circle) ) #expect( result.components[2] == WmapParser.Component( - label: "Kettle", coordinates: WmapParser.MapPoint(xCoordinate: 0.7, yCoordinate: 0.3), shape: .square) + label: "Kettle", coordinates: WmapParser.MapPoint(xCoordinate: 0.7, yCoordinate: 0.3), + shape: .square) ) #expect( result.components[3] |