Skip to content

Commit e4041ec

Browse files
feat: IPNet type
1 parent 7a70251 commit e4041ec

File tree

2 files changed

+111
-2
lines changed

2 files changed

+111
-2
lines changed

scw/custom_types.go

+36-1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ import (
55
"encoding/json"
66
"fmt"
77
"io"
8+
"net"
9+
"strings"
810
"time"
911

1012
"github.com./scaleway/scaleway-sdk-go/internal/errors"
@@ -123,7 +125,7 @@ type TimeSeriesPoint struct {
123125
Value float32
124126
}
125127

126-
func (tsp *TimeSeriesPoint) MarshalJSON() ([]byte, error) {
128+
func (tsp TimeSeriesPoint) MarshalJSON() ([]byte, error) {
127129
timestamp := tsp.Timestamp.Format(time.RFC3339)
128130
value, err := json.Marshal(tsp.Value)
129131
if err != nil {
@@ -164,3 +166,36 @@ func (tsp *TimeSeriesPoint) UnmarshalJSON(b []byte) error {
164166

165167
return nil
166168
}
169+
170+
// IPNet inherits net.IPNet and represents an IP network.
171+
type IPNet struct {
172+
net.IPNet
173+
}
174+
175+
func (n IPNet) MarshalJSON() ([]byte, error) {
176+
return []byte(`"` + n.String() + `"`), nil
177+
}
178+
179+
func (n *IPNet) UnmarshalJSON(b []byte) error {
180+
var str *string
181+
182+
err := json.Unmarshal(b, &str)
183+
if err != nil {
184+
return err
185+
}
186+
if str == nil {
187+
return nil
188+
}
189+
190+
if !strings.Contains(*str, "/") && net.ParseIP(*str) != nil {
191+
*str += "/32"
192+
}
193+
194+
_, value, err := net.ParseCIDR(*str)
195+
if err != nil {
196+
return errors.Wrap(err, "cannot decode JSON")
197+
}
198+
n.IPNet = *value
199+
200+
return nil
201+
}

scw/custom_types_test.go

+75-1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package scw
33
import (
44
"encoding/json"
55
"io/ioutil"
6+
"net"
67
"testing"
78
"time"
89

@@ -67,7 +68,7 @@ func TestTimeSeries_MarshallJSON(t *testing.T) {
6768
}
6869
}
6970

70-
func TestTimeSeries_UnmarshallJSON(t *testing.T) {
71+
func TestTimeSeries_UnmarshalJSON(t *testing.T) {
7172
cases := []struct {
7273
name string
7374
json string
@@ -166,3 +167,76 @@ func TestFile_UnmarshalJSON(t *testing.T) {
166167
content: []byte("\x00\x00\x00\n"),
167168
}))
168169
}
170+
171+
func TestIPNet_MarshallJSON(t *testing.T) {
172+
cases := []struct {
173+
name string
174+
ipRange IPNet
175+
want string
176+
err error
177+
}{
178+
{
179+
name: "ip",
180+
ipRange: IPNet{IPNet: net.IPNet{IP: net.IPv4(42, 42, 42, 42), Mask: net.CIDRMask(32, 32)}},
181+
want: `"42.42.42.42/32"`,
182+
},
183+
{
184+
name: "network",
185+
ipRange: IPNet{IPNet: net.IPNet{IP: net.IPv4(42, 42, 42, 42), Mask: net.CIDRMask(16, 32)}},
186+
want: `"42.42.42.42/16"`,
187+
},
188+
}
189+
190+
for _, c := range cases {
191+
t.Run(c.name, func(t *testing.T) {
192+
got, err := json.Marshal(c.ipRange)
193+
194+
testhelpers.Equals(t, c.err, err)
195+
if c.err == nil {
196+
testhelpers.Equals(t, c.want, string(got))
197+
}
198+
})
199+
}
200+
}
201+
202+
func TestIPNet_UnmarshalJSON(t *testing.T) {
203+
cases := []struct {
204+
name string
205+
json string
206+
want IPNet
207+
err string
208+
}{
209+
{
210+
name: "IP with CIDR",
211+
json: `"42.42.42.42/32"`,
212+
want: IPNet{IPNet: net.IPNet{IP: net.IPv4(42, 42, 42, 42), Mask: net.CIDRMask(32, 32)}},
213+
},
214+
{
215+
name: "IP with network",
216+
json: `"192.0.2.1/24"`,
217+
want: IPNet{IPNet: net.IPNet{IP: net.IPv4(192, 0, 2, 0), Mask: net.CIDRMask(24, 32)}},
218+
},
219+
{
220+
name: "IP alone",
221+
json: `"42.42.42.42"`,
222+
want: IPNet{IPNet: net.IPNet{IP: net.IPv4(42, 42, 42, 42), Mask: net.CIDRMask(32, 32)}},
223+
},
224+
{
225+
name: "with timestamp error",
226+
json: `"name"`,
227+
err: "scaleway-sdk-go: cannot decode JSON: invalid CIDR address: name",
228+
},
229+
}
230+
231+
for _, c := range cases {
232+
t.Run(c.name, func(t *testing.T) {
233+
ipNet := &IPNet{}
234+
err := json.Unmarshal([]byte(c.json), ipNet)
235+
if err != nil {
236+
testhelpers.Equals(t, c.err, err.Error())
237+
}
238+
239+
testhelpers.Equals(t, c.want.String(), ipNet.String())
240+
})
241+
}
242+
}

0 commit comments

Comments
 (0)