fs: re-implement DumpMode with Bits

This almost 100% backwards compatible. The only difference being that
in the rc options/get output DumpMode will be output as strings
instead of integers. This is a lot more convenient for the user. They
still accept integer inputs though so the fallout from this should be
minimal.
This commit is contained in:
Nick Craig-Wood 2023-10-03 12:56:17 +01:00
parent 75745fcb21
commit 55d10f4d25
2 changed files with 21 additions and 82 deletions

View File

@ -1,12 +1,7 @@
package fs package fs
import (
"fmt"
"strings"
)
// DumpFlags describes the Dump options in force // DumpFlags describes the Dump options in force
type DumpFlags int type DumpFlags = Bits[dumpChoices]
// DumpFlags definitions // DumpFlags definitions
const ( const (
@ -20,80 +15,24 @@ const (
DumpOpenFiles DumpOpenFiles
) )
var dumpFlags = []struct { type dumpChoices struct{}
flag DumpFlags
name string func (dumpChoices) Choices() []BitsChoicesInfo {
}{ return []BitsChoicesInfo{
{DumpHeaders, "headers"}, {uint64(DumpHeaders), "headers"},
{DumpBodies, "bodies"}, {uint64(DumpBodies), "bodies"},
{DumpRequests, "requests"}, {uint64(DumpRequests), "requests"},
{DumpResponses, "responses"}, {uint64(DumpResponses), "responses"},
{DumpAuth, "auth"}, {uint64(DumpAuth), "auth"},
{DumpFilters, "filters"}, {uint64(DumpFilters), "filters"},
{DumpGoRoutines, "goroutines"}, {uint64(DumpGoRoutines), "goroutines"},
{DumpOpenFiles, "openfiles"}, {uint64(DumpOpenFiles), "openfiles"},
}
} }
// DumpFlagsList is a list of dump flags used in the help func (dumpChoices) Type() string {
var DumpFlagsList string
func init() {
// calculate the dump flags list
var out []string
for _, info := range dumpFlags {
out = append(out, info.name)
}
DumpFlagsList = strings.Join(out, ",")
}
// String turns a DumpFlags into a string
func (f DumpFlags) String() string {
var out []string
for _, info := range dumpFlags {
if f&info.flag != 0 {
out = append(out, info.name)
f &^= info.flag
}
}
if f != 0 {
out = append(out, fmt.Sprintf("Unknown-0x%X", int(f)))
}
return strings.Join(out, ",")
}
// Set a DumpFlags as a comma separated list of flags
func (f *DumpFlags) Set(s string) error {
var flags DumpFlags
parts := strings.Split(s, ",")
for _, part := range parts {
found := false
part = strings.ToLower(strings.TrimSpace(part))
if part == "" {
continue
}
for _, info := range dumpFlags {
if part == info.name {
found = true
flags |= info.flag
}
}
if !found {
return fmt.Errorf("unknown dump flag %q", part)
}
}
*f = flags
return nil
}
// Type of the value
func (f DumpFlags) Type() string {
return "DumpFlags" return "DumpFlags"
} }
// UnmarshalJSON makes sure the value can be parsed as a string or integer in JSON // DumpFlagsList is a list of dump flags used in the help
func (f *DumpFlags) UnmarshalJSON(in []byte) error { var DumpFlagsList = DumpHeaders.Help()
return UnmarshalJSONFlag(in, f, func(i int64) error {
*f = (DumpFlags)(i)
return nil
})
}

View File

@ -33,9 +33,9 @@ func TestDumpFlagsSet(t *testing.T) {
{"bodies,headers,auth", DumpBodies | DumpHeaders | DumpAuth, ""}, {"bodies,headers,auth", DumpBodies | DumpHeaders | DumpAuth, ""},
{"bodies,headers,auth", DumpBodies | DumpHeaders | DumpAuth, ""}, {"bodies,headers,auth", DumpBodies | DumpHeaders | DumpAuth, ""},
{"headers,bodies,requests,responses,auth,filters", DumpHeaders | DumpBodies | DumpRequests | DumpResponses | DumpAuth | DumpFilters, ""}, {"headers,bodies,requests,responses,auth,filters", DumpHeaders | DumpBodies | DumpRequests | DumpResponses | DumpAuth | DumpFilters, ""},
{"headers,bodies,unknown,auth", 0, "unknown dump flag \"unknown\""}, {"headers,bodies,unknown,auth", 0, "invalid choice \"unknown\""},
} { } {
f := DumpFlags(-1) f := DumpFlags(0xffffffffffffffff)
initial := f initial := f
err := f.Set(test.in) err := f.Set(test.in)
if err != nil { if err != nil {
@ -72,12 +72,12 @@ func TestDumpFlagsUnmarshallJSON(t *testing.T) {
{`"bodies,headers,auth"`, DumpBodies | DumpHeaders | DumpAuth, ""}, {`"bodies,headers,auth"`, DumpBodies | DumpHeaders | DumpAuth, ""},
{`"bodies,headers,auth"`, DumpBodies | DumpHeaders | DumpAuth, ""}, {`"bodies,headers,auth"`, DumpBodies | DumpHeaders | DumpAuth, ""},
{`"headers,bodies,requests,responses,auth,filters"`, DumpHeaders | DumpBodies | DumpRequests | DumpResponses | DumpAuth | DumpFilters, ""}, {`"headers,bodies,requests,responses,auth,filters"`, DumpHeaders | DumpBodies | DumpRequests | DumpResponses | DumpAuth | DumpFilters, ""},
{`"headers,bodies,unknown,auth"`, 0, "unknown dump flag \"unknown\""}, {`"headers,bodies,unknown,auth"`, 0, "invalid choice \"unknown\""},
{`0`, DumpFlags(0), ""}, {`0`, DumpFlags(0), ""},
{strconv.Itoa(int(DumpBodies)), DumpBodies, ""}, {strconv.Itoa(int(DumpBodies)), DumpBodies, ""},
{strconv.Itoa(int(DumpBodies | DumpHeaders | DumpAuth)), DumpBodies | DumpHeaders | DumpAuth, ""}, {strconv.Itoa(int(DumpBodies | DumpHeaders | DumpAuth)), DumpBodies | DumpHeaders | DumpAuth, ""},
} { } {
f := DumpFlags(-1) f := DumpFlags(0xffffffffffffffff)
initial := f initial := f
err := json.Unmarshal([]byte(test.in), &f) err := json.Unmarshal([]byte(test.in), &f)
if err != nil { if err != nil {