I don't understand your "explicit overrides", but
already works. But because of the need for manual forwarding, I don't think it's as good as my solution above.
To get rid of the manual forwarding, I don't think a special-case macro is a good idea. I understand people are excited to play with macros, but to improve OptionSet
, they probably should be working on more generalized forwarding via static subscripts with dynamicMember
instead.
struct ShippingOptions: OptionSet {
private enum Option: BitFlag<RawValue> {
case nextDay, secondDay
// this bit is cursed, don't use it
case priority = 3, standard
}
static let nextDay = Self(Option.nextDay)
static let secondDay = Self(Option.secondDay)
static let priority = Self(Option.priority)
static let standard = Self(Option.standard)
let rawValue: Int
}
public extension OptionSet {
init(_ option: some RawRepresentable<some RawRepresentable<RawValue>>) {
self.init(rawValue: option.rawValue.rawValue)
}
}
BitFlag
/// A representation of a single bit "flag".
public struct BitFlag<RawValue: BinaryInteger & _ExpressibleByBuiltinIntegerLiteral> {
public let rawValue: RawValue
public init?(rawValue: RawValue) {
guard
rawValue != 0,
rawValue & (rawValue - 1) == 0
else { return nil }
self.rawValue = rawValue
}
}
// MARK: - Equatable
extension BitFlag: Equatable { }
// MARK: - ExpressibleByIntegerLiteral
extension BitFlag: ExpressibleByIntegerLiteral {
public init(integerLiteral flagIndex: RawValue) {
self.init(rawValue: 1 << flagIndex)!
}
}
// MARK: - RawRepresentable
extension BitFlag: RawRepresentable { }