2018-09-05 14:54:38 -04:00
|
|
|
package guid
|
|
|
|
|
|
|
|
import (
|
|
|
|
"crypto/rand"
|
2018-09-26 06:54:23 -04:00
|
|
|
"encoding/json"
|
2018-09-05 14:54:38 -04:00
|
|
|
"fmt"
|
|
|
|
"io"
|
2018-09-26 06:54:23 -04:00
|
|
|
"strconv"
|
|
|
|
"strings"
|
2018-09-05 14:54:38 -04:00
|
|
|
)
|
|
|
|
|
2018-09-26 06:54:23 -04:00
|
|
|
var _ = (json.Marshaler)(&GUID{})
|
|
|
|
var _ = (json.Unmarshaler)(&GUID{})
|
|
|
|
|
2018-09-05 14:54:38 -04:00
|
|
|
type GUID [16]byte
|
|
|
|
|
|
|
|
func New() GUID {
|
|
|
|
g := GUID{}
|
|
|
|
_, err := io.ReadFull(rand.Reader, g[:])
|
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
return g
|
|
|
|
}
|
|
|
|
|
|
|
|
func (g GUID) String() string {
|
|
|
|
return fmt.Sprintf("%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x-%02x", g[3], g[2], g[1], g[0], g[5], g[4], g[7], g[6], g[8:10], g[10:])
|
|
|
|
}
|
2018-09-26 06:54:23 -04:00
|
|
|
|
|
|
|
func FromString(s string) GUID {
|
|
|
|
if len(s) != 36 {
|
|
|
|
panic(fmt.Sprintf("invalid GUID length: %d", len(s)))
|
|
|
|
}
|
|
|
|
if s[8] != '-' || s[13] != '-' || s[18] != '-' || s[23] != '-' {
|
|
|
|
panic("invalid GUID format")
|
|
|
|
}
|
|
|
|
indexOrder := [16]int{
|
|
|
|
0, 2, 4, 6,
|
|
|
|
9, 11,
|
|
|
|
14, 16,
|
|
|
|
19, 21,
|
|
|
|
24, 26, 28, 30, 32, 34,
|
|
|
|
}
|
|
|
|
byteOrder := [16]int{
|
|
|
|
3, 2, 1, 0,
|
|
|
|
5, 4,
|
|
|
|
7, 6,
|
|
|
|
8, 9,
|
|
|
|
10, 11, 12, 13, 14, 15,
|
|
|
|
}
|
|
|
|
var g GUID
|
|
|
|
for i, x := range indexOrder {
|
|
|
|
b, err := strconv.ParseInt(s[x:x+2], 16, 16)
|
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
g[byteOrder[i]] = byte(b)
|
|
|
|
}
|
|
|
|
return g
|
|
|
|
}
|
|
|
|
|
|
|
|
func (g GUID) MarshalJSON() ([]byte, error) {
|
|
|
|
return json.Marshal(g.String())
|
|
|
|
}
|
|
|
|
|
|
|
|
func (g *GUID) UnmarshalJSON(data []byte) error {
|
|
|
|
*g = FromString(strings.Trim(string(data), "\""))
|
|
|
|
return nil
|
|
|
|
}
|