How do I write a function that accepts Array <UInt8> or ArraySlice <UInt8>?

What I'm trying to do is to parse (part of) the binary protocol (MQTT) by writing a function like this:

func readString(bytes: Array<UInt8> OR ArraySlice<UInt8>) -> (string: String?, remainingBytes: ArraySlice<UInt8>?)

      

I know about polymorphism, but I'd rather have one function.

I wrote a function (using generics) that takes Array

or ArraySlice

from UnsignedIntegerType

, but I only want UInt8

. It seems like it's simple, but so far I haven't found a good solution ...

+3


source to share


1 answer


What I'm going to do is, first, forget about the return type and think about what this function should take as its parameter. In particular, think about what Array and Slice have in common, and write a common specifying that. They are both MutableCollectionType and Sliceable . And there is basically nothing else in the world (nothing else that you are likely to use, that is).

Also, you want the element type to be UInt8.

So now just say the general way allows you to say:

func readString<T:MutableCollectionType 
    where T:Sliceable, T.Generator.Element == UInt8>(bytes: T) {
        // ...
}

      

And here's the test:



let arr = [UInt8(1),UInt8(2),UInt8(3)]
readString(arr) // compiles
readString(arr[1...2]) // compiles

      

The good thing about this formulation is that the compiler will check, if possible, that you are calling legal integer types. For example, this compiles because all integers are small and positive:

readString([1,2,3])

      

But this doesn't even compile because the compiler knows that negative integer can't be UInt8:

readString([-1,2,3])

      

+4


source







All Articles