Skip to content

Instantly share code, notes, and snippets.

@bteapot
Created September 6, 2022 08:48
Show Gist options
  • Save bteapot/bf6665998abd5da6d6ee0c8eb31426a5 to your computer and use it in GitHub Desktop.
Save bteapot/bf6665998abd5da6d6ee0c8eb31426a5 to your computer and use it in GitHub Desktop.
Radical solution for detection of emptiness in generic values
// MARK: - EmptinessDetector
internal struct EmptinessDetector<Wrapped> {
let value: Wrapped
init(_ value: Wrapped) {
self.value = value
}
var isEmpty: Bool {
switch self {
case let v as OptionalContainer: return v.isEmpty
case let v as CollectionContainer: return v.isEmpty
case let v as SetAlgebraContainer: return v.isEmpty
default: return false
}
}
}
// MARK: - Optional protocol
internal protocol OptionalProtocol: ExpressibleByNilLiteral {
var isNone: Bool { get }
var isEmpty: Bool { get }
}
// MARK: Optional conformances
extension Optional: OptionalProtocol {
var isNone: Bool {
switch self {
case .none: return true
case .some: return false
}
}
var isEmpty: Bool {
switch self {
case .none: return true
case .some(let v): return EmptinessDetector(v).isEmpty
}
}
}
// MARK: Container protocols
private protocol OptionalContainer {
var isEmpty: Bool { get }
}
private protocol CollectionContainer {
var isEmpty: Bool { get }
}
private protocol SetAlgebraContainer {
var isEmpty: Bool { get }
}
// MARK: Detector conformances
extension EmptinessDetector: OptionalContainer where Wrapped: OptionalProtocol {
var isEmpty: Bool {
return self.value.isEmpty
}
}
extension EmptinessDetector: CollectionContainer where Wrapped: Collection {
var isEmpty: Bool {
return self.value.isEmpty
}
}
extension EmptinessDetector: SetAlgebraContainer where Wrapped: SetAlgebra {
var isEmpty: Bool {
return self.value.isEmpty
}
}
// MARK: Checks
func isItEmpty<T>(_ value: T) {
let isEmpty = EmptinessDetector(value).isEmpty
print("\(isEmpty ? "empty" : "value"), \(T.self), \(value)")
}
let a1: [String]? = nil
let a2: [String]? = []
let a3: [String]? = ["1"]
let a4: [String] = []
let a5: [String] = ["1"]
let d1: [Int]? = nil
let d2: [Int]? = []
let d3: [Int]? = [1]
let d4: [Int] = []
let d5: [Int] = [1]
let e1: String? = nil
let e2: String? = ""
let e3: String? = "2"
let e4: String = ""
let e5: String = "3"
let f1: Int? = nil
let f2: Int? = 4
let f3: Int = 5
let g1: AccessibilityTraits? = nil
let g2: AccessibilityTraits? = []
let g3: AccessibilityTraits? = [.isSelected, .allowsDirectInteraction]
let g4: AccessibilityTraits = []
let g5: AccessibilityTraits = [.isSelected, .allowsDirectInteraction]
isItEmpty(a1)
isItEmpty(a2)
isItEmpty(a3)
isItEmpty(a4)
isItEmpty(a5)
isItEmpty(d1)
isItEmpty(d2)
isItEmpty(d3)
isItEmpty(d4)
isItEmpty(d5)
isItEmpty(e1)
isItEmpty(e2)
isItEmpty(e3)
isItEmpty(e4)
isItEmpty(e5)
isItEmpty(f1)
isItEmpty(f2)
isItEmpty(f3)
isItEmpty(g1)
isItEmpty(g2)
isItEmpty(g3)
isItEmpty(g4)
isItEmpty(g5)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment