Implement the Unmarshaler and Marshaler interfaces.

This allows an AtomicBool to be Unmarshalled from the JSON
representation of a normal boolean and respectively marshall
it into the JSON representation of normal booleans.

This makes it easier to use AtomicBool in structs. For they can
now be read from JSON files and serialized back into them.
This commit is contained in:
Lucas Rouckhout 2021-04-28 16:48:48 +02:00
parent f861b8e1c3
commit 9a297a52be
2 changed files with 74 additions and 1 deletions

28
bool.go
View File

@ -2,7 +2,12 @@
// better performance. // better performance.
package abool package abool
import "sync/atomic" import (
"encoding/json"
"errors"
"fmt"
"sync/atomic"
)
// New creates an AtomicBool with default set to false. // New creates an AtomicBool with default set to false.
func New() *AtomicBool { func New() *AtomicBool {
@ -69,3 +74,24 @@ func (ab *AtomicBool) SetToIf(old, new bool) (set bool) {
} }
return atomic.CompareAndSwapInt32((*int32)(ab), o, n) return atomic.CompareAndSwapInt32((*int32)(ab), o, n)
} }
// Marshal an AtomicBool into JSON like a normal bool
func (ab *AtomicBool) MarshalJSON() ([]byte, error) {
return json.Marshal(ab.IsSet())
}
// Unmarshall normal bool's into AtomicBool
func (ab *AtomicBool) UnmarshalJSON(b []byte) error {
var v interface{}
if err := json.Unmarshal(b, &v); err != nil {
return err
}
switch value := v.(type) {
case bool:
ab.SetTo(value)
return nil
default:
return errors.New(fmt.Sprintf("%s is an invalid JSON representation for an AtomicBool\n", b))
}
}

View File

@ -1,6 +1,7 @@
package abool package abool
import ( import (
"encoding/json"
"math" "math"
"sync" "sync"
"sync/atomic" "sync/atomic"
@ -181,6 +182,52 @@ func TestRace(t *testing.T) {
wg.Wait() wg.Wait()
} }
func TestFalseUnmarshall(t *testing.T) {
// Marshall a normal bool into JSON byte slice
b, err := json.Marshal(false)
if err != nil {
t.Error(err)
}
// Create an AtomicBool
v := New()
// Try to unmarshall the JSON byte slice of a
// a normal bool into an AtomicBool
err = v.UnmarshalJSON(b)
if err != nil {
t.Error(err)
}
// Check if our AtomicBool is set to false
if v.IsSet() == true {
t.Errorf("Expected AtomicBool to represent false but IsSet() returns true")
}
}
func TestTrueUnmarshall(t *testing.T) {
// Marshall a normal bool into JSON byte slice
b, err := json.Marshal(true)
if err != nil {
t.Error(err)
}
// Create an AtomicBool
v := New()
// Try to unmarshall the JSON byte slice of a
// a normal bool into an AtomicBool
err = v.UnmarshalJSON(b)
if err != nil {
t.Error(err)
}
// Check if our AtomicBool is set to false
if v.IsSet() == false {
t.Errorf("Expected AtomicBool to represent true but IsSet() returns false. %+v", v)
}
}
func ExampleAtomicBool() { func ExampleAtomicBool() {
cond := New() // default to false cond := New() // default to false
any := true any := true