func RegisterProvider(p ttnpb.ApplicationPubSub_Provider, implementation Provider) {
	t := reflect.TypeOf(p)
	if _, ok := providers[t]; ok {
		panic(errAlreadyRegistered.WithAttributes("provider_id", fmt.Sprintf("%T", p)))
	}
	providers[t] = implementation
}
RegisterProvider registers an implementation for a given pub/sub provider.
package provider
import (
	"context"
	"fmt"
	"reflect"
	"go.thethings.network/lorawan-stack/v3/pkg/errors"
	"go.thethings.network/lorawan-stack/v3/pkg/ttnpb"
)
type Topics interface {
	GetBaseTopic() string
	GetUplinkMessage() *ttnpb.ApplicationPubSub_Message
	GetJoinAccept() *ttnpb.ApplicationPubSub_Message
	GetDownlinkAck() *ttnpb.ApplicationPubSub_Message
	GetDownlinkNack() *ttnpb.ApplicationPubSub_Message
	GetDownlinkSent() *ttnpb.ApplicationPubSub_Message
	GetDownlinkFailed() *ttnpb.ApplicationPubSub_Message
	GetDownlinkQueued() *ttnpb.ApplicationPubSub_Message
	GetDownlinkQueueInvalidated() *ttnpb.ApplicationPubSub_Message
	GetLocationSolved() *ttnpb.ApplicationPubSub_Message
	GetServiceData() *ttnpb.ApplicationPubSub_Message
	GetDownlinkPush() *ttnpb.ApplicationPubSub_Message
	GetDownlinkReplace() *ttnpb.ApplicationPubSub_Message
}
type Target interface {
	Topics
	GetProvider() ttnpb.ApplicationPubSub_Provider
}
type Enabler interface {
	Enabled(ctx context.Context, provider ttnpb.ApplicationPubSub_Provider) error
}
type Provider interface {
	OpenConnection(ctx context.Context, target Target, enabler Enabler) (*Connection, error)
}
var (
	errNotImplemented    = errors.DefineUnimplemented("provider_not_implemented", "provider `{provider_id}` is not implemented")
	errAlreadyRegistered = errors.DefineAlreadyExists("provider_already_registered", "provider `{provider_id}` already registered")
	providers = map[reflect.Type]Provider{}
)