<commit_before>public class ResolverBase: CObject {
  private override init (_ pointer: COpaquePointer, shouldCopy: Bool = true)
  {
    super.init(pointer, shouldCopy: shouldCopy)
  }

  private func createDependencyList (project: COpaquePointer, selectedVersion: COpaquePointer, error: UnsafeMutablePointer<UnsafeMutablePointer<CChar>>) -> COpaquePointer
  {
    preconditionFailure("Must be overridden by subclasses")
  }

  private func createAvailableVersionsList (project: COpaquePointer, error: UnsafeMutablePointer<UnsafeMutablePointer<CChar>>) -> COpaquePointer
  {
    preconditionFailure("Must be overridden by subclasses")
  }

  private func createSelectedVersionForMetadata (metadata: UnsafePointer<Void>) -> COpaquePointer
  {
    preconditionFailure("Must be overridden by subclasses")
  }
}

public final class Resolver<ProjectValue: ArbiterValue, VersionMetadata: ArbiterValue> : ResolverBase
{
  public typealias ListDependencies = (Resolver, ProjectIdentifier<ProjectValue>, SelectedVersion<VersionMetadata>) throws -> DependencyList<ProjectValue>
  public typealias ListAvailableVersions = (Resolver, ProjectIdentifier<ProjectValue>) throws -> SelectedVersionList<VersionMetadata>
  public typealias SelectedVersionForMetadata = VersionMetadata -> SelectedVersion<VersionMetadata>?

  public override init (_ pointer: COpaquePointer, shouldCopy: Bool = true)
  {
    // This omits initialization of the callback variables, which should be okay
    // as it is impossible to set up new behaviors for this ArbiterResolver
    // pointer.
    super.init(pointer, shouldCopy: shouldCopy)
  }

  public convenience init (initialGraph: ResolvedDependencyGraph<ProjectValue, VersionMetadata>?, dependenciesToResolve: DependencyList<ProjectValue>, listDependencies: ListDependencies, listAvailableVersions: ListAvailableVersions, selectedVersionForMetadata: SelectedVersionForMetadata? = nil)
  {
    // This has to be initialized in two steps, because we need a reference to
    // `self` in order to create the ArbiterResolver pointer.
    self.init(nil, shouldCopy: false)

    let behaviors = ArbiterResolverBehaviors(
      createDependencyList: createDependencyListBehavior,
      createAvailableVersionsList: createAvailableVersionsListBehavior,
      createSelectedVersionForMetadata: createSelectedVersionForMetadataBehavior)

    _pointer = ArbiterCreateResolver(behaviors, initialGraph?.pointer ?? nil, dependenciesToResolve.pointer, toUserContext(self))
  }

  private override func createDependencyList (project: COpaquePointer, selectedVersion: COpaquePointer, error: UnsafeMutablePointer<UnsafeMutablePointer<CChar>>) -> COpaquePointer
  {
    do {
      let deps = try listDependencies(self, ProjectIdentifier<ProjectValue>(project, shouldCopy: false), SelectedVersion<VersionMetadata>(selectedVersion, shouldCopy: false))
      return deps.takeOwnership()
    } catch let ex {
      String(ex).withCString { str in
        error.memory = strdup(str)
      }

      return nil
    }
  }

  private override func createAvailableVersionsList (project: COpaquePointer, error: UnsafeMutablePointer<UnsafeMutablePointer<CChar>>) -> COpaquePointer
  {
    do {
      let versions = try listAvailableVersions(self, ProjectIdentifier<ProjectValue>(project, shouldCopy: false))
      return versions.takeOwnership()
    } catch let ex {
      String(ex).withCString { str in
        error.memory = strdup(str)
      }

      return nil
    }
  }

  private override func createSelectedVersionForMetadata (metadata: UnsafePointer<Void>) -> COpaquePointer
  {
    guard let selectedVersionForMetadata = selectedVersionForMetadata else {
      return nil
    }

    if let version = selectedVersionForMetadata(VersionMetadata.fromUserValue(metadata)) {
      return version.takeOwnership()
    } else {
      return nil
    }
  }

  private let listDependencies: ListDependencies! = nil
  private let listAvailableVersions: ListAvailableVersions! = nil
  private let selectedVersionForMetadata: SelectedVersionForMetadata? = nil
}

private func createDependencyListBehavior (resolver: COpaquePointer, project: COpaquePointer, selectedVersion: COpaquePointer, error: UnsafeMutablePointer<UnsafeMutablePointer<CChar>>) -> COpaquePointer
{
  let resolver: ResolverBase = fromUserContext(ArbiterResolverContext(resolver))
  return resolver.createDependencyList(project, selectedVersion: selectedVersion, error: error)
}

private func createAvailableVersionsListBehavior (resolver: COpaquePointer, project: COpaquePointer, error: UnsafeMutablePointer<UnsafeMutablePointer<CChar>>) -> COpaquePointer
{
  let resolver: ResolverBase = fromUserContext(ArbiterResolverContext(resolver))<commit_msg>Actually save closures passed to Resolver initializer<commit_after>public class ResolverBase: CObject {
  private override init (_ pointer: COpaquePointer, shouldCopy: Bool = true)
  {
    super.init(pointer, shouldCopy: shouldCopy)
  }

  private func createDependencyList (project: COpaquePointer, selectedVersion: COpaquePointer, error: UnsafeMutablePointer<UnsafeMutablePointer<CChar>>) -> COpaquePointer
  {
    preconditionFailure("Must be overridden by subclasses")
  }

  private func createAvailableVersionsList (project: COpaquePointer, error: UnsafeMutablePointer<UnsafeMutablePointer<CChar>>) -> COpaquePointer
  {
    preconditionFailure("Must be overridden by subclasses")
  }

  private func createSelectedVersionForMetadata (metadata: UnsafePointer<Void>) -> COpaquePointer
  {
    preconditionFailure("Must be overridden by subclasses")
  }
}

public final class Resolver<ProjectValue: ArbiterValue, VersionMetadata: ArbiterValue> : ResolverBase
{
  public typealias ListDependencies = (Resolver, ProjectIdentifier<ProjectValue>, SelectedVersion<VersionMetadata>) throws -> DependencyList<ProjectValue>
  public typealias ListAvailableVersions = (Resolver, ProjectIdentifier<ProjectValue>) throws -> SelectedVersionList<VersionMetadata>
  public typealias SelectedVersionForMetadata = VersionMetadata -> SelectedVersion<VersionMetadata>?

  public override init (_ pointer: COpaquePointer, shouldCopy: Bool = true)
  {
    // This omits initialization of the callback variables, which should be okay
    // as it is impossible to set up new behaviors for this ArbiterResolver
    // pointer.
    super.init(pointer, shouldCopy: shouldCopy)
  }

  public convenience init (initialGraph: ResolvedDependencyGraph<ProjectValue, VersionMetadata>?, dependenciesToResolve: DependencyList<ProjectValue>, listDependencies: ListDependencies, listAvailableVersions: ListAvailableVersions, selectedVersionForMetadata: SelectedVersionForMetadata? = nil)
  {
    // This has to be initialized in two steps, because we need a reference to
    // `self` in order to create the ArbiterResolver pointer.
    self.init(nil, shouldCopy: false)

    self.listDependencies = listDependencies
    self.listAvailableVersions = listAvailableVersions
    self.selectedVersionForMetadata = selectedVersionForMetadata

    let behaviors = ArbiterResolverBehaviors(
      createDependencyList: createDependencyListBehavior,
      createAvailableVersionsList: createAvailableVersionsListBehavior,
      createSelectedVersionForMetadata: createSelectedVersionForMetadataBehavior)

    _pointer = ArbiterCreateResolver(behaviors, initialGraph?.pointer ?? nil, dependenciesToResolve.pointer, toUserContext(self))
  }

  private override func createDependencyList (project: COpaquePointer, selectedVersion: COpaquePointer, error: UnsafeMutablePointer<UnsafeMutablePointer<CChar>>) -> COpaquePointer
  {
    do {
      let deps = try listDependencies(self, ProjectIdentifier<ProjectValue>(project, shouldCopy: false), SelectedVersion<VersionMetadata>(selectedVersion, shouldCopy: false))
      return deps.takeOwnership()
    } catch let ex {
      String(ex).withCString { str in
        error.memory = strdup(str)
      }

      return nil
    }
  }

  private override func createAvailableVersionsList (project: COpaquePointer, error: UnsafeMutablePointer<UnsafeMutablePointer<CChar>>) -> COpaquePointer
  {
    do {
      let versions = try listAvailableVersions(self, ProjectIdentifier<ProjectValue>(project, shouldCopy: false))
      return versions.takeOwnership()
    } catch let ex {
      String(ex).withCString { str in
        error.memory = strdup(str)
      }

      return nil
    }
  }

  private override func createSelectedVersionForMetadata (metadata: UnsafePointer<Void>) -> COpaquePointer
  {
    guard let selectedVersionForMetadata = selectedVersionForMetadata else {
      return nil
    }

    if let version = selectedVersionForMetadata(VersionMetadata.fromUserValue(metadata)) {
      return version.takeOwnership()
    } else {
      return nil
    }
  }

  private var listDependencies: ListDependencies! = nil
  private var listAvailableVersions: ListAvailableVersions! = nil
  private var selectedVersionForMetadata: SelectedVersionForMetadata? = nil
}

private func createDependencyListBehavior (resolver: COpaquePointer, project: COpaquePointer, selectedVersion: COpaquePointer, error: UnsafeMutablePointer<UnsafeMutablePointer<CChar>>) -> COpaquePointer
{
  let resolver: ResolverBase = fromUserContext(ArbiterResolverContext(resolver))
  return resolver.createDependencyList(project, selectedVersion: selectedVersion, error: error)
}

private func createAvailableVersionsListBehavior (resolver: COpaquePointer, project: COpaquePointer, error: UnsafeMutablePointer<UnsafeMutablePointer<CChar>>) -> COpaquePointer
{
  let resolver: ResolverBase = fromUserContext(ArbiterResolverContext(resolver))
{'fraction_non_alphanumeric': 0.07383527454242929, 'fraction_numerical': 0.0, 'mean_word_length': 5.497972972972973, 'pattern_counts': {'":': 0, '<': 55, '<?xml version=': 0, '>': 77, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4538031', 'n_tokens_mistral': 2535, 'n_tokens_neox': 2447, 'n_words': 629}