Repository: airbnb/lottie-ios
File: Sources/Private/Experimental/ValueProviderStore.swift (Swift)

Code before:
      return typeErasedKeyframe.withValue(convertedValue)
    }

    // Verify that all of the keyframes were successfully converted to the expected type
    guard typedKeyframes.count == typeErasedKeyframes.count else {
      return nil
    }

    return KeyframeGroup(keyframes: ContiguousArray(typedKeyframes))
  }

  // MARK: Private

  private var valueProviders = [(keypath: AnimationKeypath, valueProvider: AnyValueProvider)]()

  /// Retrieves the most-recently-registered Value Provider that matches the given keypat
  private func valueProvider(for keypath: AnimationKeypath) -> AnyValueProvider? {
    // Iterate backwards though the list of value providers,
    // so the first match we find is the one that was registered most recently
    for (registeredKeypath, valueProvider) in valueProviders.reversed() {
      if registeredKeypath.matches(keypath) {
        return valueProvider
      }
    }

    return nil
  }

}

extension AnyValueProviderStorage {
  /// Whether or not this type of value provider is supported
  /// by the new Core Animation rendering engine
  var isSupportedByCoreAnimationRenderingEngine: Bool {
    switch self {
    case .singleValue, .keyframes:
      return true
    case .closure:
      return false
    }
  }
}

extension AnimationKeypath {
  /// Whether or not this keypath matches the given keypath from the animation hierarchy
  func matches(_ keypath: AnimationKeypath) -> Bool {
    var regex = "^" // match the start of the string
      + keys.joined(separator: "\\.") // match this keypath, escaping "." characters
      + "$" // match the end of the string

    // ** wildcards match anything

Review comment (suggestion):
nit: if you want to be concise!
```suggestion
    valueProviders.reversed().first(where: { $0.matches($1) })?.valueProvider
```

Code after:
      return typeErasedKeyframe.withValue(convertedValue)
    }

    // Verify that all of the keyframes were successfully converted to the expected type
    guard typedKeyframes.count == typeErasedKeyframes.count else {
      return nil
    }

    return KeyframeGroup(keyframes: ContiguousArray(typedKeyframes))
  }

  // MARK: Private

  private var valueProviders = [(keypath: AnimationKeypath, valueProvider: AnyValueProvider)]()

  /// Retrieves the most-recently-registered Value Provider that matches the given keypat
  private func valueProvider(for keypath: AnimationKeypath) -> AnyValueProvider? {
    // Find the last keypath matching the given keypath,
    // so we return the value provider that was registered most-recently
    valueProviders.last(where: { registeredKeypath, _ in
      keypath.matches(registeredKeypath)
    })?.valueProvider
  }

}

extension AnyValueProviderStorage {
  /// Whether or not this type of value provider is supported
  /// by the new Core Animation rendering engine
  var isSupportedByCoreAnimationRenderingEngine: Bool {
    switch self {
    case .singleValue, .keyframes:
      return true
    case .closure:
      return false
    }
  }
}

extension AnimationKeypath {
  /// Whether or not this keypath from the animation hierarchy
  /// matches the given keypath (which may contain wildcards)
  func matches(_ keypath: AnimationKeypath) -> Bool {
    var regex = "^" // match the start of the string
      + keypath.keys.joined(separator: "\\.") // match this keypath, escaping "." characters
      + "$" // match the end of the string

    // ** wildcards match anything
    //  - "**.Color" matches both "Layer 1.Color" and "Layer 1.Layer 2.Color"
    regex = regex.replacingOccurrences(of: "**", with: ".+")