// // Transformation.swift // LevenshteinTransformations // // Created by david-swift on 01.01.24. // // swiftlint:disable identifier_name /// A transformation (replace, delete or insert). public enum Transformation { /// Replace the element at a certain index with a certain element. case replace(at: Int, with: Element) /// Delete the element at a certain index. case delete(at: Int) /// Insert a certain element at a certain index. case insert(at: Int, element: Element) /// The index at which is directly affected by the transformation. public var index: Int { get { switch self { case let .replace(index, _), let .delete(index), let .insert(index, _): return index } } set { switch self { case let .replace(_, element): self = .replace(at: newValue, with: element) case .delete: self = .delete(at: newValue) case let .insert(_, element): self = .insert(at: newValue, element: element) } } } /// The element which is directly affected by the transformation. public var element: Element? { get { switch self { case let .replace(_, element), let .insert(_, element): return element case .delete: return nil } } set { if let newValue { switch self { case let .replace(index, _): self = .replace(at: index, with: newValue) case let .insert(index, _): self = .insert(at: index, element: newValue) case .delete: break } } } } /// Get the replace transformation for an element, or nil. /// - Parameters: /// - index: The index to replace. /// - element: The new element. public static func replace(at index: Int, with element: Element?) -> Self? { guard let element else { return nil } return .replace(at: index, with: element) } /// Get the insert transformation for an element, or nil. /// - Parameters: /// - index: The index to insert at. /// - element. The new element. /// - Returns: The transformation. public static func insert(at index: Int, element: Element?) -> Self? { guard let element else { return nil } return .insert(at: index, element: element) } /// A description of the transformation. /// - Parameter source: The initial array. /// - Returns: The description. public func description(source: [Element]) -> String { switch self { case let .replace(index, element): return "Replace '\(source[index])' at position \(index) with '\(element)'" case let .delete(index): return "Delete '\(source[index])' at position \(index)" case let .insert(index, element): return "Insert '\(element)' at position \(index)" } } /// Print a description of the transformation. /// - Parameter source: The initial array. public func log(source: [Element]) { print(description(source: source)) } /// Apply the transformation using a functions value. /// - Parameters: /// - functions: The functions value. /// - nextTransformations: All the following transformations for modifying the indices. public func transform(functions: Functions, nextTransformations: inout [Transformation]) { switch self { case let .replace(index, element): functions.replace(index, element) case let .delete(index): functions.delete(index) for index in nextTransformations.indices { nextTransformations[index].index -= 1 } case let .insert(index, element): functions.insert(index, element) for index in nextTransformations.indices { nextTransformations[index].index += 1 } } } /// Apply the transformation using a functions value. /// - Parameters: /// - functions: The functions value. /// - nextTransformations: All the following transformations for modifying the indices. public func transform( functions: AsyncFunctions, nextTransformations: inout [Transformation] ) async { switch self { case let .replace(index, element): await functions.replace(index, element) case let .delete(index): await functions.delete(index) for index in nextTransformations.indices { nextTransformations[index].index -= 1 } case let .insert(index, element): await functions.insert(index, element) for index in nextTransformations.indices { nextTransformations[index].index += 1 } } } /// Convert a series of transformations in order to be able /// to apply the same transformation on different Swift types. /// - Parameter convert: The conversion function. /// - Returns: The transformations. public func convert(convert: (Element) -> NewType?) -> Transformation? { switch self { case let .replace(index, element): return .replace(at: index, with: convert(element)) case let .delete(index): return .delete(at: index) case let .insert(index, element): return .insert(at: index, element: convert(element)) } } } // swiftlint:enable identifier_name