aboutsummaryrefslogtreecommitdiff
path: root/Sources/WmapParser/DependencyParser.swift
blob: 891be01afb88464a1d5235ff346e0b1a026b94d3 (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
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 {
      guard let isDirected = extractIsDirected(bytes, separatorIndex, end) else {
        return nil
      }

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