Doesn't seem to warrant so much ceremony to me. Variadic generics will make this into one function and it's already usable enough as it is. So any other effort expended would be better spent there.
struct ShippingOptions: OptionSet {
let rawValue: Int
static let (nextDay, secondDay) = Self[]
// this bit is cursed, don't use it
static let (priority, standard) = Self[startingFlagIndex: 3]
}
A thing that makes options; doesn't matter what it is, really.
public extension OptionSet where RawValue: BinaryInteger {
/// Provides two options.
///
///- Parameter startingFlagIndex: shifts 0b11 if > 0
static subscript(startingFlagIndex startingFlagIndex: RawValue = 0) -> (
Self,
Self
) {
( .init(flagIndex: startingFlagIndex),
.init(flagIndex: startingFlagIndex + 1)
)
}
/// Provides three options.
///
///- Parameter startingFlagIndex: shifts 0b111 if > 0
static subscript(startingFlagIndex startingFlagIndex: RawValue = 0) -> (
Self, Self,
Self
) {
Tuple[
Self[startingFlagIndex: startingFlagIndex],
.init(flagIndex: startingFlagIndex + 2)
]
}
/// Provides four options.
///
///- Parameter startingFlagIndex: shifts 0b1111 if > 0
static subscript(startingFlagIndex startingFlagIndex: RawValue = 0) -> (
Self, Self, Self,
Self
) {
Tuple[
Self[startingFlagIndex: startingFlagIndex],
.init(flagIndex: startingFlagIndex + 3)
]
}
/// Provides five options.
///
///- Parameter startingFlagIndex: shifts 0b1_1111 if > 0
static subscript(startingFlagIndex startingFlagIndex: RawValue = 0) -> (
Self, Self, Self, Self,
Self
) {
Tuple[
Self[startingFlagIndex: startingFlagIndex],
.init(flagIndex: startingFlagIndex + 4)
]
}
/// Provides six options.
///
///- Parameter startingFlagIndex: shifts 0b11_1111 if > 0
static subscript(startingFlagIndex startingFlagIndex: RawValue = 0) -> (
Self, Self, Self, Self, Self,
Self
) {
Tuple[
Self[startingFlagIndex: startingFlagIndex],
.init(flagIndex: startingFlagIndex + 5)
]
}
}
// MARK: - private
private extension OptionSet where RawValue: BinaryInteger {
private init(flagIndex: RawValue) {
self.init(rawValue: 1 << flagIndex)
}
}
Tuple
/// A workaround for not being able to extend tuples.
public struct Tuple<Elements> {
// This has utility as struct, rather than just a caseless enum, but instance information is irrelevant to this thread.
}
public extension Tuple {
// MARK: - 2-tuple
/// Create a new tuple with one more element.
static subscript<Element0, Element1, Element2>(
tuple: Elements, element: Element2
) -> (Element0, Element1, Element2)
where Elements == (Element0, Element1) {
(tuple.0, tuple.1, element)
}
// MARK: - 3-tuple
/// Create a new tuple with one more element.
static subscript<Element0, Element1, Element2, Element3>(
tuple: Elements, element: Element3
) -> (Element0, Element1, Element2, Element3)
where Elements == (Element0, Element1, Element2) {
(tuple.0, tuple.1, tuple.2, element)
}
// MARK: - 4-tuple
/// Create a new tuple with one more element.
static subscript<Element0, Element1, Element2, Element3, Element4>(
tuple: Elements, element: Element4
) -> (Element0, Element1, Element2, Element3, Element4)
where Elements == (Element0, Element1, Element2, Element3) {
(tuple.0, tuple.1, tuple.2, tuple.3, element)
}
// MARK: - 5-tuple
/// Create a new tuple with one more element.
static subscript<Element0, Element1, Element2, Element3, Element4, Element5>(
tuple: Elements, element: Element5
) -> (Element0, Element1, Element2, Element3, Element4, Element5)
where Elements == (Element0, Element1, Element2, Element3, Element4) {
(tuple.0, tuple.1, tuple.2, tuple.3, tuple.4, element)
}
}