mirror of
https://github.com/ipfs/kubo.git
synced 2026-02-21 18:37:45 +08:00
go-ipfs-config: feat: add flag and priority types
These let us zero-encode "default" to "null" (and omit it with "omitempty") so we don't have to hard code the default in the config.
This commit is contained in:
parent
89e73d989c
commit
dfe53cd5b6
127
config/types.go
127
config/types.go
@ -1,7 +1,9 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"encoding"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"time"
|
||||
)
|
||||
|
||||
@ -41,6 +43,128 @@ func (o Strings) MarshalJSON() ([]byte, error) {
|
||||
var _ json.Unmarshaler = (*Strings)(nil)
|
||||
var _ json.Marshaler = (*Strings)(nil)
|
||||
|
||||
// Flag represents a ternary value: false (-1), default (0), or true (+1).
|
||||
//
|
||||
// When encoded in json, False is "false", Default is "null" (or empty), and True
|
||||
// is "true".
|
||||
type Flag int8
|
||||
|
||||
const (
|
||||
False Flag = -1
|
||||
Default Flag = 0
|
||||
True Flag = 1
|
||||
)
|
||||
|
||||
func (f Flag) MarshalJSON() ([]byte, error) {
|
||||
switch f {
|
||||
case Default:
|
||||
return json.Marshal(nil)
|
||||
case True:
|
||||
return json.Marshal(true)
|
||||
case False:
|
||||
return json.Marshal(false)
|
||||
default:
|
||||
return nil, fmt.Errorf("invalid flag value: %d", f)
|
||||
}
|
||||
}
|
||||
|
||||
func (f *Flag) UnmarshalJSON(input []byte) error {
|
||||
switch string(input) {
|
||||
case "null", "undefined":
|
||||
*f = Default
|
||||
case "false":
|
||||
*f = False
|
||||
case "true":
|
||||
*f = True
|
||||
default:
|
||||
return fmt.Errorf("failed to unmarshal %q into a flag: must be null/undefined, true, or false", string(input))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (f Flag) String() string {
|
||||
switch f {
|
||||
case Default:
|
||||
return "default"
|
||||
case True:
|
||||
return "true"
|
||||
case False:
|
||||
return "false"
|
||||
default:
|
||||
return fmt.Sprintf("<invalid flag value %d>", f)
|
||||
}
|
||||
}
|
||||
|
||||
var _ json.Unmarshaler = (*Flag)(nil)
|
||||
var _ json.Marshaler = (*Flag)(nil)
|
||||
|
||||
// Priority represents a value with a priority where 0 means "default" and -11
|
||||
// means "disabled".
|
||||
//
|
||||
// When encoded in json, Default is encoded as "null" and Disabled is encoded as
|
||||
// "false".
|
||||
type Priority int64
|
||||
|
||||
const (
|
||||
DefaultPriority Priority = 0
|
||||
Disabled Priority = -1
|
||||
)
|
||||
|
||||
func (p Priority) MarshalJSON() ([]byte, error) {
|
||||
// > 0 == Priority
|
||||
if p > 0 {
|
||||
return json.Marshal(int64(p))
|
||||
}
|
||||
// <= 0 == special
|
||||
switch p {
|
||||
case DefaultPriority:
|
||||
return json.Marshal(nil)
|
||||
case Disabled:
|
||||
return json.Marshal(false)
|
||||
default:
|
||||
return nil, fmt.Errorf("invalid priority value: %d", p)
|
||||
}
|
||||
}
|
||||
|
||||
func (p *Priority) UnmarshalJSON(input []byte) error {
|
||||
switch string(input) {
|
||||
case "null", "undefined":
|
||||
*p = DefaultPriority
|
||||
case "false":
|
||||
*p = Disabled
|
||||
case "true":
|
||||
return fmt.Errorf("'true' is not a valid priority")
|
||||
default:
|
||||
var priority int64
|
||||
err := json.Unmarshal(input, &priority)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if priority <= 0 {
|
||||
return fmt.Errorf("priority must be positive: %d <= 0", priority)
|
||||
}
|
||||
*p = Priority(priority)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p Priority) String() string {
|
||||
if p > 0 {
|
||||
return fmt.Sprintf("%d", p)
|
||||
}
|
||||
switch p {
|
||||
case DefaultPriority:
|
||||
return "default"
|
||||
case Disabled:
|
||||
return "false"
|
||||
default:
|
||||
return fmt.Sprintf("<invalid priority %d>", p)
|
||||
}
|
||||
}
|
||||
|
||||
var _ json.Unmarshaler = (*Flag)(nil)
|
||||
var _ json.Marshaler = (*Flag)(nil)
|
||||
|
||||
// Duration wraps time.Duration to provide json serialization and deserialization.
|
||||
//
|
||||
// NOTE: the zero value encodes to an empty string.
|
||||
@ -59,3 +183,6 @@ func (d Duration) MarshalText() ([]byte, error) {
|
||||
func (d Duration) String() string {
|
||||
return time.Duration(d).String()
|
||||
}
|
||||
|
||||
var _ encoding.TextUnmarshaler = (*Duration)(nil)
|
||||
var _ encoding.TextMarshaler = (*Duration)(nil)
|
||||
|
||||
@ -83,3 +83,102 @@ func TestFunkyStrings(t *testing.T) {
|
||||
t.Fatalf("unexpected result: %v", s)
|
||||
}
|
||||
}
|
||||
|
||||
func TestFlag(t *testing.T) {
|
||||
// make sure we have the right zero value.
|
||||
var defaultFlag Flag
|
||||
if defaultFlag != Default {
|
||||
t.Errorf("expected default flag to be %q, got %q", Default, defaultFlag)
|
||||
}
|
||||
|
||||
for jsonStr, goValue := range map[string]Flag{
|
||||
"null": Default,
|
||||
"true": True,
|
||||
"false": False,
|
||||
} {
|
||||
var d Flag
|
||||
err := json.Unmarshal([]byte(jsonStr), &d)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if d != goValue {
|
||||
t.Fatalf("expected %s, got %s", goValue, d)
|
||||
}
|
||||
|
||||
// Reverse
|
||||
out, err := json.Marshal(goValue)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if string(out) != jsonStr {
|
||||
t.Fatalf("expected %s, got %s", jsonStr, string(out))
|
||||
}
|
||||
}
|
||||
|
||||
type Foo struct {
|
||||
F Flag `json:",omitempty"`
|
||||
}
|
||||
out, err := json.Marshal(new(Foo))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
expected := "{}"
|
||||
if string(out) != expected {
|
||||
t.Fatal("expected omitempty to omit the flag")
|
||||
}
|
||||
}
|
||||
|
||||
func TestPriority(t *testing.T) {
|
||||
// make sure we have the right zero value.
|
||||
var defaultPriority Priority
|
||||
if defaultPriority != DefaultPriority {
|
||||
t.Errorf("expected default priority to be %q, got %q", DefaultPriority, defaultPriority)
|
||||
}
|
||||
|
||||
for jsonStr, goValue := range map[string]Priority{
|
||||
"null": DefaultPriority,
|
||||
"false": Disabled,
|
||||
"1": 1,
|
||||
"2": 2,
|
||||
"100": 100,
|
||||
} {
|
||||
var d Priority
|
||||
err := json.Unmarshal([]byte(jsonStr), &d)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if d != goValue {
|
||||
t.Fatalf("expected %s, got %s", goValue, d)
|
||||
}
|
||||
|
||||
// Reverse
|
||||
out, err := json.Marshal(goValue)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if string(out) != jsonStr {
|
||||
t.Fatalf("expected %s, got %s", jsonStr, string(out))
|
||||
}
|
||||
}
|
||||
|
||||
type Foo struct {
|
||||
P Priority `json:",omitempty"`
|
||||
}
|
||||
out, err := json.Marshal(new(Foo))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
expected := "{}"
|
||||
if string(out) != expected {
|
||||
t.Fatal("expected omitempty to omit the flag")
|
||||
}
|
||||
for _, invalid := range []string{
|
||||
"0", "-1", "-2", "1.1", "0.0",
|
||||
} {
|
||||
var p Priority
|
||||
err := json.Unmarshal([]byte(invalid), &p)
|
||||
if err == nil {
|
||||
t.Errorf("expected to fail to decode %s as a priority", invalid)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user