Skip to content

Commit

Permalink
Merge pull request #190 from mattfarina/constraints-text-marshal
Browse files Browse the repository at this point in the history
Adding text marshaling and unmarshaling
  • Loading branch information
mattfarina committed Nov 28, 2022
2 parents 00300c4 + 3c1d0f2 commit 3efb84c
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 35 deletions.
27 changes: 8 additions & 19 deletions constraints.go
Expand Up @@ -2,7 +2,6 @@ package semver

import (
"bytes"
"encoding/json"
"errors"
"fmt"
"regexp"
Expand Down Expand Up @@ -135,31 +134,21 @@ func (cs Constraints) String() string {
return strings.Join(buf, " || ")
}

// UnmarshalJSON implements JSON.Unmarshaler interface.
func (cs *Constraints) UnmarshalJSON(b []byte) error {
var s string
if err := json.Unmarshal(b, &s); err != nil {
return err
}
temp, err := NewConstraint(s)
// UnmarshalText implements the encoding.TextUnmarshaler interface.
func (cs *Constraints) UnmarshalText(text []byte) error {
temp, err := NewConstraint(string(text))
if err != nil {
return err
}

*cs = *temp

return nil
}

// MarshalJSON implements JSON.Marshaler interface.
func (cs Constraints) MarshalJSON() ([]byte, error) {
// we need our own encoder so we don't escape '<' and '>' which json.Marshal does
buf := new(bytes.Buffer)
enc := json.NewEncoder(buf)
enc.SetEscapeHTML(false)

if err := enc.Encode(cs.String()); err != nil {
return nil, err
}
return bytes.TrimRight(buf.Bytes(), "\n"), nil
// MarshalText implements the encoding.TextMarshaler interface.
func (cs Constraints) MarshalText() ([]byte, error) {
return []byte(cs.String()), nil
}

var constraintOps map[string]cfunc
Expand Down
68 changes: 52 additions & 16 deletions constraints_test.go
Expand Up @@ -680,55 +680,91 @@ func TestConstraintString(t *testing.T) {
}
}

func TestJsonMarshalConstraints(t *testing.T) {
func TestTextMarshalConstraints(t *testing.T) {
tests := []struct {
sCs string
want string
constraint string
want string
}{
{"1.1.1", "1.1.1"},
{">=1.1.1", ">=1.1.1"},
{"<=1.1.1", "<=1.1.1"},
{"1.2.3", "1.2.3"},
{">=1.2.3", ">=1.2.3"},
{"<=1.2.3", "<=1.2.3"},
{"1 <=1.2.3", "1 <=1.2.3"},
{"1, <=1.2.3", "1 <=1.2.3"},
{">1, <=1.2.3", ">1 <=1.2.3"},
{"> 1 , <=1.2.3", ">1 <=1.2.3"},
}

for _, tc := range tests {
cs, err := NewConstraint(tc.sCs)
cs, err := NewConstraint(tc.constraint)
if err != nil {
t.Errorf("Error creating constraints: %s", err)
}

out, err2 := cs.MarshalText()
if err2 != nil {
t.Errorf("Error constraint version: %s", err2)
}

got := string(out)
if got != tc.want {
t.Errorf("Error marshaling constraint, unexpected marshaled content: got=%q want=%q", got, tc.want)
}

// Test that this works for JSON as well as text. When JSON marshaling
// functions are missing it falls through to TextMarshal.
// NOTE: To not escape the < and > (which json.Marshal does) you need
// a custom encoder where html escaping is disabled. This must be done
// in the top level encoder being used to marshal the constraints.
buf := new(bytes.Buffer)
enc := json.NewEncoder(buf)
enc.SetEscapeHTML(false)
err = enc.Encode(cs)
if err != nil {
t.Errorf("Error unmarshaling version: %s", err)
t.Errorf("Error unmarshaling constraint: %s", err)
}
got := buf.String()
got = buf.String()
// The encoder used here adds a newline so we add that to what we want
// so they align. The newline is an artifact of the testing.
want := fmt.Sprintf("%q\n", tc.want)
if got != want {
t.Errorf("Error marshaling unexpected marshaled content: got=%q want=%q", got, want)
t.Errorf("Error marshaling constraint, unexpected marshaled content: got=%q want=%q", got, want)
}
}
}

func TestJsonUnmarshalConstraints(t *testing.T) {
func TestTextUnmarshalConstraints(t *testing.T) {
tests := []struct {
sCs string
want string
constraint string
want string
}{
{"1.1.1", "1.1.1"},
{"1.2.3", "1.2.3"},
{">=1.2.3", ">=1.2.3"},
{"<=1.2.3", "<=1.2.3"},
{">1 <=1.2.3", ">1 <=1.2.3"},
{"> 1 <=1.2.3", ">1 <=1.2.3"},
{">1, <=1.2.3", ">1 <=1.2.3"},
}

for _, tc := range tests {
cs := Constraints{}
err := json.Unmarshal([]byte(fmt.Sprintf("%q", tc.sCs)), &cs)
err := cs.UnmarshalText([]byte(tc.constraint))
if err != nil {
t.Errorf("Error unmarshaling constraints: %s", err)
}
got := cs.String()
if got != tc.want {
t.Errorf("Error unmarshaling unexpected object content: got=%q want=%q", got, tc.want)
t.Errorf("Error unmarshaling constraint, unexpected object content: got=%q want=%q", got, tc.want)
}

// Test that this works for JSON as well as text. When JSON unmarshaling
// functions are missing it falls through to TextUnmarshal.
err = json.Unmarshal([]byte(fmt.Sprintf("%q", tc.constraint)), &cs)
if err != nil {
t.Errorf("Error unmarshaling constraints: %s", err)
}
got = cs.String()
if got != tc.want {
t.Errorf("Error unmarshaling constraint, unexpected object content: got=%q want=%q", got, tc.want)
}
}
}

0 comments on commit 3efb84c

Please sign in to comment.