func TryRaftBroker() VersionGuessOpt {
	return guessOpt{func(cfg *guessCfg) { cfg.listener = rBroker }}
}
TryRaftBroker changes from guessing the version for a classical ZooKeeper
based broker to guessing for a raft based broker (v2.8.0+).

Note that with raft, there can be a TryRaftController attempt as well.
package kversion
import (
	"bytes"
	"fmt"
	"text/tabwriter"
	"github.com/twmb/franz-go/pkg/kmsg"
)
type Versions struct {
	k2v []int16
}
func FromApiVersionsResponse(r *kmsg.ApiVersionsResponse) *Versions {
	var v Versions
	for _, key := range r.ApiKeys {
		v.SetMaxKeyVersion(key.ApiKey, key.MaxVersion)
	}
	return &v
}
func (vs *Versions) HasKey(k int16) bool {
	_, has := vs.LookupMaxKeyVersion(k)
	return has
}
func (vs *Versions) LookupMaxKeyVersion(k int16) (int16, bool) {
	if k < 0 {
		return -1, false
	}
	if int(k) >= len(vs.k2v) {
		return -1, false
	}
	version := vs.k2v[k]
	if version < 0 {
		return -1, false
	}
	return version, true
}
func (vs *Versions) SetMaxKeyVersion(k, v int16) {
	if v < 0 {
		v = -1
	}
	if k < 0 || v < 0 && int(k) >= len(vs.k2v)+1 {
		return
	}
	needLen := int(k) + 1
	for len(vs.k2v) < needLen {
		vs.k2v = append(vs.k2v, -1)
	}
	vs.k2v[k] = v
}
func (vs *Versions) Equal(other *Versions) bool {
	long, short := vs.k2v, other.k2v
	if len(short) > len(long) {
		long, short = short, long
	}
	for i, v := range short {
		if v != long[i] {
			return false
		}
	}
	for _, v := range long[len(short):] {
		if v >= 0 {
			return false
		}
	}
	return true
}
func (vs *Versions) EachMaxKeyVersion(fn func(k, v int16)) {
	for k, v := range vs.k2v {
		if v >= 0 {
			fn(int16(k), v)
		}
	}
}
type VersionGuessOpt interface {
	apply(*guessCfg)
}
type guessOpt struct{ fn func(*guessCfg) }
func (opt guessOpt) apply(cfg *guessCfg) { opt.fn(cfg) }
func SkipKeys(keys ...int16) VersionGuessOpt {
	return guessOpt{func(cfg *guessCfg) { cfg.skipKeys = keys }}
}