isle/go/cmd/entrypoint/flags.go

94 lines
1.9 KiB
Go

package main
import (
"encoding"
"errors"
"fmt"
"isle/nebula"
"isle/toolkit"
"net"
"net/netip"
"strconv"
"dev.mediocregopher.com/mediocre-go-lib.git/mlog"
)
type textUnmarshaler[T any] interface {
encoding.TextUnmarshaler
*T
}
type textUnmarshalerFlag[T encoding.TextMarshaler, P textUnmarshaler[T]] struct {
V T
}
func (f *textUnmarshalerFlag[T, P]) Set(v string) error {
return P(&(f.V)).UnmarshalText([]byte(v))
}
func (f *textUnmarshalerFlag[T, P]) String() string {
b, err := f.V.MarshalText()
if err != nil {
panic(fmt.Sprintf("calling MarshalText on %#v: %v", f.V, err))
}
return string(b)
}
func (f *textUnmarshalerFlag[T, P]) Type() string { return "string" }
type (
hostNameFlag = textUnmarshalerFlag[nebula.HostName, *nebula.HostName]
ipNetFlag = textUnmarshalerFlag[nebula.IPNet, *nebula.IPNet]
ipFlag = textUnmarshalerFlag[netip.Addr, *netip.Addr]
)
////////////////////////////////////////////////////////////////////////////////
type (
addrFlagStr string
addrFlag = textUnmarshalerFlag[addrFlagStr, *addrFlagStr]
)
func (f addrFlagStr) MarshalText() ([]byte, error) {
return []byte(f), nil
}
func (f *addrFlagStr) UnmarshalText(b []byte) error {
str := string(b)
_, portStr, err := net.SplitHostPort(str)
if err != nil {
return err
}
if _, err := strconv.ParseUint(portStr, 10, 16); err != nil {
return fmt.Errorf("invalid port %q", portStr)
}
*f = addrFlagStr(str)
return nil
}
////////////////////////////////////////////////////////////////////////////////
type logLevelFlag struct {
mlog.Level
}
func (f *logLevelFlag) Set(v string) error {
f.Level = toolkit.LogLevelFromString(v)
if f.Level == nil {
return errors.New("not a valid log level")
}
return nil
}
func (f *logLevelFlag) String() string {
if f.Level == nil {
return "UNKNOWN"
}
return f.Level.String()
}
func (f *logLevelFlag) Type() string { return "string" }