109 lines
2.5 KiB
Go
109 lines
2.5 KiB
Go
|
package types
|
||
|
|
||
|
import (
|
||
|
"database/sql/driver"
|
||
|
"encoding/json"
|
||
|
"errors"
|
||
|
"fmt"
|
||
|
"net/netip"
|
||
|
|
||
|
"tailscale.com/tailcfg"
|
||
|
)
|
||
|
|
||
|
var ErrCannotParsePrefix = errors.New("cannot parse prefix")
|
||
|
|
||
|
// This is a "wrapper" type around tailscales
|
||
|
// Hostinfo to allow us to add database "serialization"
|
||
|
// methods. This allows us to use a typed values throughout
|
||
|
// the code and not have to marshal/unmarshal and error
|
||
|
// check all over the code.
|
||
|
type HostInfo tailcfg.Hostinfo
|
||
|
|
||
|
func (hi *HostInfo) Scan(destination interface{}) error {
|
||
|
switch value := destination.(type) {
|
||
|
case []byte:
|
||
|
return json.Unmarshal(value, hi)
|
||
|
|
||
|
case string:
|
||
|
return json.Unmarshal([]byte(value), hi)
|
||
|
|
||
|
default:
|
||
|
return fmt.Errorf("%w: unexpected data type %T", ErrMachineAddressesInvalid, destination)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Value return json value, implement driver.Valuer interface.
|
||
|
func (hi HostInfo) Value() (driver.Value, error) {
|
||
|
bytes, err := json.Marshal(hi)
|
||
|
|
||
|
return string(bytes), err
|
||
|
}
|
||
|
|
||
|
type IPPrefix netip.Prefix
|
||
|
|
||
|
func (i *IPPrefix) Scan(destination interface{}) error {
|
||
|
switch value := destination.(type) {
|
||
|
case string:
|
||
|
prefix, err := netip.ParsePrefix(value)
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
*i = IPPrefix(prefix)
|
||
|
|
||
|
return nil
|
||
|
default:
|
||
|
return fmt.Errorf("%w: unexpected data type %T", ErrCannotParsePrefix, destination)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Value return json value, implement driver.Valuer interface.
|
||
|
func (i IPPrefix) Value() (driver.Value, error) {
|
||
|
prefixStr := netip.Prefix(i).String()
|
||
|
|
||
|
return prefixStr, nil
|
||
|
}
|
||
|
|
||
|
type IPPrefixes []netip.Prefix
|
||
|
|
||
|
func (i *IPPrefixes) Scan(destination interface{}) error {
|
||
|
switch value := destination.(type) {
|
||
|
case []byte:
|
||
|
return json.Unmarshal(value, i)
|
||
|
|
||
|
case string:
|
||
|
return json.Unmarshal([]byte(value), i)
|
||
|
|
||
|
default:
|
||
|
return fmt.Errorf("%w: unexpected data type %T", ErrMachineAddressesInvalid, destination)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Value return json value, implement driver.Valuer interface.
|
||
|
func (i IPPrefixes) Value() (driver.Value, error) {
|
||
|
bytes, err := json.Marshal(i)
|
||
|
|
||
|
return string(bytes), err
|
||
|
}
|
||
|
|
||
|
type StringList []string
|
||
|
|
||
|
func (i *StringList) Scan(destination interface{}) error {
|
||
|
switch value := destination.(type) {
|
||
|
case []byte:
|
||
|
return json.Unmarshal(value, i)
|
||
|
|
||
|
case string:
|
||
|
return json.Unmarshal([]byte(value), i)
|
||
|
|
||
|
default:
|
||
|
return fmt.Errorf("%w: unexpected data type %T", ErrMachineAddressesInvalid, destination)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Value return json value, implement driver.Valuer interface.
|
||
|
func (i StringList) Value() (driver.Value, error) {
|
||
|
bytes, err := json.Marshal(i)
|
||
|
|
||
|
return string(bytes), err
|
||
|
}
|