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" }