Skip to content
This repository has been archived by the owner on Mar 9, 2022. It is now read-only.

Commit

Permalink
feat: OptionalString type and UnixFSShardingSizeThreshold (#149)
Browse files Browse the repository at this point in the history
* feat: add OptionalString type
* test: fix OptionalInteger test
* add Internal.UnixFSShardingSizeThreshold as optional string
* test: OptionalString null unmarshal with default
* fix: omitempty UnixFSShardingSizeThreshold

Co-authored-by: Marcin Rataj <lidel@lidel.org>
  • Loading branch information
aschmahmann and lidel committed Oct 28, 2021
1 parent 070b449 commit 58ff619
Show file tree
Hide file tree
Showing 3 changed files with 151 additions and 2 deletions.
3 changes: 2 additions & 1 deletion internal.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
package config

type Internal struct {
Bitswap *InternalBitswap `json:",omitempty"` // This is omitempty since we are expecting to make changes to all subcomponents of Internal
Bitswap *InternalBitswap `json:",omitempty"` // This is omitempty since we are expecting to make changes to all subcomponents of Internal
UnixFSShardingSizeThreshold *OptionalString `json:",omitempty"`
}

type InternalBitswap struct {
Expand Down
52 changes: 52 additions & 0 deletions types.go
Original file line number Diff line number Diff line change
Expand Up @@ -313,3 +313,55 @@ func (p OptionalInteger) String() string {

var _ json.Unmarshaler = (*OptionalInteger)(nil)
var _ json.Marshaler = (*OptionalInteger)(nil)

// OptionalString represents a string that has a default value
//
// When encoded in json, Default is encoded as "null"
type OptionalString struct {
value *string
}

// WithDefault resolves the integer with the given default.
func (p *OptionalString) WithDefault(defaultValue string) (value string) {
if p == nil || p.value == nil {
return defaultValue
}
return *p.value
}

// IsDefault returns if this is a default optional integer
func (p *OptionalString) IsDefault() bool {
return p == nil || p.value == nil
}

func (p OptionalString) MarshalJSON() ([]byte, error) {
if p.value != nil {
return json.Marshal(p.value)
}
return json.Marshal(nil)
}

func (p *OptionalString) UnmarshalJSON(input []byte) error {
switch string(input) {
case "null", "undefined":
*p = OptionalString{}
default:
var value string
err := json.Unmarshal(input, &value)
if err != nil {
return err
}
*p = OptionalString{value: &value}
}
return nil
}

func (p OptionalString) String() string {
if p.value == nil {
return "default"
}
return fmt.Sprintf("%d", p.value)
}

var _ json.Unmarshaler = (*OptionalInteger)(nil)
var _ json.Marshaler = (*OptionalInteger)(nil)
98 changes: 97 additions & 1 deletion types_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -389,10 +389,106 @@ func TestOptionalInteger(t *testing.T) {
for _, invalid := range []string{
"foo", "-1.1", "1.1", "0.0", "[]",
} {
var p Priority
var p OptionalInteger
err := json.Unmarshal([]byte(invalid), &p)
if err == nil {
t.Errorf("expected to fail to decode %s as a priority", invalid)
}
}
}

func TestOptionalString(t *testing.T) {
makeStringPointer := func(v string) *string {
return &v
}

var defaultOptionalString OptionalString
if !defaultOptionalString.IsDefault() {
t.Fatal("should be the default")
}
if val := defaultOptionalString.WithDefault(""); val != "" {
t.Errorf("optional integer should have been empty, got %s", val)
}

if val := defaultOptionalString.WithDefault("foo"); val != "foo" {
t.Errorf("optional integer should have been foo, got %s", val)
}

var filledStr OptionalString
filledStr = OptionalString{value: makeStringPointer("foo")}
if filledStr.IsDefault() {
t.Fatal("should not be the default")
}
if val := filledStr.WithDefault("bar"); val != "foo" {
t.Errorf("optional integer should have been foo, got %s", val)
}

filledStr = OptionalString{value: makeStringPointer("")}
if val := filledStr.WithDefault("foo"); val != "" {
t.Errorf("optional integer should have been 0, got %s", val)
}

for jsonStr, goValue := range map[string]OptionalString{
"null": {},
"\"0\"": {value: makeStringPointer("0")},
`"1"`: {value: makeStringPointer("1")},
`"-1"`: {value: makeStringPointer("-1")},
`"qwerty"`: {value: makeStringPointer("qwerty")},
} {
var d OptionalString
err := json.Unmarshal([]byte(jsonStr), &d)
if err != nil {
t.Fatal(err)
}

if goValue.value == nil && d.value == nil {
} else if goValue.value == nil && d.value != nil {
t.Errorf("expected default, got %s", d)
} else if *d.value != *goValue.value {
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))
}
}

// marshal with omitempty
type Foo struct {
S *OptionalString `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 optional integer")
}
// unmarshal from omitempty output and get default value
var foo2 Foo
if err := json.Unmarshal(out, &foo2); err != nil {
t.Fatalf("%s failed to unmarshall with %s", string(out), err)
}
if s := foo2.S.WithDefault("foo"); s != "foo" {
t.Fatalf("expected default value to be used, got %s", s)
}
if !foo2.S.IsDefault() {
t.Fatal("expected value to be the default")
}

for _, invalid := range []string{
"[]", "{}", "0", "a", "'b'",
} {
var p OptionalString
err := json.Unmarshal([]byte(invalid), &p)
if err == nil {
t.Errorf("expected to fail to decode %s as an optional string", invalid)
}
}
}

0 comments on commit 58ff619

Please sign in to comment.