Skip to content

Commit bd5a590

Browse files
vincentserpoulrs
authored andcommitted
add simple value and scan (#46)
1 parent cc5ec57 commit bd5a590

File tree

3 files changed

+128
-0
lines changed

3 files changed

+128
-0
lines changed

b/README.md

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
# Bytes storage
2+
3+
This subpackage is there to allow storage of XIDs in a binary format in, for example, a database.
4+
It allows some data size optimisation as the 12 bytes will be smaller to store than a string.

b/id.go

+38
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
package xidb
2+
3+
import (
4+
"database/sql/driver"
5+
"fmt"
6+
7+
"github.com/rs/xid"
8+
)
9+
10+
type ID struct {
11+
xid.ID
12+
}
13+
14+
// Value implements the driver.Valuer interface.
15+
func (id ID) Value() (driver.Value, error) {
16+
if id.ID.IsNil() {
17+
return nil, nil
18+
}
19+
return id.ID[:], nil
20+
}
21+
22+
// Scan implements the sql.Scanner interface.
23+
func (id *ID) Scan(value interface{}) (err error) {
24+
switch val := value.(type) {
25+
case []byte:
26+
i, err := xid.FromBytes(val)
27+
if err != nil {
28+
return err
29+
}
30+
*id = ID{ID: i}
31+
return nil
32+
case nil:
33+
*id = ID{ID: xid.NilID()}
34+
return nil
35+
default:
36+
return fmt.Errorf("xid: scanning unsupported type: %T", value)
37+
}
38+
}

b/id_test.go

+86
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
package xidb
2+
3+
import (
4+
"reflect"
5+
"testing"
6+
7+
"github.com/rs/xid"
8+
)
9+
10+
func TestIDValue(t *testing.T) {
11+
i, _ := xid.FromString("9m4e2mr0ui3e8a215n4g")
12+
13+
tests := []struct {
14+
name string
15+
id ID
16+
expectedVal interface{}
17+
}{
18+
{
19+
name: "non nil id",
20+
id: ID{ID: i},
21+
expectedVal: i.Bytes(),
22+
},
23+
{
24+
name: "nil id",
25+
id: ID{ID: xid.NilID()},
26+
expectedVal: nil,
27+
},
28+
}
29+
30+
for _, tt := range tests {
31+
t.Run(tt.name, func(t *testing.T) {
32+
got, _ := tt.id.Value()
33+
if !reflect.DeepEqual(got, tt.expectedVal) {
34+
t.Errorf("wanted %v, got %v", tt.expectedVal, got)
35+
}
36+
})
37+
}
38+
}
39+
40+
func TestIDScan(t *testing.T) {
41+
i, _ := xid.FromString("9m4e2mr0ui3e8a215n4g")
42+
43+
tests := []struct {
44+
name string
45+
val interface{}
46+
expectedID ID
47+
expectedErr bool
48+
}{
49+
{
50+
name: "bytes id",
51+
val: i.Bytes(),
52+
expectedID: ID{ID: i},
53+
},
54+
{
55+
name: "nil id",
56+
val: nil,
57+
expectedID: ID{ID: xid.NilID()},
58+
},
59+
{
60+
name: "wrong bytes",
61+
val: []byte{0x01},
62+
expectedErr: true,
63+
},
64+
{
65+
name: "unknown type",
66+
val: 1,
67+
expectedErr: true,
68+
},
69+
}
70+
71+
for _, tt := range tests {
72+
t.Run(tt.name, func(t *testing.T) {
73+
id := &ID{}
74+
err := id.Scan(tt.val)
75+
if (err != nil) != tt.expectedErr {
76+
t.Errorf("error expected: %t, got %t", tt.expectedErr, (err != nil))
77+
}
78+
if err == nil {
79+
if !reflect.DeepEqual(id.ID, tt.expectedID.ID) {
80+
t.Errorf("wanted %v, got %v", tt.expectedID, id)
81+
}
82+
}
83+
84+
})
85+
}
86+
}

0 commit comments

Comments
 (0)