aboutsummaryrefslogtreecommitdiff
path: root/Sources/WmapParser/DependencyParser.swift
blob: 45408d549bace1cb64a46964b98fd3c63b6db4b7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
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
    }
    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 {
    let isDirected = extractIsDirected(bytes, separatorIndex, end)

    guard let fromComponent = extractTrimmedString(bytes, start, separatorIndex) else {
      return nil
    }

    guard let toComponent = extractTrimmedString(bytes, separatorIndex + 2, end) else {
      return nil
    }

    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 false }
    if bytes[followingCharacter] == kGreaterThan {
      return true
    }
    return false
  }
}