Convert [UInt8] to Int

We can generalize @eskimo's solution a bit if we want (perhaps too much) to work with any iterator or collection of UInt8 and any FixedWidthInteger type:

extension FixedWidthInteger {
  init<I>(littleEndianBytes iterator: inout I)
  where I: IteratorProtocol, I.Element == UInt8 {
    self = stride(from: 0, to: Self.bitWidth, by: 8).reduce(into: 0) {
      $0 |= Self(truncatingIfNeeded: iterator.next()!) &<< $1
    }
  }
  
  init<C>(littleEndianBytes bytes: C) where C: Collection, C.Element == UInt8 {
    precondition(bytes.count == (Self.bitWidth+7)/8)
    var iter = bytes.makeIterator()
    self.init(littleEndianBytes: &iter)
  }
}

Even in this ridiculous generality, Swift generates basically optimal code with optimization enabled, which I think is pretty cool:

func foo(_ bytes: [UInt8]) -> UInt32 {
    return UInt32(littleEndianBytes: bytes)
}

output.foo([Swift.UInt8]) -> Swift.UInt32:
        push    rbp                         // setup stack frame
        mov     rbp, rsp
        cmp     qword ptr [rdi + 16], 4     // check count == 4
        jne     .LBB6_1
        mov     eax, dword ptr [rdi + 32]   // 4-byte load from array
        pop     rbp                         // tear down stack frame
        ret
.LBB6_1:
        ud2                                 // trap if count != 4
45 Likes