From 2c935642f6aa3db2df3f48f81e80b37740512679 Mon Sep 17 00:00:00 2001 From: Chenyu Zhao Date: Wed, 18 May 2022 03:34:03 -0400 Subject: [PATCH] Make Deck satisfy the sql.Scanner interface --- card.go | 22 ++++++++++++++++++---- card_test.go | 7 +++++++ deck.go | 21 +++++++++++++++++++++ 3 files changed, 46 insertions(+), 4 deletions(-) diff --git a/card.go b/card.go index f05f2e5..06affa6 100644 --- a/card.go +++ b/card.go @@ -1,5 +1,9 @@ package cards +import ( + "errors" +) + type Card int32 var ( @@ -53,22 +57,32 @@ func NewCard(s string) Card { func NewCards(s string) []Card { cards := []Card{} - for i := 0; i < len(s); i += 2 { - cards = append(cards, NewCard(s[i:i+2])) - } - return cards + for i := 0; i < len(s); i += 2 { + cards = append(cards, NewCard(s[i:i+2])) + } + return cards } func (c Card) MarshalText() ([]byte, error) { return []byte(c.String()), nil } +func (c *Card) UnmarshalText(text []byte) error { + if len(text) != 2 { + return errors.New("must have len 2") + } + *c = NewCard(string(text)) + // TODO: validate + return nil +} + func (c Card) MarshalJSON() ([]byte, error) { return []byte("\"" + c.String() + "\""), nil } func (c *Card) UnmarshalJSON(b []byte) error { *c = NewCard(string(b[1:3])) + // TODO: validate return nil } diff --git a/card_test.go b/card_test.go index 7ac97fc..6d06d93 100644 --- a/card_test.go +++ b/card_test.go @@ -32,6 +32,13 @@ func TestMarshalText(t *testing.T) { assert.Equal(t, "Ah", string(b)) } +func TestUnmarshalText(t *testing.T) { + var c Card + assert.Nil(t, c.UnmarshalText([]byte("Ah"))) + assert.Equal(t, NewCard("Ah"), c) + assert.Error(t, c.UnmarshalText([]byte("Ahh")), "must have len 2") +} + func TestMarshalJSON(t *testing.T) { cards := []Card{ NewCard("Ah"), diff --git a/deck.go b/deck.go index bb49c7f..e865b0b 100644 --- a/deck.go +++ b/deck.go @@ -1,6 +1,8 @@ package cards import ( + "errors" + "fmt" "math/rand" "time" ) @@ -62,6 +64,25 @@ func (deck *Deck) Empty() bool { return len(deck.cards) == 0 } +// Scan implements the Scanner interface. +func (deck *Deck) Scan(src interface{}) error { + switch v := src.(type) { + case string: + if len(v)%2 != 0 { + return errors.New("string must have even length") + } + deck.cards = make([]Card, len(v)/2) + for i := 0; i < len(v); i += 2 { + if err := deck.cards[i/2].UnmarshalText([]byte(v)); err != nil { + return fmt.Errorf("Could not unmarshal card '%s': %v", v[i:i+2], err) + } + } + return nil + default: + return errors.New("must be `string` type") + } +} + func initializeFullCards() []Card { var cards []Card