-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #9 from roanutil/feature/sequence-filter
Add SequenceFilter and CollectionFilter
- Loading branch information
Showing
23 changed files
with
1,650 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
// AnyCollectionPredicate.swift | ||
// Filter | ||
// | ||
// | ||
// MIT License | ||
// | ||
// Copyright © 2024 Andrew Roan | ||
|
||
import Foundation | ||
|
||
/// Builds predicates where the output is type-erased of the incoming `Root` and `Value` types. | ||
public protocol AnyCollectionPredicate { | ||
associatedtype Output | ||
/// Builds a predicate of type `Output` for a given property on a root type. | ||
/// - Parameters | ||
/// - filter: CollectionFilter<Value> | ||
/// - keyPath: KeyPath<Root, Value> | ||
/// - Returns | ||
/// - Output | ||
static func build<Root, Value>(from filter: CollectionFilter<Value>, on keyPath: KeyPath<Root, Value>) -> Output | ||
where Value: Collection | ||
} | ||
|
||
extension AnyCollectionPredicate { | ||
/// Builds a predicate of type `Output` for a given `Value` type. | ||
/// - Parameters | ||
/// - filter: CollectionFilter<Value> | ||
/// - Returns | ||
/// - Output | ||
@inlinable | ||
public static func build<Value>(from filter: CollectionFilter<Value>) -> Output where Value: Collection { | ||
build(from: filter, on: \.self) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
// CollectionFilter.swift | ||
// Filter | ||
// | ||
// | ||
// MIT License | ||
// | ||
// Copyright © 2024 Andrew Roan | ||
|
||
import Foundation | ||
|
||
public enum CollectionFilter<S>: Equatable where S: Collection, S: Equatable, S.Element: Equatable { | ||
case isIn(S) | ||
case sequence(SequenceFilter<S>) | ||
indirect case or(Self, Self) | ||
indirect case orMulti([Self]) | ||
indirect case and(Self, Self) | ||
indirect case andMulti([Self]) | ||
indirect case not(Self) | ||
|
||
/// A wrapper for CollectionFilter when comparing an optional type. | ||
public enum Optional: Equatable { | ||
case orNil(CollectionFilter<S>) | ||
case notNil(CollectionFilter<S>?) | ||
case isNil | ||
|
||
/// Returns the wrapped CollectionFilter from `self`. | ||
@inlinable | ||
public var unwrapped: CollectionFilter<S>? { | ||
switch self { | ||
case let .orNil(unwrapped): | ||
return unwrapped | ||
case let .notNil(unwrapped): | ||
return unwrapped | ||
case .isNil: | ||
return nil | ||
} | ||
} | ||
} | ||
|
||
public enum Element: Equatable { | ||
case equatable(EquatableFilter<S.Element>) | ||
} | ||
} | ||
|
||
extension CollectionFilter: Hashable where S: Hashable, S.Element: Hashable {} | ||
|
||
extension CollectionFilter.Optional: Hashable where S: Hashable, S.Element: Hashable {} | ||
|
||
extension CollectionFilter: Sendable where S: Sendable, S.Element: Sendable {} | ||
|
||
extension CollectionFilter.Optional: Sendable where S: Sendable, S.Element: Sendable {} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
// CollectionPredicate.swift | ||
// Filter | ||
// | ||
// | ||
// MIT License | ||
// | ||
// Copyright © 2024 Andrew Roan | ||
|
||
import Foundation | ||
|
||
/// Builds predicates where the output is type constrained by the incoming `Root` and `Value` types. | ||
public protocol CollectionPredicate { | ||
/// The predicate this type builds | ||
associatedtype Output | ||
/// Root type being filtered | ||
associatedtype Root | ||
/// Property type on `Root` being filtered | ||
associatedtype Value: Collection where Value: Equatable, Value.Element: Equatable | ||
|
||
/// Builds a predicate of type `Output` for a given property on a root type. | ||
/// - Parameters | ||
/// - filter: CollectionFilter<Value> | ||
/// - keyPath: KeyPath<Root, Value> | ||
/// - Returns | ||
/// - Output | ||
static func build(from filter: CollectionFilter<Value>, on keyPath: KeyPath<Root, Value>) -> Output | ||
} | ||
|
||
extension CollectionPredicate where Root == Value { | ||
/// Builds a predicate of type `Output` for a given `Value` type. | ||
/// - Parameters | ||
/// - filter: CollectionFilter<Value> | ||
/// - Returns | ||
/// - Output | ||
@inlinable | ||
public static func build(from filter: CollectionFilter<Value>) -> Output { | ||
build(from: filter, on: \.self) | ||
} | ||
} |
33 changes: 33 additions & 0 deletions
33
Sources/Filter/Collection/OptionalAnyCollectionPredicate.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
// OptionalAnyCollectionPredicate.swift | ||
// Filter | ||
// | ||
// | ||
// MIT License | ||
// | ||
// Copyright © 2024 Andrew Roan | ||
|
||
import Foundation | ||
|
||
/// Builds predicates where the output is type-erased of the incoming `Root` and `Value?` types. | ||
public protocol OptionalAnyCollectionPredicate: AnyCollectionPredicate { | ||
/// Builds a predicate of type `Output` for a given property on a root type. | ||
/// - Parameters | ||
/// - filter: CollectionFilter<Value>.Optional | ||
/// - keyPath: KeyPath<Root, Value?> | ||
/// - Returns | ||
/// - Output | ||
static func build<Model, Value>(from filter: CollectionFilter<Value>.Optional, on keyPath: KeyPath<Model, Value?>) | ||
-> Output where Value: Collection | ||
} | ||
|
||
extension OptionalAnyCollectionPredicate { | ||
/// Builds a predicate of type `Output` for a given `Value` type. | ||
/// - Parameters | ||
/// - filter: CollectionFilter<Value>.Optional | ||
/// - Returns | ||
/// - Output | ||
@inlinable | ||
public static func build<Value>(from filter: CollectionFilter<Value>.Optional) -> Output where Value: Collection { | ||
build(from: filter, on: \.self) | ||
} | ||
} |
32 changes: 32 additions & 0 deletions
32
Sources/Filter/Collection/OptionalCollectionPredicate.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
// OptionalCollectionPredicate.swift | ||
// Filter | ||
// | ||
// | ||
// MIT License | ||
// | ||
// Copyright © 2024 Andrew Roan | ||
|
||
import Foundation | ||
|
||
/// Builds predicates where the output is type constrained by the incoming `Root` and `Value?` types. | ||
public protocol OptionalCollectionPredicate: CollectionPredicate { | ||
/// Builds a predicate of type `Output` for a given property on a root type. | ||
/// - Parameters | ||
/// - filter: CollectionFilter<Value>.Optional | ||
/// - keyPath: KeyPath<Root, Value> | ||
/// - Returns | ||
/// - Output | ||
static func build(from filter: CollectionFilter<Value>.Optional, on keyPath: KeyPath<Root, Value?>) -> Output | ||
} | ||
|
||
extension OptionalCollectionPredicate where Root == Value? { | ||
/// Builds a predicate of type `Output` for a given `Value?` type. | ||
/// - Parameters | ||
/// - filter: CollectionFilter<Value>.Optional | ||
/// - Returns | ||
/// - Output | ||
@inlinable | ||
public static func build(from filter: CollectionFilter<Value>.Optional) -> Output { | ||
build(from: filter, on: \.self) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
// AnySequencePredicate.swift | ||
// Filter | ||
// | ||
// | ||
// MIT License | ||
// | ||
// Copyright © 2024 Andrew Roan | ||
|
||
import Foundation | ||
|
||
/// Builds predicates where the output is type-erased of the incoming `Root` and `Value` types. | ||
public protocol AnySequencePredicate { | ||
associatedtype Output | ||
/// Builds a predicate of type `Output` for a given property on a root type. | ||
/// - Parameters | ||
/// - filter: SequenceFilter<Value> | ||
/// - keyPath: KeyPath<Root, Value> | ||
/// - Returns | ||
/// - Output | ||
static func build<Root, Value>(from filter: SequenceFilter<Value>, on keyPath: KeyPath<Root, Value>) -> Output | ||
where Value: Sequence | ||
} | ||
|
||
extension AnySequencePredicate { | ||
/// Builds a predicate of type `Output` for a given `Value` type. | ||
/// - Parameters | ||
/// - filter: SequenceFilter<Value> | ||
/// - Returns | ||
/// - Output | ||
@inlinable | ||
public static func build<Value>(from filter: SequenceFilter<Value>) -> Output where Value: Sequence { | ||
build(from: filter, on: \.self) | ||
} | ||
} |
33 changes: 33 additions & 0 deletions
33
Sources/Filter/Sequence/OptionalAnySequencePredicate.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
// OptionalAnySequencePredicate.swift | ||
// Filter | ||
// | ||
// | ||
// MIT License | ||
// | ||
// Copyright © 2024 Andrew Roan | ||
|
||
import Foundation | ||
|
||
/// Builds predicates where the output is type-erased of the incoming `Root` and `Value?` types. | ||
public protocol OptionalAnySequencePredicate: AnySequencePredicate { | ||
/// Builds a predicate of type `Output` for a given property on a root type. | ||
/// - Parameters | ||
/// - filter: SequenceFilter<Value>.Optional | ||
/// - keyPath: KeyPath<Root, Value?> | ||
/// - Returns | ||
/// - Output | ||
static func build<Model, Value>(from filter: SequenceFilter<Value>.Optional, on keyPath: KeyPath<Model, Value?>) | ||
-> Output where Value: Sequence | ||
} | ||
|
||
extension OptionalAnySequencePredicate { | ||
/// Builds a predicate of type `Output` for a given `Value` type. | ||
/// - Parameters | ||
/// - filter: SequenceFilter<Value>.Optional | ||
/// - Returns | ||
/// - Output | ||
@inlinable | ||
public static func build<Value>(from filter: SequenceFilter<Value>.Optional) -> Output where Value: Sequence { | ||
build(from: filter, on: \.self) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
// OptionalSequencePredicate.swift | ||
// Filter | ||
// | ||
// | ||
// MIT License | ||
// | ||
// Copyright © 2024 Andrew Roan | ||
|
||
import Foundation | ||
|
||
/// Builds predicates where the output is type constrained by the incoming `Root` and `Value?` types. | ||
public protocol OptionalSequencePredicate: SequencePredicate { | ||
/// Builds a predicate of type `Output` for a given property on a root type. | ||
/// - Parameters | ||
/// - filter: SequenceFilter<Value>.Optional | ||
/// - keyPath: KeyPath<Root, Value> | ||
/// - Returns | ||
/// - Output | ||
static func build(from filter: SequenceFilter<Value>.Optional, on keyPath: KeyPath<Root, Value?>) -> Output | ||
} | ||
|
||
extension OptionalSequencePredicate where Root == Value? { | ||
/// Builds a predicate of type `Output` for a given `Value?` type. | ||
/// - Parameters | ||
/// - filter: SequenceFilter<Value>.Optional | ||
/// - Returns | ||
/// - Output | ||
@inlinable | ||
public static func build(from filter: SequenceFilter<Value>.Optional) -> Output { | ||
build(from: filter, on: \.self) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
// SequenceFilter.swift | ||
// Filter | ||
// | ||
// | ||
// MIT License | ||
// | ||
// Copyright © 2024 Andrew Roan | ||
|
||
import Foundation | ||
|
||
public enum SequenceFilter<S>: Equatable where S: Sequence, S: Equatable, S.Element: Equatable { | ||
case contains(S.Element) | ||
indirect case or(Self, Self) | ||
indirect case orMulti([Self]) | ||
indirect case and(Self, Self) | ||
indirect case andMulti([Self]) | ||
indirect case not(Self) | ||
|
||
/// A wrapper for SequenceFilter when comparing an optional type. | ||
public enum Optional: Equatable { | ||
case orNil(SequenceFilter<S>) | ||
case notNil(SequenceFilter<S>?) | ||
case isNil | ||
|
||
/// Returns the wrapped SequenceFilter from `self`. | ||
@inlinable | ||
public var unwrapped: SequenceFilter<S>? { | ||
switch self { | ||
case let .orNil(unwrapped): | ||
return unwrapped | ||
case let .notNil(unwrapped): | ||
return unwrapped | ||
case .isNil: | ||
return nil | ||
} | ||
} | ||
} | ||
} | ||
|
||
extension SequenceFilter: Hashable where S: Hashable, S.Element: Hashable {} | ||
|
||
extension SequenceFilter.Optional: Hashable where S: Hashable, S.Element: Hashable {} | ||
|
||
extension SequenceFilter: Sendable where S: Sendable, S.Element: Sendable {} | ||
|
||
extension SequenceFilter.Optional: Sendable where S: Sendable, S.Element: Sendable {} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
// SequencePredicate.swift | ||
// Filter | ||
// | ||
// | ||
// MIT License | ||
// | ||
// Copyright © 2024 Andrew Roan | ||
|
||
import Foundation | ||
|
||
/// Builds predicates where the output is type constrained by the incoming `Root` and `Value` types. | ||
public protocol SequencePredicate { | ||
/// The predicate this type builds | ||
associatedtype Output | ||
/// Root type being filtered | ||
associatedtype Root | ||
/// Property type on `Root` being filtered | ||
associatedtype Value: Sequence where Value: Equatable, Value.Element: Equatable | ||
|
||
/// Builds a predicate of type `Output` for a given property on a root type. | ||
/// - Parameters | ||
/// - filter: SequenceFilter<Value> | ||
/// - keyPath: KeyPath<Root, Value> | ||
/// - Returns | ||
/// - Output | ||
static func build(from filter: SequenceFilter<Value>, on keyPath: KeyPath<Root, Value>) -> Output | ||
} | ||
|
||
extension SequencePredicate where Root == Value { | ||
/// Builds a predicate of type `Output` for a given `Value` type. | ||
/// - Parameters | ||
/// - filter: SequenceFilter<Value> | ||
/// - Returns | ||
/// - Output | ||
@inlinable | ||
public static func build(from filter: SequenceFilter<Value>) -> Output { | ||
build(from: filter, on: \.self) | ||
} | ||
} |
Oops, something went wrong.