Find the name that was associated to a value of an OptionSet

394 views Asked by At

So I have an OptionSet:

struct Ability: OptionSet {
    let rawValue: Int

    static let create  = Ability(rawValue: 1 << 0)
    static let read    = Ability(rawValue: 1 << 1)
    static let update  = Ability(rawValue: 1 << 2)
    static let delete  = Ability(rawValue: 1 << 3)

    init(rawValue: Int) {
        self.rawValue = rawValue
    }
}

I'm just writing one as an example here. In reality my code doesn't know what OptionSet it has exactly, it only knows it gets an OptionSet. What I want to do is be able to get the name of the option from its rawValue as a String.

So basically I want to write a function with the following signature:

func convertOptionToString<OS: OptionSet>(optionSet: OS) -> String

Where convertOptionToString(Ability.read) would return "read"

Of course I know that OptionSets can also hold multiple values, but I already know how I would deal with that situation, so that's not a problem I need help with.

I am hoping that this problem can be solved using some kind of smart Reflection, but I haven't been able to find out how yet. Anybody want to give it a go?

1

There are 1 answers

5
rmaddy On

Update your struct to conform to CustomStringConvertible and implement the description property:

struct Ability: OptionSet, CustomStringConvertible {
    let rawValue: Int

    static let create  = Ability(rawValue: 1 << 0)
    static let read    = Ability(rawValue: 1 << 1)
    static let update  = Ability(rawValue: 1 << 2)
    static let delete  = Ability(rawValue: 1 << 3)

    init(rawValue: Int) {
        self.rawValue = rawValue
    }

    var description: String {
        var vals = [String]()
        if self.contains(.create) {
            vals.append("create")
        }
        if self.contains(.read) {
            vals.append("read")
        }
        if self.contains(.update) {
            vals.append("update")
        }
        if self.contains(.delete) {
            vals.append("delete")
        }

        return vals.joined(separator: ",")
    }
}

print(Ability.read)
let opts: Ability = [ .read, .delete ]
print(opts)

Output:

read
read,delete