github.com/naemono/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  }