Can I have my cake and share it too with extensions?


(Travis Griggs) #1

In my own project, I add some extensions to Data and other objects to make building/parsing Data objects easier. Amongst others, I have extensions like this:

func += (data:inout Data, string:String) {
  data.append(string.data(using: .utf8)!)
}

func += (data:inout Data, convertible:DataConvertible) {
  data.append(convertible.data)
}

I use it widely.

But I’ve also been incorporated a small single file MQTT implementation (LightMQTT) that is shared as an ad hoc component with others. I’ve been trying to simplify the implementation of LightMQTT to use a similar technique, but the way things encode themselves is a little different (e.g. a string puts a 2 byte big endian count before itself, etc). Naively, I had added extensions like such:

protocol MQTTDataAppendable {
    static func += (data:inout Data, appendee:Self)
}

extension UInt8:MQTTDataAppendable {
    static func += (data:inout Data, appendee:UInt8) {
        data.append(appendee)
    }
}

extension UInt16:MQTTDataAppendable {
    static func += (data:inout Data, appendee:UInt16) {
        data += UInt8((appendee & 0xFF00) >> 8)
        data += UInt8(appendee & 0xFF)
    }
}

extension String:MQTTDataAppendable {
    // http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.html#_Toc398718016
    static func += (data:inout Data, appendee:String) {
        data += UInt16(appendee.utf8.count)
        data.append(appendee.data(using: .utf8)!)
    }
}

So in the same code space, when I tried then use expressions like:

packet += “MQTT”

The compiler gets cornfuzzled because there’s of course ambiguous resolution of +=. I get why this is. The question I guess is can I pull this off (regardless of whether its a good idea or not, because I suspect it may not be, but I still want to know). I toyed with sprinkling fileprivate in front of those extensions, but it didn’t like the way I did it.

I could just make a Packet struct that wraps a Data struct I think, and that would keep the two from colliding. Curious what other solutions (good or bad) would allow the overloaded operator extensions to be disambiguated?