func WithErrorDataType() DefinitionOption {
	return definitionOptionFunc(func(d *definition) {
		d.dataType = errorDataType
	})
}
WithErrorDataType is a convenience function that sets the data type of the event to an error.
package events
import (
	"net"
	"sort"
	"strings"
	pbtypes "github.com/gogo/protobuf/types"
	"go.thethings.network/lorawan-stack/v3/pkg/auth"
	"go.thethings.network/lorawan-stack/v3/pkg/rpcmetadata"
	"go.thethings.network/lorawan-stack/v3/pkg/ttnpb"
	"google.golang.org/grpc/codes"
	"google.golang.org/grpc/peer"
)
type Option interface {
	applyTo(*event)
}
type optionFunc func(e *event)
func (f optionFunc) applyTo(e *event) { f(e) }
func WithIdentifiers(identifiers ...EntityIdentifiers) Option {
	return optionFunc(func(e *event) {
		for _, ids := range identifiers {
			e.innerEvent.Identifiers = append(e.innerEvent.Identifiers, ids.GetEntityIdentifiers())
		}
	})
}
func WithData(data interface{}) Option {
	return optionFunc(func(e *event) {
		e.data = data
		if data, ok := data.(interface{ GetCorrelationIDs() []string }); ok {
			if cids := data.GetCorrelationIDs(); len(cids) > 0 {
				cids = append(cids[:0:0], cids...)
				sort.Strings(cids)
				e.innerEvent.CorrelationIds = mergeStrings(e.innerEvent.CorrelationIds, cids)
			}
		}
		if data, ok := data.(interface{ GetCorrelationIds() []string }); ok {
			if cids := data.GetCorrelationIds(); len(cids) > 0 {
				cids = append(cids[:0:0], cids...)
				sort.Strings(cids)
				e.innerEvent.CorrelationIds = mergeStrings(e.innerEvent.CorrelationIds, cids)
			}
		}
	})
}
func WithVisibility(rights ...ttnpb.Right) Option {
	return optionFunc(func(e *event) {
		e.innerEvent.Visibility = ttnpb.RightsFrom(rights...)
	})
}
func WithAuthFromContext() Option {
	return optionFunc(func(e *event) {
		md := rpcmetadata.FromIncomingContext(e.ctx)
		authentication := &ttnpb.Event_Authentication{}
		if md.AuthType != "" {
			authentication.Type = md.AuthType
		}
		if md.AuthValue != "" {
			if tokenType, tokenID, _, err := auth.SplitToken(md.AuthValue); err == nil {
				authentication.TokenType = tokenType.String()
				authentication.TokenId = tokenID
			}
		}
		if authentication.TokenId != "" || authentication.TokenType != "" || authentication.Type != "" {
			e.innerEvent.Authentication = authentication
		}
	})
}
func WithClientInfoFromContext() Option {
	return optionFunc(func(e *event) {
		if p, ok := peer.FromContext(e.ctx); ok && p.Addr != nil && p.Addr.String() != "pipe" {
			if host, _, err := net.SplitHostPort(p.Addr.String()); err == nil {
				e.innerEvent.RemoteIp = host
			}
		}
		md := rpcmetadata.FromIncomingContext(e.ctx)
		if md.XForwardedFor != "" {
			xff := strings.Split(md.XForwardedFor, ",")
			e.innerEvent.RemoteIp = strings.Trim(xff[0], " ")
		}
		if md := rpcmetadata.FromIncomingContext(e.ctx); md.UserAgent != "" {
			e.innerEvent.UserAgent = md.UserAgent
		}
	})
}
type DefinitionOption interface {
	Option
	applyToDefinition(*definition)
}
type definitionOptionFunc func(d *definition)
func (definitionOptionFunc) applyTo(*event) {}
func (f definitionOptionFunc) applyToDefinition(d *definition) { f(d) }
func WithDataType(t interface{}) DefinitionOption {
	msg, err := marshalData(t)
	if err != nil {
		panic(err)
	}
	return definitionOptionFunc(func(d *definition) {
		d.dataType = msg
	})
}
var errorDataType, _ = marshalData(&ttnpb.ErrorDetails{
	Namespace:     "pkg/example",
	Name:          "example",
	MessageFormat: "example error for `{attr_name}`",
	Attributes: &pbtypes.Struct{
		Fields: map[string]*pbtypes.Value{
			"attr_name": {Kind: &pbtypes.Value_StringValue{
				StringValue: "attr_value",
			}},
		},
	},
	Code: uint32(codes.Unknown),
})