Skip to content

Depend on CasePathsCore #370

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 13 additions & 4 deletions Package.resolved

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 7 additions & 3 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -18,25 +18,29 @@ let package = Package(
],
dependencies: [
.package(url: "https://github.com/apple/swift-docc-plugin", from: "1.0.0"),
.package(url: "https://github.com/pointfreeco/swift-case-paths", from: "1.0.0"),
.package(url: "https://github.com/pointfreeco/swift-case-paths", from: "1.6.0"),
.package(url: "https://github.com/google/swift-benchmark", from: "0.1.1"),
],
targets: [
.target(
name: "Parsing",
dependencies: [.product(name: "CasePaths", package: "swift-case-paths")]
dependencies: [
.product(name: "CasePathsCore", package: "swift-case-paths"),
]
),
.testTarget(
name: "ParsingTests",
dependencies: [
"Parsing"
"Parsing",
.product(name: "CasePaths", package: "swift-case-paths")
]
),
.executableTarget(
name: "swift-parsing-benchmark",
dependencies: [
"Parsing",
.product(name: "Benchmark", package: "swift-benchmark"),
.product(name: "CasePaths", package: "swift-case-paths")
]
),
]
Expand Down
60 changes: 36 additions & 24 deletions Sources/Parsing/Conversions/Enum.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import CasePaths
import CasePathsCore

extension Conversion {
/// Converts the associated values of an enum case into the case, and an enum case into its
Expand All @@ -7,12 +7,13 @@ extension Conversion {
/// Useful for transforming the output of a ``ParserPrinter`` into an enum:
///
/// ```swift
/// @CasePathable
/// enum Expression {
/// case add(Int, Int)
/// ...
/// }
///
/// let add = ParsePrint(.case(Expression.add)) {
/// let add = ParsePrint(.case(\Expression.Cases.add)) {
/// Int.parser()
/// "+"
/// Int.parser()
Expand All @@ -29,35 +30,46 @@ extension Conversion {
/// and extract the associated values from the case.
@inlinable
public static func `case`<Values, Enum>(
_ initializer: @escaping (Values) -> Enum
) -> Self where Self == CasePath<Enum, Values> {
/initializer
_ keyPath: CaseKeyPath<Enum, Values>
) -> Self where Self == Conversions.EnumConversion<Enum, Values> {
Self(casePath: AnyCasePath(keyPath))
}

/// A performance-optimized version of ``case(_:)``.
@inlinable
public static func `case`<Enum>(
_ initializer: Enum
) -> Self where Self == CasePath<Enum, Void> {
/initializer
public static func `case`<Values, Enum: CasePathable>(
_ keyPath: KeyPath<Enum.AllCasePaths, AnyCasePath<Enum, Values>>
) -> Self where Self == Conversions.EnumConversion<Enum, Values> {
Self(casePath: Enum.allCasePaths[keyPath: keyPath])
}
}

extension CasePath: Conversion {
@inlinable
public func apply(_ input: Value) -> Root {
self.embed(input)
}
extension Conversions {
public struct EnumConversion<Root, Value>: Conversion {
@usableFromInline
let casePath: AnyCasePath<Root, Value>

@inlinable
public func unapply(_ output: Root) throws -> Value {
guard let value = self.extract(from: output)
else {
throw ConvertingError(
"""
case: Failed to extract \(Value.self) from \(output).
"""
)
@inlinable
init(casePath: AnyCasePath<Root, Value>) {
self.casePath = casePath
}

@inlinable
public func apply(_ input: Value) -> Root {
casePath.embed(input)
}

@inlinable
public func unapply(_ output: Root) throws -> Value {
guard let value = casePath.extract(from: output)
else {
throw ConvertingError(
"""
case: Failed to extract \(Value.self) from \(output).
"""
)
}
return value
}
return value
}
}
Loading
Loading