Add pgtype.Macaddr
This commit is contained in:
+154
@@ -0,0 +1,154 @@
|
||||
package pgtype
|
||||
|
||||
import (
|
||||
"database/sql/driver"
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
)
|
||||
|
||||
type Macaddr struct {
|
||||
Addr net.HardwareAddr
|
||||
Status Status
|
||||
}
|
||||
|
||||
func (dst *Macaddr) Set(src interface{}) error {
|
||||
if src == nil {
|
||||
*dst = Macaddr{Status: Null}
|
||||
return nil
|
||||
}
|
||||
|
||||
switch value := src.(type) {
|
||||
case net.HardwareAddr:
|
||||
addr := make(net.HardwareAddr, len(value))
|
||||
copy(addr, value)
|
||||
*dst = Macaddr{Addr: addr, Status: Present}
|
||||
case string:
|
||||
addr, err := net.ParseMAC(value)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
*dst = Macaddr{Addr: addr, Status: Present}
|
||||
default:
|
||||
if originalSrc, ok := underlyingPtrType(src); ok {
|
||||
return dst.Set(originalSrc)
|
||||
}
|
||||
return fmt.Errorf("cannot convert %v to Macaddr", value)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (dst *Macaddr) Get() interface{} {
|
||||
switch dst.Status {
|
||||
case Present:
|
||||
return dst.Addr
|
||||
case Null:
|
||||
return nil
|
||||
default:
|
||||
return dst.Status
|
||||
}
|
||||
}
|
||||
|
||||
func (src *Macaddr) AssignTo(dst interface{}) error {
|
||||
switch src.Status {
|
||||
case Present:
|
||||
switch v := dst.(type) {
|
||||
case *net.HardwareAddr:
|
||||
*v = make(net.HardwareAddr, len(src.Addr))
|
||||
copy(*v, src.Addr)
|
||||
return nil
|
||||
case *string:
|
||||
*v = src.Addr.String()
|
||||
return nil
|
||||
default:
|
||||
if nextDst, retry := GetAssignToDstType(dst); retry {
|
||||
return src.AssignTo(nextDst)
|
||||
}
|
||||
}
|
||||
case Null:
|
||||
return nullAssignTo(dst)
|
||||
}
|
||||
|
||||
return fmt.Errorf("cannot decode %v into %T", src, dst)
|
||||
}
|
||||
|
||||
func (dst *Macaddr) DecodeText(ci *ConnInfo, src []byte) error {
|
||||
if src == nil {
|
||||
*dst = Macaddr{Status: Null}
|
||||
return nil
|
||||
}
|
||||
|
||||
addr, err := net.ParseMAC(string(src))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
*dst = Macaddr{Addr: addr, Status: Present}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (dst *Macaddr) DecodeBinary(ci *ConnInfo, src []byte) error {
|
||||
if src == nil {
|
||||
*dst = Macaddr{Status: Null}
|
||||
return nil
|
||||
}
|
||||
|
||||
if len(src) != 6 {
|
||||
return fmt.Errorf("Received an invalid size for a macaddr: %d", len(src))
|
||||
}
|
||||
|
||||
addr := make(net.HardwareAddr, 6)
|
||||
copy(addr, src)
|
||||
|
||||
*dst = Macaddr{Addr: addr, Status: Present}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (src Macaddr) EncodeText(ci *ConnInfo, w io.Writer) (bool, error) {
|
||||
switch src.Status {
|
||||
case Null:
|
||||
return true, nil
|
||||
case Undefined:
|
||||
return false, errUndefined
|
||||
}
|
||||
|
||||
_, err := io.WriteString(w, src.Addr.String())
|
||||
return false, err
|
||||
}
|
||||
|
||||
// EncodeBinary encodes src into w.
|
||||
func (src Macaddr) EncodeBinary(ci *ConnInfo, w io.Writer) (bool, error) {
|
||||
switch src.Status {
|
||||
case Null:
|
||||
return true, nil
|
||||
case Undefined:
|
||||
return false, errUndefined
|
||||
}
|
||||
|
||||
_, err := w.Write([]byte(src.Addr))
|
||||
return false, err
|
||||
}
|
||||
|
||||
// Scan implements the database/sql Scanner interface.
|
||||
func (dst *Macaddr) Scan(src interface{}) error {
|
||||
if src == nil {
|
||||
*dst = Macaddr{Status: Null}
|
||||
return nil
|
||||
}
|
||||
|
||||
switch src := src.(type) {
|
||||
case string:
|
||||
return dst.DecodeText(nil, []byte(src))
|
||||
case []byte:
|
||||
return dst.DecodeText(nil, src)
|
||||
}
|
||||
|
||||
return fmt.Errorf("cannot scan %T", src)
|
||||
}
|
||||
|
||||
// Value implements the database/sql/driver Valuer interface.
|
||||
func (src Macaddr) Value() (driver.Value, error) {
|
||||
return encodeValueText(src)
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
package pgtype_test
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"net"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/jackc/pgx/pgtype"
|
||||
)
|
||||
|
||||
func TestMacaddrTranscode(t *testing.T) {
|
||||
testSuccessfulTranscode(t, "macaddr", []interface{}{
|
||||
pgtype.Macaddr{Addr: mustParseMacaddr(t, "01:23:45:67:89:ab"), Status: pgtype.Present},
|
||||
pgtype.Macaddr{Status: pgtype.Null},
|
||||
})
|
||||
}
|
||||
|
||||
func TestMacaddrSet(t *testing.T) {
|
||||
successfulTests := []struct {
|
||||
source interface{}
|
||||
result pgtype.Macaddr
|
||||
}{
|
||||
{
|
||||
source: mustParseMacaddr(t, "01:23:45:67:89:ab"),
|
||||
result: pgtype.Macaddr{Addr: mustParseMacaddr(t, "01:23:45:67:89:ab"), Status: pgtype.Present},
|
||||
},
|
||||
{
|
||||
source: "01:23:45:67:89:ab",
|
||||
result: pgtype.Macaddr{Addr: mustParseMacaddr(t, "01:23:45:67:89:ab"), Status: pgtype.Present},
|
||||
},
|
||||
}
|
||||
|
||||
for i, tt := range successfulTests {
|
||||
var r pgtype.Macaddr
|
||||
err := r.Set(tt.source)
|
||||
if err != nil {
|
||||
t.Errorf("%d: %v", i, err)
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(r, tt.result) {
|
||||
t.Errorf("%d: expected %v to convert to %v, but it was %v", i, tt.source, tt.result, r)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestMacaddrAssignTo(t *testing.T) {
|
||||
{
|
||||
src := pgtype.Macaddr{Addr: mustParseMacaddr(t, "01:23:45:67:89:ab"), Status: pgtype.Present}
|
||||
var dst net.HardwareAddr
|
||||
expected := mustParseMacaddr(t, "01:23:45:67:89:ab")
|
||||
|
||||
err := src.AssignTo(&dst)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
if bytes.Compare([]byte(dst), []byte(expected)) != 0 {
|
||||
t.Errorf("expected %v to assign %v, but result was %v", src, expected, dst)
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
src := pgtype.Macaddr{Addr: mustParseMacaddr(t, "01:23:45:67:89:ab"), Status: pgtype.Present}
|
||||
var dst string
|
||||
expected := "01:23:45:67:89:ab"
|
||||
|
||||
err := src.AssignTo(&dst)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
if dst != expected {
|
||||
t.Errorf("expected %v to assign %v, but result was %v", src, expected, dst)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -245,6 +245,7 @@ func init() {
|
||||
"jsonb": &Jsonb{},
|
||||
"line": &Line{},
|
||||
"lseg": &Lseg{},
|
||||
"macaddr": &Macaddr{},
|
||||
"name": &Name{},
|
||||
"numeric": &Numeric{},
|
||||
"numrange": &Numrange{},
|
||||
|
||||
@@ -78,6 +78,15 @@ func mustParseCidr(t testing.TB, s string) *net.IPNet {
|
||||
return ipnet
|
||||
}
|
||||
|
||||
func mustParseMacaddr(t testing.TB, s string) net.HardwareAddr {
|
||||
addr, err := net.ParseMAC(s)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
return addr
|
||||
}
|
||||
|
||||
type forceTextEncoder struct {
|
||||
e pgtype.TextEncoder
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user