github.com/reggieriser/pop@v4.13.1+incompatible/slices/uuid.go (about) 1 package slices 2 3 import ( 4 "database/sql/driver" 5 "encoding/json" 6 "fmt" 7 "strings" 8 9 "errors" 10 11 "github.com/gofrs/uuid" 12 ) 13 14 // For reading in arrays from postgres 15 16 // UUID is a slice of UUIDs. 17 type UUID []uuid.UUID 18 19 // Interface implements the nulls.nullable interface. 20 func (s UUID) Interface() interface{} { 21 return []uuid.UUID(s) 22 } 23 24 // Scan implements the sql.Scanner interface. 25 // It allows to read the UUID slice from the database value. 26 func (s *UUID) Scan(src interface{}) error { 27 b, ok := src.([]byte) 28 if !ok { 29 return errors.New("scan source was not []byte") 30 } 31 us, err := strSliceToUUIDSlice(strToUUID(string(b))) 32 if err != nil { 33 return err 34 } 35 *s = us 36 return nil 37 } 38 39 // Value implements the driver.Valuer interface. 40 // It allows to convert the UUID slice to a driver.value. 41 func (s UUID) Value() (driver.Value, error) { 42 ss := make([]string, len(s)) 43 for i, u := range s { 44 ss[i] = u.String() 45 } 46 return fmt.Sprintf("{%s}", strings.Join(ss, ",")), nil 47 } 48 49 // UnmarshalJSON will unmarshall JSON value into 50 // the UUID slice representation of this value. 51 func (s *UUID) UnmarshalJSON(data []byte) error { 52 var ss []string 53 if err := json.Unmarshal(data, &ss); err != nil { 54 return err 55 } 56 us, err := strSliceToUUIDSlice(ss) 57 if err != nil { 58 return err 59 } 60 *s = us 61 return nil 62 } 63 64 // UnmarshalText will unmarshall text value into 65 // the UUID slice representation of this value. 66 func (s *UUID) UnmarshalText(text []byte) error { 67 var ss []string 68 for _, x := range strings.Split(string(text), ",") { 69 ss = append(ss, strings.TrimSpace(x)) 70 } 71 us, err := strSliceToUUIDSlice(ss) 72 if err != nil { 73 return err 74 } 75 *s = us 76 return nil 77 } 78 79 // TagValue implements the tagValuer interface, to work with https://github.com/gobuffalo/tags. 80 func (s UUID) TagValue() string { 81 return s.Format(",") 82 } 83 84 // Format presents the slice as a string, using a given separator. 85 func (s UUID) Format(sep string) string { 86 ss := make([]string, len(s)) 87 for i, u := range s { 88 ss[i] = u.String() 89 } 90 return strings.Join(ss, sep) 91 } 92 93 func strToUUID(s string) []string { 94 r := strings.Trim(s, "{}") 95 return strings.Split(r, ",") 96 } 97 98 func strSliceToUUIDSlice(ss []string) (UUID, error) { 99 us := make([]uuid.UUID, len(ss)) 100 for i, s := range ss { 101 if s == "" { 102 continue 103 } 104 u, err := uuid.FromString(s) 105 if err != nil { 106 return UUID{}, err 107 } 108 us[i] = u 109 } 110 return UUID(us), nil 111 }