Repository: Masterminds/semver
Pull request #173 (2022-05-28 21:00:22)

Implement encoding.TextMarshaler and encoding.TextUnmarshaler
This PR implements encoding.TextMarshaler and encoding.TextUnmarshaler for `semver.Version`.

This now allows marshalling and unmarshalling yaml, which was tested using three different yaml libraries.


Patch:
diff --git a/version.go b/version.go
index 4283d39..baecfcd 100644
--- a/version.go
+++ b/version.go
@@ -55,8 +55,10 @@ func init() {
 	versionRegex = regexp.MustCompile("^" + semVerRegex + "$")
 }
 
-const num string = "0123456789"
-const allowed string = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-" + num
+const (
+	num     string = "0123456789"
+	allowed string = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-" + num
+)
 
 // StrictNewVersion parses a given version and returns an instance of Version or
 // an error if unable to parse the version. Only parses valid semantic versions.
@@ -267,7 +269,6 @@ func (v Version) Metadata() string {
 
 // originalVPrefix returns the original 'v' prefix if any.
 func (v Version) originalVPrefix() string {
-
 	// Note, only lowercase v is supported as a prefix by the parser.
 	if v.original != "" && v.original[:1] == "v" {
 		return v.original[:1]
@@ -436,6 +437,23 @@ func (v Version) MarshalJSON() ([]byte, error) {
 	return json.Marshal(v.String())
 }
 
+// UnmarshalText implements the encoding.TextUnmarshaler interface.
+func (v *Version) UnmarshalText(text []byte) error {
+	temp, err := NewVersion(string(text))
+	if err != nil {
+		return err
+	}
+
+	*v = *temp
+
+	return nil
+}
+
+// MarshalText implements the encoding.TextMarshaler interface.
+func (v Version) MarshalText() ([]byte, error) {
+	return []byte(v.String()), nil
+}
+
 // Scan implements the SQL.Scanner interface.
 func (v *Version) Scan(value interface{}) error {
 	var s string
@@ -470,7 +488,6 @@ func compareSegment(v, o uint64) int {
 }
 
 func comparePrerelease(v, o string) int {
-
 	// split the prelease versions by their part. The separator, per the spec,
 	// is a .
 	sparts := strings.Split(v, ".")
@@ -562,7 +579,6 @@ func comparePrePart(s, o string) int {
 		return 1
 	}
 	return -1
-
 }
 
 // Like strings.ContainsAny but does an only instead of any.


Test patch:
diff --git a/version_test.go b/version_test.go
index 0f690f4..6a80b28 100644
--- a/version_test.go
+++ b/version_test.go
@@ -542,6 +542,42 @@ func TestJsonUnmarshal(t *testing.T) {
 	}
 }
 
+func TestTextMarshal(t *testing.T) {
+	sVer := "1.1.1"
+
+	x, err := StrictNewVersion(sVer)
+	if err != nil {
+		t.Errorf("Error creating version: %s", err)
+	}
+
+	out, err2 := x.MarshalText()
+	if err2 != nil {
+		t.Errorf("Error marshaling version: %s", err2)
+	}
+
+	got := string(out)
+	want := sVer
+	if got != want {
+		t.Errorf("Error marshaling unexpected marshaled content: got=%q want=%q", got, want)
+	}
+}
+
+func TestTextUnmarshal(t *testing.T) {
+	sVer := "1.1.1"
+	ver := &Version{}
+
+	err := ver.UnmarshalText([]byte(sVer))
+	if err != nil {
+		t.Errorf("Error unmarshaling version: %s", err)
+	}
+
+	got := ver.String()
+	want := sVer
+	if got != want {
+		t.Errorf("Error unmarshaling unexpected object content: got=%q want=%q", got, want)
+	}
+}
+
 func TestSQLScanner(t *testing.T) {
 	sVer := "1.1.1"
 	x, err := StrictNewVersion(sVer)