github.com/go-board/x-go@v0.1.2-0.20220610024734-db1323f6cb15/xdatabase/xsql/types.go (about)

     1  package xsql
     2  
     3  import (
     4  	"database/sql/driver"
     5  	"errors"
     6  	"net"
     7  	"strings"
     8  )
     9  
    10  // StringArray present a slice of array which store in database in string mode,
    11  // but in application is string slice mode, this will translate automatically.
    12  type StringArray []string
    13  
    14  func (a StringArray) String() string {
    15  	return strings.Join(a, ",")
    16  }
    17  
    18  func (a *StringArray) Scan(src interface{}) error {
    19  	switch x := src.(type) {
    20  	case string:
    21  		*a = strings.Split(x, ",")
    22  		return nil
    23  	case []byte:
    24  		*a = strings.Split(string(x), ",")
    25  		return nil
    26  	default:
    27  		return nil
    28  	}
    29  }
    30  
    31  func (a StringArray) Value() (driver.Value, error) {
    32  	x := strings.Join(a, ",")
    33  	return x, nil
    34  }
    35  
    36  // Enum present a selectable of value which store in database in int mode,
    37  // but in application is string mode, this will translate automatically.
    38  type Enum struct {
    39  	value    string
    40  	valueMap map[string]int
    41  	keyMap   map[int]string
    42  }
    43  
    44  func NewEnum(valueMap map[string]int, defs ...string) *Enum {
    45  	def := ""
    46  	if len(defs) > 0 {
    47  		def = defs[0]
    48  	}
    49  	keyMap := make(map[int]string)
    50  	for v, i := range valueMap {
    51  		keyMap[i] = v
    52  	}
    53  	return &Enum{
    54  		value:    def,
    55  		valueMap: valueMap,
    56  		keyMap:   keyMap,
    57  	}
    58  }
    59  
    60  func (a *Enum) String() string {
    61  	return a.value
    62  }
    63  
    64  func (a *Enum) fromInt(i int) {
    65  	a.value = a.keyMap[i]
    66  }
    67  
    68  func (a *Enum) Scan(src interface{}) error {
    69  	switch x := src.(type) {
    70  	case int:
    71  		a.fromInt(x)
    72  		return nil
    73  	case int64:
    74  		a.fromInt(int(x))
    75  		return nil
    76  	case int32:
    77  		a.fromInt(int(x))
    78  		return nil
    79  	default:
    80  		return nil
    81  	}
    82  }
    83  
    84  func (a Enum) Value() (driver.Value, error) {
    85  	return a.valueMap[a.value], nil
    86  }
    87  
    88  // IPV4 present a selectable of ipv4 address which store in database in int mode,
    89  // but in application is ipv4 mode, this will translate automatically.
    90  type IPV4 struct {
    91  	ipStr string
    92  	ip    net.IP
    93  }
    94  
    95  func NewIPV4(ip string) (*IPV4, error) {
    96  	ipaddr := net.ParseIP(ip)
    97  	if ipaddr == nil {
    98  		return nil, errors.New("err: parse ipv4 failed: " + ip)
    99  	}
   100  	return &IPV4{ip: ipaddr, ipStr: ip}, nil
   101  }
   102  
   103  func (a IPV4) toUint32() uint32 {
   104  	return uint32(a.ip[0])<<24 + uint32(a.ip[1])<<16 + uint32(a.ip[2])<<8 + uint32(a.ip[3])
   105  }
   106  
   107  func (a *IPV4) fromUint32(u uint32) error {
   108  	a.ip[0] = uint8(u >> 24)
   109  	a.ip[1] = uint8(u >> 16)
   110  	a.ip[2] = uint8(u >> 8)
   111  	a.ip[3] = uint8(u)
   112  	a.ipStr = a.ip.String()
   113  	return nil
   114  }
   115  
   116  func (a IPV4) IP() net.IP {
   117  	return a.ip
   118  }
   119  
   120  func (a IPV4) String() string {
   121  	return a.ipStr
   122  }
   123  
   124  func (a *IPV4) Scan(src interface{}) error {
   125  	a.ip = a.ip[:0]
   126  	switch x := src.(type) {
   127  	case uint32:
   128  		return a.fromUint32(x)
   129  	case uint64:
   130  		return a.fromUint32(uint32(x))
   131  	case int64:
   132  		return a.fromUint32(uint32(x))
   133  	default:
   134  		return errors.New("err: unsupported type")
   135  	}
   136  }
   137  
   138  func (a IPV4) Value() (driver.Value, error) {
   139  	return a.toUint32(), nil
   140  }