Implementation of Collection Versions of Zip

Here's the current implementation of index(before:):

extension ZipLongest2Collection: BidirectionalCollection, RandomAccessCollection where
    Collection1: RandomAccessCollection, Collection2: RandomAccessCollection {
  @inlinable public func index (before index: Index) -> Index {
    switch (index.index1, index.index2) {
      case (collection1.startIndex, collection2.startIndex):
        preconditionFailure("Can't decrement beyond startIndex")

      case (let index1, collection2.endIndex) where
          collection1.distance(from: collection1.startIndex, to: index1) >
          collection2.distance(from: collection2.startIndex, to: collection2.endIndex):
        return Index(collection1.index(before: index1), collection2.endIndex)

      case (collection1.endIndex, let index2) where
          collection2.distance(from: collection2.startIndex, to: index2) >
          collection1.distance(from: collection1.startIndex, to: collection1.endIndex):
        return Index(collection1.endIndex, collection2.index(before: index2))

      case (collection1.startIndex, _), (_, collection2.startIndex):
        preconditionFailure("Can't decrement beyond startIndex")

      case let (index1, index2):
        return Index(collection1.index(before: index1), collection2.index(before: index2))
    }
  }
}

To answer your question:

typealias Index = ZipLongest2Collection<[Int], [Int]>.Index

let xs = zipLongest([Int](), [0, 1]) // (Or zip(longest:_:), still undecided.)

assert(xs.endIndex == Index(0, 2))
assert(xs.index(before: xs.endIndex) == Index(0, 1))
assert(xs.index(before: xs.index(before: xs.endIndex)) == xs.startIndex)

I'll post a repo containing a Swift package with the implementation and unit tests later today so people can follow along and play with (and poke holes in) it.