Skip to content

Instantly share code, notes, and snippets.

@HevaWu
Last active August 20, 2021 04:02
Show Gist options
  • Save HevaWu/40bad4ca94beb7a2a60e8c1f98c6470a to your computer and use it in GitHub Desktop.
Save HevaWu/40bad4ca94beb7a2a60e8c1f98c6470a to your computer and use it in GitHub Desktop.
Swift Option Compare: OptionSet vs Enum vs Struct
func log(_ category: LCategory) {
print(category.description)
}
log(.categoryA)
log([.categoryB, .categoryA])
log([.categoryA, .categoryB])
struct LCategory: OptionSet, CustomStringConvertible {
let rawValue: Int
static let categoryA = LCategory(rawValue: 1 << 0)
static let categoryB = LCategory(rawValue: 1 << 1)
static let categoryC = LCategory(rawValue: 1 << 2)
static let categoryD = LCategory(rawValue: 1 << 3)
static let categoryE = LCategory(rawValue: 1 << 4)
static var descriptionMap: [Int: String] = [
LCategory.categoryA.rawValue: "categoryA",
LCategory.categoryB.rawValue: "categoryB",
LCategory.categoryC.rawValue: "categoryC",
LCategory.categoryD.rawValue: "categoryD",
LCategory.categoryE.rawValue: "categoryE",
]
var description: String {
var valList = [String]()
for k in getOptionList() {
if let val = Self.descriptionMap[k] {
valList.append(val)
} else {
assertionFailure("LCategory descriptionMap not contains key \(k)")
}
}
var str = String("[")
str.append(contentsOf: valList.joined(separator: "]["))
str.append("]")
return str
}
func getOptionList() -> [Int] {
var list = [Int]()
let largest = rawValue.bitWidth - rawValue.leadingZeroBitCount
for i in 0..<largest {
if rawValue & (1 << i) != 0 {
list.append(1 << i)
}
}
return list
}
}
extension LCategory {
static let categoryZ = LCategory(rawValue: 1 << 25)
}
LCategory.descriptionMap[LCategory.categoryZ.rawValue] = "categoryZ"
log([.categoryZ, .categoryA, .categoryB])
// ========= LCategoryType protocol ==============================================
protocol LCategoryType: OptionSet, CustomStringConvertible {
var rawValue: Int { get set }
static var descriptionMap: [Int: String] { get set }
}
extension LCategoryType {
var description: String {
var valList = [String]()
for k in getOptionList() {
if let val = Self.descriptionMap[k] {
valList.append(val)
} else {
assertionFailure("LCategory descriptionMap not contains key \(k)")
}
}
var str = String("[")
str.append(contentsOf: valList.joined(separator: "]["))
str.append("]")
return str
}
func getOptionList() -> [Int] {
var list = [Int]()
let largest = rawValue.bitWidth - rawValue.leadingZeroBitCount
for i in 0..<largest {
if rawValue & (1 << i) != 0 {
list.append(1 << i)
}
}
return list
}
}
struct LCategoryTest: LCategoryType {
var rawValue: Int
static let categoryA = LCategoryTest(rawValue: 1 << 0)
static let categoryB = LCategoryTest(rawValue: 1 << 1)
static var descriptionMap: [Int : String] = [
LCategoryTest.categoryA.rawValue: "categoryA",
LCategoryTest.categoryB.rawValue: "categoryB"
]
}
func log(_ category: LCategoryType) {
print(category.description)
}
// ========= LCategoryType protocol Others ================================
//protocol LCategory: CustomStringConvertible {
// associatedtype T: CustomStringConvertible
// var type: T { get set }
//}
//
//extension LCategory {
// var description: String {
// return type.description
// }
//}
//class LCategoryType: OptionSet {
//
// let rawValue: Int
//
// required init(rawValue: Int) {
// self.rawValue = rawValue
// }
//
// func getDescriptionMap() -> [Int: String] {
// fatalError("Must implement getDescriptionMap function in sub-class")
// }
//
// func getDescription() -> String {
// fatalError("Must implement getDescription function in sub-class")
// }
//
// func getOptionList() -> [Int] {
// var list = [Int]()
// let largest = rawValue.bitWidth - rawValue.leadingZeroBitCount
// for i in 0..<largest {
// if rawValue & (1 << i) != 0 {
// list.append(1 << i)
// }
// }
// return list
// }
//
//}
//class LCategoryModule: LCategoryType {
//
// static let categoryA = LCategoryModule(rawValue: 1 << 0)
// static let categoryB = LCategoryModule(rawValue: 1 << 1)
// static let categoryC = LCategoryModule(rawValue: 1 << 2)
// static let categoryD = LCategoryModule(rawValue: 1 << 3)
// static let categoryE = LCategoryModule(rawValue: 1 << 4)
//
// required init(rawValue: Int) {
// super.init(rawValue: rawValue)
// }
//
// override func getDescriptionMap() -> [Int: String] {
//
// return [
// LCategoryModule.categoryA.rawValue: "categoryA",
// LCategoryModule.categoryB.rawValue: "categoryB",
// LCategoryModule.categoryC.rawValue: "categoryC",
// LCategoryModule.categoryD.rawValue: "categoryD",
// LCategoryModule.categoryE.rawValue: "categoryE",
// ]
// }
//
// override func getDescription() -> String {
// var valList = [String]()
// let map = getDescriptionMap()
// for k in getOptionList() {
// if let val = map[k] {
// valList.append(val)
// } else {
// assertionFailure("LCategory descriptionMap not contains key \(k)")
// }
// }
// var str = String("[")
// str.append(contentsOf: valList.joined(separator: "]["))
// str.append("]")
// return str
// }
//}
//
////extension LCategory {
//// static let categoryZ = LCSLoggerCategory(rawValue: 1 << 26)
////}
//
//let d: LCategoryType = [LCategoryModule.categoryA, LCategoryModule.categoryZ]
//print(d.description)
// ========= Enum ==============================================
enum LCategory: String {
case categoryA
case categoryB
case categoryC
}
extension LCategory {
case categoryD
}
// ========= struct ==============================================
struct LCategory: CustomStringConvertible {
private let typeList: [LCategoryType]
init(_ category: LCategoryType) {
typeList = [category]
}
init(_ cateogories: [LCategoryType]) {
typeList = cateogories
}
var description: String {
let sortedList = typeList.sorted().map { $0.rawValue }
var str = String()
str.append("[")
str.append(sortedList.joined(separator: "]["))
str.append("]")
return str
}
}
struct LCategoryType {
let rawValue: String
static let categoryA = LCategoryType(rawValue: "categoryA")
static let categoryB = LCategoryType(rawValue: "categoryB")
static let categoryC = LCategoryType(rawValue: "categoryC")
static let categoryD = LCategoryType(rawValue: "categoryD")
}
extension LCategoryType: Comparable {
static func < (lhs: LCategoryType, rhs: LCategoryType) -> Bool {
return lhs.rawValue < rhs.rawValue
}
}
extension LCategoryType {
static let categoryF = LCategoryType(rawValue: "categoryF")
}
func log(category: LCategory) {
print(category.description)
}
log(category: .init([.categoryF, .categoryA, .categoryB]))
log(category: .init(.categoryA))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment