From 69be6e3beeb3d56a88a3ce02367c17b2bf55c919 Mon Sep 17 00:00:00 2001 From: Pavel Merzlyakov Date: Sat, 8 Oct 2022 00:52:06 +0300 Subject: [PATCH] json marshalling added. change package interface --- json.go | 33 ++++++++++++++ json_test.go | 105 +++++++++++++++++++++++++++++++++++++++++++++ sql.go | 2 +- versioning.go | 31 +++++-------- versioning_test.go | 4 +- 5 files changed, 152 insertions(+), 23 deletions(-) create mode 100644 json.go create mode 100644 json_test.go diff --git a/json.go b/json.go new file mode 100644 index 0000000..562b012 --- /dev/null +++ b/json.go @@ -0,0 +1,33 @@ +package versioning + +import "encoding/json" + +func (v *Version) UnmarshalJSON(data []byte) error { + // try parse from string + if data[0] == '"' { + tmp, err := ParseVersion(string(data[1 : len(data)-1])) + if err != nil { + return err + } + + *v = tmp + return nil + } + + var code uint32 + if err := json.Unmarshal(data, &code); err != nil { + return err + } + + tmp, err := ParseVersionFromCode(code) + if err != nil { + return err + } + + *v = tmp + return nil +} + +func (v Version) MarshalJSON() ([]byte, error) { + return json.Marshal(v.String()) +} diff --git a/json_test.go b/json_test.go new file mode 100644 index 0000000..3be80c7 --- /dev/null +++ b/json_test.go @@ -0,0 +1,105 @@ +package versioning_test + +import ( + "encoding/json" + "testing" + + "github.com/stretchr/testify/require" + + "git.bit5.ru/backend/versioning" +) + +type structWithVersion struct { + Version versioning.Version `json:"v"` +} + +func TestMarshalJSON(t *testing.T) { + cases := []struct { + version structWithVersion + expectedJson string + }{ + { + version: structWithVersion{versioning.MustParseVersion("")}, + expectedJson: `{"v":"0.0.0"}`, + }, + + { + version: structWithVersion{versioning.MustParseVersion("10")}, + expectedJson: `{"v":"10.0.0"}`, + }, + + { + version: structWithVersion{versioning.MustParseVersion("11.2")}, + expectedJson: `{"v":"11.2.0"}`, + }, + + { + version: structWithVersion{versioning.MustParseVersion("11.2.33")}, + expectedJson: `{"v":"11.2.33"}`, + }, + } + + for i, c := range cases { + caseNum := i + 1 + + actualJson, err := json.Marshal(c.version) + require.NoError(t, err, "case #%d", caseNum) + require.EqualValues(t, []byte(c.expectedJson), actualJson, "case #%d", caseNum) + } +} + +func TestUnmarshalJSON(t *testing.T) { + cases := []struct { + versionJson string + expectedVal structWithVersion + }{ + { + versionJson: `{"v":"0.0.0"}`, + expectedVal: structWithVersion{versioning.MustParseVersion("")}, + }, + + { + versionJson: `{"v":"0.0.1"}`, + expectedVal: structWithVersion{versioning.MustParseVersion("0.0.1")}, + }, + + { + versionJson: `{"v":"0.1"}`, + expectedVal: structWithVersion{versioning.MustParseVersion("0.1.0")}, + }, + + { + versionJson: `{"v":"1"}`, + expectedVal: structWithVersion{versioning.MustParseVersion("1.0.0")}, + }, + + { + versionJson: `{"v":0}`, + expectedVal: structWithVersion{versioning.MustParseVersion("0.0.0")}, + }, + + { + versionJson: `{"v":99}`, + expectedVal: structWithVersion{versioning.MustParseVersion("0.0.99")}, + }, + + { + versionJson: `{"v":88899}`, + expectedVal: structWithVersion{versioning.MustParseVersion("0.888.99")}, + }, + + { + versionJson: `{"v":7788899}`, + expectedVal: structWithVersion{versioning.MustParseVersion("77.888.99")}, + }, + } + + for i, c := range cases { + caseNum := i + 1 + + var actualVal structWithVersion + err := json.Unmarshal([]byte(c.versionJson), &actualVal) + require.NoError(t, err, "case #%d", caseNum) + require.EqualValues(t, c.expectedVal, actualVal, "case #%d", caseNum) + } +} diff --git a/sql.go b/sql.go index 35d234c..4c596b2 100644 --- a/sql.go +++ b/sql.go @@ -25,7 +25,7 @@ func (v *Version) Scan(value interface{}) error { return errors.Errorf("incompatible version code type - %T", value) } - parsed, err := ParseFromCode(code) + parsed, err := ParseVersionFromCode(code) if err != nil { return err } diff --git a/versioning.go b/versioning.go index 242ede6..c65ec20 100644 --- a/versioning.go +++ b/versioning.go @@ -16,13 +16,6 @@ const ( var maxVersion = newVersion(MaxMajor, MaxMinor, MaxPatch) -type Layout uint8 - -const ( - Full Layout = iota - WithoutPatch -) - type Version struct { major uint16 minor uint16 @@ -31,17 +24,7 @@ type Version struct { } func (v Version) String() string { - return v.Format(Full) -} - -func (v Version) Format(l Layout) string { - switch l { - default: - return fmt.Sprintf("%d.%d.%d", v.major, v.minor, v.patch) - - case WithoutPatch: - return fmt.Sprintf("%d.%d", v.major, v.minor) - } + return fmt.Sprintf("%d.%d.%d", v.major, v.minor, v.patch) } func (v Version) Code() uint32 { @@ -52,7 +35,7 @@ func (a Version) Less(b Version) bool { return a.Code() < b.Code() } -func Parse(str string) (Version, error) { +func ParseVersion(str string) (Version, error) { parts := strings.Split(str, ".") partsLen := len(parts) if partsLen > 3 { @@ -87,7 +70,15 @@ func Parse(str string) (Version, error) { return newVersion(maj, min, patch), nil } -func ParseFromCode(code uint32) (Version, error) { +func MustParseVersion(str string) Version { + v, err := ParseVersion(str) + if err != nil { + return Version{} + } + return v +} + +func ParseVersionFromCode(code uint32) (Version, error) { patch := code % 100 minor := code%100000 - patch major := code - minor - patch diff --git a/versioning_test.go b/versioning_test.go index fad80f1..6b4d0fe 100644 --- a/versioning_test.go +++ b/versioning_test.go @@ -74,7 +74,7 @@ func TestParse(t *testing.T) { for i, c := range cases { caseNum := i + 1 - v, err := versioning.Parse(c.versionStr) + v, err := versioning.ParseVersion(c.versionStr) if !c.valid { require.Error(t, err, "case#%d", caseNum) @@ -129,7 +129,7 @@ func TestParseFromCode(t *testing.T) { for i, c := range cases { caseNum := i + 1 - v, err := versioning.ParseFromCode(c.code) + v, err := versioning.ParseVersionFromCode(c.code) if !c.valid { require.Error(t, err, "case#%d", caseNum)