I think my cognition for Swift types/protocols/generics has overflowed. I've been using the pattern of extending "an input stream bytes" by doing something like:
extension GeneratorType where Element == UInt8 {
func foobar() {
...
}
}
It's worked in the past for simple stuff. And today I was playing with the following:
protocol Unpackable {
static func unpack(inout input:IndexingGenerator<[UInt8]>) -> Self
}
extension UInt8:Unpackable {
static func unpack(inout input:IndexingGenerator<[UInt8]>) -> UInt8 {
return input.next()!
}
}
extension UInt16:Unpackable {
static func unpack(inout input:IndexingGenerator<[UInt8]>) -> UInt16 {
return UInt16(input.next()!) | (UInt16(input.next()!) << 8)
}
}
Works fine. But if I try to put the two together with something like
extension GeneratorType where Element == UInt8 {
func unpackAll() -> (UInt8, UInt16) {
return (UInt8.unpack(&self), UInt16.unpack(&self))
}
then I get the following error:
Cannot convert value of type 'Self' to expected argument type 'IndexingGenerator<[UInt8]>'
Doesn't an IndexingGenerator conform to GeneratorType? Is its Element not UInt8? Is the error in using IndexingGenerator? I can't specify the argument types as GeneratorType (though I'd really like to be able to).
I'm still waiting for the light bulb to flicker on for Swift types. Some days I really like the language. Other days, I feel like I'm yelling at my dog trying to get him to come, and he just stares at me without moving, then turns and chases down the street anyway.
Try this:
extension GeneratorType where Element == UInt8 {
func unpackAll() -> (UInt8, UInt16)? {
guard let _self = self as? IndexingGenerator<[Element]> else { return nil }
var vSelf = _self
return (UInt8.unpack(&vSelf), UInt16.unpack(&vSelf))
}
}
Update:
protocol Unpackable {
static func unpack<T : GeneratorType where T.Element == UInt8>(inout input:T) -> Self
}
extension UInt8: Unpackable {
static func unpack<T : GeneratorType where T.Element == UInt8>(inout input: T) -> UInt8 {
return input.next()!
}
}
extension UInt16: Unpackable {
static func unpack<T : GeneratorType where T.Element == UInt8>(inout input: T) -> UInt16 {
return UInt16(input.next()!) | (UInt16(input.next()!) << 8)
}
}
extension GeneratorType where Element == UInt8 {
mutating func unpackAll() -> (UInt8, UInt16) {
return (UInt8.unpack(&self), UInt16.unpack(&self))
}
}