add unlink enpoint
This commit is contained in:
@@ -89,7 +89,8 @@ func setAdminRoutes(mux *http.ServeMux) {
|
||||
mux.HandleFunc("/admin/home", withUserWare(cont.ServeHome))
|
||||
mux.HandleFunc("/admin/change_own_password", withUserWare(cont.ServeChangeOwnPassword))
|
||||
mux.HandleFunc("/admin/change_own_password_do", withUserWare(cont.ServeChangeOwnPasswordDo))
|
||||
mux.HandleFunc("/admin/link_lastfm_callback", withUserWare(cont.ServeLinkLastFMCallback))
|
||||
mux.HandleFunc("/admin/link_lastfm_do", withUserWare(cont.ServeLinkLastFMDo))
|
||||
mux.HandleFunc("/admin/unlink_lastfm_do", withUserWare(cont.ServeUnlinkLastFMDo))
|
||||
mux.HandleFunc("/admin/change_password", withAdminWare(cont.ServeChangePassword))
|
||||
mux.HandleFunc("/admin/change_password_do", withAdminWare(cont.ServeChangePasswordDo))
|
||||
mux.HandleFunc("/admin/create_user", withAdminWare(cont.ServeCreateUser))
|
||||
|
||||
3
go.mod
3
go.mod
@@ -2,7 +2,6 @@ module github.com/sentriz/gonic
|
||||
|
||||
require (
|
||||
cloud.google.com/go v0.37.1 // indirect
|
||||
github.com/davecgh/go-spew v1.1.1
|
||||
github.com/denisenkom/go-mssqldb v0.0.0-20190315220205-a8ed825ac853 // indirect
|
||||
github.com/dhowden/tag v0.0.0-20181104225729-a9f04c2798ca
|
||||
github.com/erikstmartin/go-testdb v0.0.0-20160219214506-8d10e4a1bae5 // indirect
|
||||
@@ -17,7 +16,7 @@ require (
|
||||
github.com/mattn/go-sqlite3 v1.10.0 // indirect
|
||||
github.com/mozillazg/go-unidecode v0.1.1
|
||||
github.com/myesui/uuid v1.0.0 // indirect
|
||||
github.com/twinj/uuid v1.0.0
|
||||
github.com/twinj/uuid v1.0.0 // indirect
|
||||
github.com/wader/gormstore v0.0.0-20190302154359-acb787ba3755
|
||||
golang.org/x/crypto v0.0.0-20190411191339-88737f569e3a // indirect
|
||||
google.golang.org/appengine v1.5.0 // indirect
|
||||
|
||||
@@ -22,14 +22,14 @@ func (c *Controller) ServeLoginDo(w http.ResponseWriter, r *http.Request) {
|
||||
if username == "" || password == "" {
|
||||
session.AddFlash("please provide both a username and password")
|
||||
session.Save(r, w)
|
||||
http.Redirect(w, r, r.Header.Get("Referer"), 302)
|
||||
http.Redirect(w, r, r.Header.Get("Referer"), http.StatusSeeOther)
|
||||
return
|
||||
}
|
||||
user := c.GetUserFromName(username)
|
||||
if !(username == user.Name && password == user.Password) {
|
||||
session.AddFlash("invalid username / password")
|
||||
session.Save(r, w)
|
||||
http.Redirect(w, r, r.Header.Get("Referer"), 302)
|
||||
http.Redirect(w, r, r.Header.Get("Referer"), http.StatusSeeOther)
|
||||
return
|
||||
}
|
||||
// put the user name into the session. future endpoints after this one
|
||||
@@ -37,14 +37,14 @@ func (c *Controller) ServeLoginDo(w http.ResponseWriter, r *http.Request) {
|
||||
// session and put the row into the request context.
|
||||
session.Values["user"] = user.Name
|
||||
session.Save(r, w)
|
||||
http.Redirect(w, r, "/admin/home", 303)
|
||||
http.Redirect(w, r, "/admin/home", http.StatusSeeOther)
|
||||
}
|
||||
|
||||
func (c *Controller) ServeLogout(w http.ResponseWriter, r *http.Request) {
|
||||
session := r.Context().Value("session").(*sessions.Session)
|
||||
delete(session.Values, "user")
|
||||
session.Save(r, w)
|
||||
http.Redirect(w, r, "/admin/login", 303)
|
||||
http.Redirect(w, r, "/admin/login", http.StatusSeeOther)
|
||||
}
|
||||
|
||||
func (c *Controller) ServeHome(w http.ResponseWriter, r *http.Request) {
|
||||
@@ -53,9 +53,19 @@ func (c *Controller) ServeHome(w http.ResponseWriter, r *http.Request) {
|
||||
c.DB.Table("albums").Count(&data.AlbumCount)
|
||||
c.DB.Table("tracks").Count(&data.TrackCount)
|
||||
c.DB.Find(&data.AllUsers)
|
||||
var apiKey db.Setting
|
||||
c.DB.Where("key = ?", "lastfm_api_key").First(&apiKey)
|
||||
data.CurrentLastFMAPIKey = apiKey.Value
|
||||
data.CurrentLastFMAPIKey = c.GetSetting("lastfm_api_key")
|
||||
scheme := utilities.FirstExisting(
|
||||
"http", // fallback
|
||||
r.Header.Get("X-Forwarded-Proto"),
|
||||
r.Header.Get("X-Forwarded-Scheme"),
|
||||
r.URL.Scheme,
|
||||
)
|
||||
host := utilities.FirstExisting(
|
||||
"localhost:7373", // fallback
|
||||
r.Header.Get("X-Forwarded-Host"),
|
||||
r.Host,
|
||||
)
|
||||
data.RequestRoot = fmt.Sprintf("%s://%s", scheme, host)
|
||||
renderTemplate(w, r, "home", &data)
|
||||
}
|
||||
|
||||
@@ -71,41 +81,44 @@ func (c *Controller) ServeChangeOwnPasswordDo(w http.ResponseWriter, r *http.Req
|
||||
if err != nil {
|
||||
session.AddFlash(err.Error())
|
||||
session.Save(r, w)
|
||||
http.Redirect(w, r, r.Header.Get("Referer"), 302)
|
||||
http.Redirect(w, r, r.Header.Get("Referer"), http.StatusSeeOther)
|
||||
return
|
||||
}
|
||||
user := r.Context().Value("user").(*db.User)
|
||||
user.Password = passwordOne
|
||||
c.DB.Save(user)
|
||||
http.Redirect(w, r, "/admin/home", 303)
|
||||
http.Redirect(w, r, "/admin/home", http.StatusSeeOther)
|
||||
}
|
||||
|
||||
func (c *Controller) ServeLinkLastFMCallback(w http.ResponseWriter, r *http.Request) {
|
||||
func (c *Controller) ServeLinkLastFMDo(w http.ResponseWriter, r *http.Request) {
|
||||
token := r.URL.Query().Get("token")
|
||||
if token == "" {
|
||||
http.Error(w, "please provide a token", 400)
|
||||
return
|
||||
}
|
||||
var apiKey db.Setting
|
||||
c.DB.Where("key = ?", "lastfm_api_key").First(&apiKey)
|
||||
var secret db.Setting
|
||||
c.DB.Where("key = ?", "lastfm_secret").First(&secret)
|
||||
sessionKey, err := lastfm.GetSession(
|
||||
apiKey.Value,
|
||||
secret.Value,
|
||||
c.GetSetting("lastfm_api_key"),
|
||||
c.GetSetting("lastfm_secret"),
|
||||
token,
|
||||
)
|
||||
session := r.Context().Value("session").(*sessions.Session)
|
||||
if err != nil {
|
||||
session.AddFlash(err.Error())
|
||||
session.Save(r, w)
|
||||
http.Redirect(w, r, "/admin/home", 302)
|
||||
http.Redirect(w, r, "/admin/home", http.StatusSeeOther)
|
||||
return
|
||||
}
|
||||
user := r.Context().Value("user").(*db.User)
|
||||
user.LastFMSession = sessionKey
|
||||
c.DB.Save(&user)
|
||||
http.Redirect(w, r, "/admin/home", 302)
|
||||
http.Redirect(w, r, "/admin/home", http.StatusSeeOther)
|
||||
}
|
||||
|
||||
func (c *Controller) ServeUnlinkLastFMDo(w http.ResponseWriter, r *http.Request) {
|
||||
user := r.Context().Value("user").(*db.User)
|
||||
user.LastFMSession = ""
|
||||
c.DB.Save(&user)
|
||||
http.Redirect(w, r, "/admin/home", http.StatusSeeOther)
|
||||
}
|
||||
|
||||
func (c *Controller) ServeChangePassword(w http.ResponseWriter, r *http.Request) {
|
||||
@@ -136,12 +149,12 @@ func (c *Controller) ServeChangePasswordDo(w http.ResponseWriter, r *http.Reques
|
||||
if err != nil {
|
||||
session.AddFlash(err.Error())
|
||||
session.Save(r, w)
|
||||
http.Redirect(w, r, r.Header.Get("Referer"), 302)
|
||||
http.Redirect(w, r, r.Header.Get("Referer"), http.StatusSeeOther)
|
||||
return
|
||||
}
|
||||
user.Password = passwordOne
|
||||
c.DB.Save(&user)
|
||||
http.Redirect(w, r, "/admin/home", 303)
|
||||
http.Redirect(w, r, "/admin/home", http.StatusSeeOther)
|
||||
}
|
||||
|
||||
func (c *Controller) ServeCreateUser(w http.ResponseWriter, r *http.Request) {
|
||||
@@ -155,7 +168,7 @@ func (c *Controller) ServeCreateUserDo(w http.ResponseWriter, r *http.Request) {
|
||||
if err != nil {
|
||||
session.AddFlash(err.Error())
|
||||
session.Save(r, w)
|
||||
http.Redirect(w, r, r.Header.Get("Referer"), 302)
|
||||
http.Redirect(w, r, r.Header.Get("Referer"), http.StatusSeeOther)
|
||||
return
|
||||
}
|
||||
passwordOne := r.FormValue("password_one")
|
||||
@@ -164,7 +177,7 @@ func (c *Controller) ServeCreateUserDo(w http.ResponseWriter, r *http.Request) {
|
||||
if err != nil {
|
||||
session.AddFlash(err.Error())
|
||||
session.Save(r, w)
|
||||
http.Redirect(w, r, r.Header.Get("Referer"), 302)
|
||||
http.Redirect(w, r, r.Header.Get("Referer"), http.StatusSeeOther)
|
||||
return
|
||||
}
|
||||
user := db.User{
|
||||
@@ -177,10 +190,10 @@ func (c *Controller) ServeCreateUserDo(w http.ResponseWriter, r *http.Request) {
|
||||
"could not create user `%s`: %v", username, err,
|
||||
))
|
||||
session.Save(r, w)
|
||||
http.Redirect(w, r, r.Header.Get("Referer"), 302)
|
||||
http.Redirect(w, r, r.Header.Get("Referer"), http.StatusSeeOther)
|
||||
return
|
||||
}
|
||||
http.Redirect(w, r, "/admin/home", 303)
|
||||
http.Redirect(w, r, "/admin/home", http.StatusSeeOther)
|
||||
}
|
||||
|
||||
func (c *Controller) ServeUpdateLastFMAPIKey(w http.ResponseWriter, r *http.Request) {
|
||||
@@ -198,10 +211,10 @@ func (c *Controller) ServeUpdateLastFMAPIKeyDo(w http.ResponseWriter, r *http.Re
|
||||
if err != nil {
|
||||
session.AddFlash(err.Error())
|
||||
session.Save(r, w)
|
||||
http.Redirect(w, r, r.Header.Get("Referer"), 302)
|
||||
http.Redirect(w, r, r.Header.Get("Referer"), http.StatusSeeOther)
|
||||
return
|
||||
}
|
||||
c.SetSetting("lastfm_api_key", apiKey)
|
||||
c.SetSetting("lastfm_secret", secret)
|
||||
http.Redirect(w, r, "/admin/home", 303)
|
||||
http.Redirect(w, r, "/admin/home", http.StatusSeeOther)
|
||||
}
|
||||
|
||||
@@ -12,7 +12,6 @@ import (
|
||||
|
||||
"github.com/gorilla/sessions"
|
||||
"github.com/sentriz/gonic/db"
|
||||
"github.com/sentriz/gonic/handler/utilities"
|
||||
"github.com/sentriz/gonic/subsonic"
|
||||
|
||||
"github.com/jinzhu/gorm"
|
||||
@@ -182,18 +181,6 @@ func renderTemplate(w http.ResponseWriter, r *http.Request,
|
||||
if ok {
|
||||
data.User = user
|
||||
}
|
||||
scheme := utilities.FirstExisting(
|
||||
"http", // fallback
|
||||
r.Header.Get("X-Forwarded-Proto"),
|
||||
r.Header.Get("X-Forwarded-Scheme"),
|
||||
r.URL.Scheme,
|
||||
)
|
||||
host := utilities.FirstExisting(
|
||||
"localhost:7373", // fallback
|
||||
r.Header.Get("X-Forwarded-Host"),
|
||||
r.Host,
|
||||
)
|
||||
data.RequestRoot = fmt.Sprintf("%s://%s", scheme, host)
|
||||
err := templates[name].ExecuteTemplate(w, "layout", data)
|
||||
if err != nil {
|
||||
http.Error(w, fmt.Sprintf("500 when executing: %v", err), 500)
|
||||
|
||||
@@ -117,7 +117,7 @@ func (c *Controller) WithUserSession(next http.HandlerFunc) http.HandlerFunc {
|
||||
if !ok {
|
||||
session.AddFlash("you are not authenticated")
|
||||
session.Save(r, w)
|
||||
http.Redirect(w, r, "/admin/login", 303)
|
||||
http.Redirect(w, r, "/admin/login", http.StatusSeeOther)
|
||||
return
|
||||
}
|
||||
// take username from sesion and add the user row
|
||||
@@ -135,7 +135,7 @@ func (c *Controller) WithAdminSession(next http.HandlerFunc) http.HandlerFunc {
|
||||
if !user.IsAdmin {
|
||||
session.AddFlash("you are not an admin")
|
||||
session.Save(r, w)
|
||||
http.Redirect(w, r, "/admin/login", 303)
|
||||
http.Redirect(w, r, "/admin/login", http.StatusSeeOther)
|
||||
return
|
||||
}
|
||||
next.ServeHTTP(w, r)
|
||||
|
||||
@@ -24,7 +24,7 @@ var (
|
||||
func getParamSignature(params url.Values, secret string) string {
|
||||
// the parameters must be in order before hashing
|
||||
paramKeys := make([]string, 0)
|
||||
for k, _ := range params {
|
||||
for k := range params {
|
||||
paramKeys = append(paramKeys, k)
|
||||
}
|
||||
sort.Strings(paramKeys)
|
||||
|
||||
@@ -88,3 +88,10 @@ form input[type=submit] {
|
||||
background-color: #fd1b1b1c;
|
||||
}
|
||||
|
||||
.angry {
|
||||
background-color: #f4433669;
|
||||
}
|
||||
|
||||
.happy {
|
||||
background-color: #4caf5069;
|
||||
}
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
package tags
|
||||
|
||||
type probeData struct {
|
||||
Format *probeFormat `json:"format"`
|
||||
}
|
||||
|
||||
type probeFormat struct {
|
||||
Filename string `json:"filename"`
|
||||
NBStreams int `json:"nb_streams"`
|
||||
NBPrograms int `json:"nb_programs"`
|
||||
FormatName string `json:"format_name"`
|
||||
FormatLongName string `json:"format_long_name"`
|
||||
StartTime float64 `json:"start_time,string"`
|
||||
Duration float64 `json:"duration,string"`
|
||||
Size string `json:"size"`
|
||||
Bitrate int `json:"bit_rate,string"`
|
||||
ProbeScore int `json:"probe_score"`
|
||||
Tags map[string]string `json:"tags"`
|
||||
}
|
||||
Binary file not shown.
Binary file not shown.
203
tags/tags.go
203
tags/tags.go
@@ -1,203 +0,0 @@
|
||||
package tags
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os/exec"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
var (
|
||||
titleFields = []string{
|
||||
"TITLE",
|
||||
"title",
|
||||
}
|
||||
albumFields = []string{
|
||||
"ALBUM",
|
||||
"album",
|
||||
}
|
||||
artistFields = []string{
|
||||
"ARTIST",
|
||||
"artist",
|
||||
}
|
||||
albumArtistFields = []string{
|
||||
"ALBUM ARTIST",
|
||||
"ALBUMARTIST",
|
||||
"ALBUM_ARTIST",
|
||||
"album artist",
|
||||
"album_artist",
|
||||
"albumartist",
|
||||
}
|
||||
composerFields = []string{
|
||||
"COMPOSER",
|
||||
"composer",
|
||||
}
|
||||
genreFields = []string{
|
||||
"GENRE",
|
||||
"genre",
|
||||
}
|
||||
yearFields = []string{
|
||||
"YEAR",
|
||||
"year",
|
||||
}
|
||||
trackFields = []string{
|
||||
"TRACK",
|
||||
"track",
|
||||
}
|
||||
totaltrackFields = []string{
|
||||
"TOTALTRACKS",
|
||||
"TRACKC",
|
||||
"TRACKTOTAL",
|
||||
"totaltracks",
|
||||
"trackc",
|
||||
"tracktotal",
|
||||
}
|
||||
discFields = []string{
|
||||
"DISC",
|
||||
"disc",
|
||||
}
|
||||
totaldiscFields = []string{
|
||||
"DISCC",
|
||||
"DISCTOTAL",
|
||||
"TOTALDISCS",
|
||||
"discc",
|
||||
"disctotal",
|
||||
"totaldiscs",
|
||||
}
|
||||
lyricsFields = []string{
|
||||
"LYRICS",
|
||||
"lyrics",
|
||||
}
|
||||
commentFields = []string{
|
||||
"COMMENT",
|
||||
"COMMENTS",
|
||||
"comment",
|
||||
"comments",
|
||||
}
|
||||
)
|
||||
|
||||
func firstExisting(keys *[]string, map_ *map[string]string) string {
|
||||
for _, field := range *keys {
|
||||
v, ok := (*map_)[field]
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
return v
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
type Metadata interface {
|
||||
Title() string
|
||||
Album() string
|
||||
Artist() string
|
||||
AlbumArtist() string
|
||||
Composer() string
|
||||
Genre() string
|
||||
Year() int
|
||||
Track() int
|
||||
TotalTracks() int
|
||||
Disc() int
|
||||
TotalDiscs() int
|
||||
Lyrics() string
|
||||
Comment() string
|
||||
Length() float64
|
||||
Format() string
|
||||
Bitrate() int
|
||||
}
|
||||
|
||||
type Track struct {
|
||||
format *probeFormat
|
||||
}
|
||||
|
||||
func (t *Track) Title() string {
|
||||
return firstExisting(&titleFields, &t.format.Tags)
|
||||
}
|
||||
|
||||
func (t *Track) Album() string {
|
||||
return firstExisting(&albumFields, &t.format.Tags)
|
||||
}
|
||||
|
||||
func (t *Track) Artist() string {
|
||||
return firstExisting(&artistFields, &t.format.Tags)
|
||||
}
|
||||
|
||||
func (t *Track) AlbumArtist() string {
|
||||
return firstExisting(&albumArtistFields, &t.format.Tags)
|
||||
}
|
||||
|
||||
func (t *Track) Composer() string {
|
||||
return firstExisting(&composerFields, &t.format.Tags)
|
||||
}
|
||||
|
||||
func (t *Track) Genre() string {
|
||||
return firstExisting(&genreFields, &t.format.Tags)
|
||||
}
|
||||
|
||||
func (t *Track) Year() int {
|
||||
i, _ := strconv.Atoi(firstExisting(&yearFields, &t.format.Tags))
|
||||
return i
|
||||
}
|
||||
|
||||
func (t *Track) Track() int {
|
||||
i, _ := strconv.Atoi(firstExisting(&trackFields, &t.format.Tags))
|
||||
return i
|
||||
}
|
||||
|
||||
func (t *Track) TotalTracks() int {
|
||||
i, _ := strconv.Atoi(firstExisting(&totaltrackFields, &t.format.Tags))
|
||||
return i
|
||||
}
|
||||
|
||||
func (t *Track) Disc() int {
|
||||
i, _ := strconv.Atoi(firstExisting(&discFields, &t.format.Tags))
|
||||
return i
|
||||
}
|
||||
|
||||
func (t *Track) TotalDiscs() int {
|
||||
i, _ := strconv.Atoi(firstExisting(&totaldiscFields, &t.format.Tags))
|
||||
return i
|
||||
}
|
||||
|
||||
func (t *Track) Lyrics() string {
|
||||
return firstExisting(&lyricsFields, &t.format.Tags)
|
||||
}
|
||||
|
||||
func (t *Track) Comment() string {
|
||||
return firstExisting(&commentFields, &t.format.Tags)
|
||||
}
|
||||
|
||||
func (t *Track) Format() string {
|
||||
return t.format.FormatName
|
||||
}
|
||||
|
||||
func (t *Track) Length() float64 {
|
||||
return t.format.Duration
|
||||
}
|
||||
|
||||
func (t *Track) Bitrate() int {
|
||||
return t.format.Bitrate
|
||||
}
|
||||
|
||||
func Read(filename string) (Metadata, error) {
|
||||
command := exec.Command(
|
||||
"ffprobe",
|
||||
"-print_format", "json",
|
||||
"-show_format",
|
||||
filename,
|
||||
)
|
||||
probe, err := command.Output()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("when running ffprobe with `%s`: %v",
|
||||
filename, err)
|
||||
}
|
||||
var data probeData
|
||||
err = json.Unmarshal(probe, &data)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("when unmarshalling: %v", err)
|
||||
}
|
||||
track := Track{
|
||||
format: data.Format,
|
||||
}
|
||||
return &track, nil
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
package tags
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestRead(t *testing.T) {
|
||||
start := time.Now()
|
||||
cwd, _ := os.Getwd()
|
||||
data, err := Read(
|
||||
fmt.Sprintf("%s/static/test_flac", cwd),
|
||||
)
|
||||
if err != nil {
|
||||
t.Errorf("when reading tags: %v\n", err)
|
||||
return
|
||||
}
|
||||
length := data.Length()
|
||||
if length != 160.4 {
|
||||
t.Errorf("expected length to be `160.4`, got %f", length)
|
||||
}
|
||||
bitrate := data.Bitrate()
|
||||
if bitrate != 815694 {
|
||||
t.Errorf("expected bitrate to be `815694`, got %d", bitrate)
|
||||
}
|
||||
format := data.Format()
|
||||
if format != "flac" {
|
||||
t.Errorf("expected format to be `flac`, got %s", format)
|
||||
}
|
||||
fmt.Println(data.Title())
|
||||
fmt.Println(data.Album())
|
||||
fmt.Println(data.AlbumArtist())
|
||||
fmt.Println(data.Year())
|
||||
fmt.Printf("it's been %s\n", time.Since(start))
|
||||
}
|
||||
@@ -21,9 +21,9 @@
|
||||
{{ end }}
|
||||
{{ if .CurrentLastFMAPIKey }}
|
||||
{{ if .User.LastFMSession }}
|
||||
<span class="light">current status</span> linked
|
||||
<span class="light">current status</span> <span class="happy">linked</span> <a href="/admin/unlink_lastfm_do">unlink</a><br/>
|
||||
{{ else }}
|
||||
<span class="light">current status</span> unlinked <a href="https://www.last.fm/api/auth/?api_key={{ .CurrentLastFMAPIKey }}&cb={{ .RequestRoot }}/admin/link_lastfm_callback">link</a><br/>
|
||||
<span class="light">current status</span> <span class="angry">unlinked</span> <a href="https://www.last.fm/api/auth/?api_key={{ .CurrentLastFMAPIKey }}&cb={{ .RequestRoot }}/admin/link_lastfm_do">link</a><br/>
|
||||
{{ end }}
|
||||
{{ else if not .User.IsAdmin }}
|
||||
<span class="light">api key not set. please ask your admin to set it</span>
|
||||
|
||||
6
vendor/github.com/twinj/uuid/.gitignore
generated
vendored
6
vendor/github.com/twinj/uuid/.gitignore
generated
vendored
@@ -1,6 +0,0 @@
|
||||
*.iml
|
||||
/savers/*generator-*
|
||||
/savers/generator-*
|
||||
/vendor/
|
||||
*.out
|
||||
cover*.html
|
||||
34
vendor/github.com/twinj/uuid/.travis.yml
generated
vendored
34
vendor/github.com/twinj/uuid/.travis.yml
generated
vendored
@@ -1,34 +0,0 @@
|
||||
language: go
|
||||
|
||||
sudo: false
|
||||
|
||||
go_import_path: github.com/myesui/uuid
|
||||
|
||||
go:
|
||||
- 1.8
|
||||
- 1.7
|
||||
- 1.6
|
||||
|
||||
os:
|
||||
- linux
|
||||
- osx
|
||||
|
||||
env:
|
||||
global:
|
||||
- PATH=$HOME/gopath/bin:$PATH
|
||||
|
||||
before_script:
|
||||
- gofmt -s -l -e .
|
||||
- go vet ./...
|
||||
|
||||
before_install:
|
||||
- go get -t -v ./...
|
||||
- go get github.com/mattn/goveralls
|
||||
|
||||
script:
|
||||
- go test -v -race github.com/myesui/uuid
|
||||
- go test -v -covermode=count -coverprofile=cover.out
|
||||
- goveralls -coverprofile=cover.out -service=travis-ci
|
||||
|
||||
notifications:
|
||||
email: true
|
||||
20
vendor/github.com/twinj/uuid/LICENSE
generated
vendored
20
vendor/github.com/twinj/uuid/LICENSE
generated
vendored
@@ -1,20 +0,0 @@
|
||||
Copyright (C) 2011 by Krzysztof Kowalik <chris@nu7hat.ch>
|
||||
Copyright (C) 2016 by Daniel Kemp <twinj@github.com> Derivative work
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do
|
||||
so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
311
vendor/github.com/twinj/uuid/README.md
generated
vendored
311
vendor/github.com/twinj/uuid/README.md
generated
vendored
@@ -1,311 +0,0 @@
|
||||
Go UUID implementation
|
||||
========================
|
||||
|
||||
[](https://raw.githubusercontent.com/myesui/uuid/master/LICENSE)
|
||||
[](http://godoc.org/github.com/myesui/uuid)
|
||||
[](https://ci.appveyor.com/project/myesui/uuid)
|
||||
[](https://travis-ci.org/myesui/uuid)
|
||||
[](https://coveralls.io/github/myesui/uuid?branch=master)
|
||||
[](https://goreportcard.com/report/github.com/myesui/uuid)
|
||||
|
||||
This package provides RFC 4122 and DCE 1.1 compliant UUIDs.
|
||||
It will generate the following:
|
||||
|
||||
* Version 1: based on a Timestamp and MAC address as Node id
|
||||
* Version 2: based on DCE Security - Experimental
|
||||
* Version 3: based on MD5 hash
|
||||
* Version 4: based on cryptographically secure random numbers
|
||||
* Version 5: based on SHA-1 hash
|
||||
|
||||
Functions NewV1, NewV2, NewV3, NewV4, NewV5, New, NewHex and Parse() for
|
||||
generating version 1, 2, 3, 4 and 5 Uuid's
|
||||
|
||||
# Requirements
|
||||
|
||||
Will generally support last 3 versions of Go.
|
||||
|
||||
- 1.8
|
||||
- 1.7
|
||||
- 1.6
|
||||
|
||||
## Installation
|
||||
|
||||
Use the `go` tool:
|
||||
|
||||
$ go get gopkg.in/myesui/uuid.v1
|
||||
|
||||
|
||||
See [gopkg.in](http://labix.org/gopkg.in)
|
||||
|
||||
# Typical Usage
|
||||
|
||||
See [documentation and examples](http://godoc.org/github.com/myesui/uuid)
|
||||
for more information.
|
||||
|
||||
## All UUIDs
|
||||
|
||||
import "gopkg.in/myesui/uuid.v1"
|
||||
|
||||
id, _ := uuid.Parse("6ba7b810-9dad-11d1-80b4-00c04fd430c8")
|
||||
|
||||
if uuid.Equal(id, uuid.NameSpaceDNS) {
|
||||
fmt.Println("Alas these are equal")
|
||||
}
|
||||
|
||||
if uuid.Compare(id, uuid.NameSpaceDNS) == 0 {
|
||||
fmt.Println("They are also equal")
|
||||
}
|
||||
|
||||
if uuid.Compare(id, uuid.NameSpaceX500) == -1 {
|
||||
fmt.Println("id < uuid.NameSpaceX500")
|
||||
}
|
||||
|
||||
if uuid.Compare(uuid.NameSpaceX50, id) == 1 {
|
||||
fmt.Println("uuid.NameSpaceX500 > id")
|
||||
}
|
||||
|
||||
// Default Format is FormatCanonical
|
||||
fmt.Println(uuid.Formatter(id, uuid.FormatCanonicalCurly))
|
||||
|
||||
uuid.SwitchFormat(uuid.FormatCanonicalBracket)
|
||||
|
||||
## Formatting UUIDs
|
||||
|
||||
The default format is uuid.FormatCanonical xxxxxxxx-xxxx-xxxx-xxxx-xxxxxx
|
||||
|
||||
Any call to uuid.String() will produce this output.
|
||||
|
||||
The format is twice as fast as the others at producing a string from the bytes.
|
||||
|
||||
To change to another format permanently use:
|
||||
|
||||
uuid.SwitchFormat(uuid.Format*)
|
||||
uuid.SwitchFormatToUpper(uuid.Format*)
|
||||
|
||||
Once this has been called in an init function all UUID.String() calls will use the new format.
|
||||
|
||||
Available formats:
|
||||
|
||||
FormatHex = xxxxxxxxxxxxxxxxxxxxxxxxxx
|
||||
FormatHexCurly = {xxxxxxxxxxxxxxxxxxxxxxxxxx}
|
||||
FormatHexBracket = (xxxxxxxxxxxxxxxxxxxxxxxxxx)
|
||||
|
||||
// This is the default format.
|
||||
FormatCanonical Format = xxxxxxxx-xxxx-xxxx-xxxx-xxxxxx
|
||||
|
||||
FormatCanonicalCurly = {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxx}
|
||||
FormatCanonicalBracket = (xxxxxxxx-xxxx-xxxx-xxxx-xxxxxx)
|
||||
FormatUrn = urn:uuid:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxx
|
||||
|
||||
The uuid.Formatter function also exists and is only ever meant to be used for one time prints where a different format from the default or switched format is required. You can supply your own format as long as it fits the pattern.
|
||||
which contains %x for the five groups in an UUID. Eg: FormatCanonical = %x-%x-%x-%x-%x
|
||||
|
||||
You can also stwict to a custom format
|
||||
|
||||
Note: AT this time cutsom formats are not supported for TextMarshalling. If a custom format is deteced it will use the canonical format. Use a call to String() and save as a string instead.
|
||||
|
||||
## Version 1 and 2 UUIDs
|
||||
|
||||
import "gopkg.in/myesui/uuid.v1"
|
||||
|
||||
id := uuid.NewV1()
|
||||
fmt.Println(id)
|
||||
fmt.Printf("version %s variant %x: %s\n", u1.Version(), u1.Variant(), id)
|
||||
|
||||
id = uuid.NewV2(uuid.DomainUser)
|
||||
fmt.Println(id)
|
||||
fmt.Printf("version %s variant %x: %s\n", u1.Version(), u1.Variant(), id)
|
||||
|
||||
ids := uuid.BulkV1(500)
|
||||
for _, v := range ids {
|
||||
fmt.Println(v)
|
||||
}
|
||||
|
||||
ids = make([]UUID, 100)
|
||||
ReadV1(ids)
|
||||
for _, v := range ids {
|
||||
fmt.Println(v)
|
||||
}
|
||||
|
||||
// If you wish to register a saving mechanism to keep track of your UUIDs over restarts
|
||||
// It is recommeneded to add a Saver so as to reduce risk in UUID collisions
|
||||
saver := savers.FileSystemSaver.Init()
|
||||
|
||||
// Must be called before any V1 or V2 UUIDs. Do not call other uuid.Register* if
|
||||
// registering a Saver
|
||||
uuid.RegisterSaver(saver)
|
||||
|
||||
## Version 3 and 5 UUIDs
|
||||
|
||||
import "gopkg.in/myesui/uuid.v1"
|
||||
|
||||
id := uuid.NewV3(uuid.NameSpaceURL, uuid.Name("www.example.com"))
|
||||
fmt.Println(id)
|
||||
fmt.Printf("version %s variant %x: %s\n", u1.Version(), u1.Variant(), id)
|
||||
|
||||
id := uuid.NewV5(uuid.NameSpaceURL, uuid.Name("www.example.com"))
|
||||
fmt.Println(id)
|
||||
fmt.Printf("version %s variant %x: %s\n", u1.Version(), u1.Variant(), id)
|
||||
|
||||
id = uuid.NewV5(uuid.NameSpaceURL, id)
|
||||
fmt.Println(id)
|
||||
fmt.Printf("version %s variant %x: %s\n", u1.Version(), u1.Variant(), id)
|
||||
|
||||
## Version 4 UUIDs
|
||||
|
||||
import "gopkg.in/myesui/uuid.v1"
|
||||
|
||||
// A V4 UUID will panic by default if the systems CPRNG fails - this can
|
||||
// be changed by registering your own generator
|
||||
u4 := uuid.NewV4()
|
||||
fmt.Println(id)
|
||||
fmt.Printf("version %d variant %x: %s\n", u4.Version(), u4.Variant(), u4)
|
||||
|
||||
ids := uuid.BulkV4(500)
|
||||
for _, v := range ids {
|
||||
fmt.Println(v)
|
||||
}
|
||||
|
||||
ids := make([]UUID, 100)
|
||||
ReadV4(ids)
|
||||
for _, v := range ids {
|
||||
fmt.Println(v)
|
||||
}
|
||||
|
||||
## Custom Generators
|
||||
|
||||
import "gopkg.in/myesui/uuid.v1"
|
||||
|
||||
// Improve resolution for V1 and 2 UUIDs
|
||||
// The resolution correlates to how many ids can be created before waiting
|
||||
// for the next unique timestamp. The default is a low 1024, this equates
|
||||
// to Ids that can be created in 100 nanoseconds. It is low to encourage
|
||||
// you to set it.
|
||||
uuid.RegisterGenerator(&GeneratorConfig{Resolution: 18465})
|
||||
|
||||
// Provide your own node Id or MAC address
|
||||
uuid.RegisterGenerator(&GeneratorConfig{
|
||||
Id: func() uuid.Node{
|
||||
// My Node Id
|
||||
// If this returns nil a random one will be generated
|
||||
},
|
||||
})
|
||||
|
||||
// Replace the default Timestamp spinner with your own.
|
||||
uuid.RegisterGenerator(&GeneratorConfig{
|
||||
Next: func()(uuid.Timestamp){
|
||||
// My own Timestamp function...
|
||||
// Resolution will become reduendant if you set this.
|
||||
// The package will increment the clock sequence if you produce equal Timestamps
|
||||
},
|
||||
})
|
||||
|
||||
// Replace the default crypto/rand.Read CPRNG with your own.
|
||||
uuid.RegisterGenerator(&GeneratorConfig{
|
||||
Random: func([]byte)(int, error){
|
||||
// My CPRNG function...
|
||||
},
|
||||
})
|
||||
|
||||
// type HandleRandomError func([]byte, int, error) error
|
||||
|
||||
// Replace the default random number error handler for V4 UUIDs. This function is called
|
||||
// when there is an error in the crypto/rand CPRNG. The default error handler function reads
|
||||
// from math.Rand as a fallback.
|
||||
//
|
||||
// You can change that behaviour and handle the error by providing your own function.
|
||||
//
|
||||
// Errors could be due to a lack of system entropy or some other serious issue. These issues are rare,
|
||||
// however, having the tools to handle such issues is important.
|
||||
// This approach was taken as each user of this package will want to handle this differently.
|
||||
//
|
||||
// For example one user of the package might want to just panic instead.
|
||||
// Returning an error will cause a panic.
|
||||
|
||||
uuid.RegisterGenerator(&GeneratorConfig{
|
||||
HandleError: func(id []byte, n int, err error)bool{
|
||||
return err
|
||||
},
|
||||
})
|
||||
|
||||
// You can also just generate your own completely.
|
||||
myGenerator := NewGenerator(nil)
|
||||
|
||||
id := myGenerator.NewV4()
|
||||
|
||||
// You can replace the logger
|
||||
uuid.RegisterGenerator(&GeneratorConfig{
|
||||
Logger: log.New(someWriter, "my-prefix", myFlags),
|
||||
})
|
||||
|
||||
|
||||
## Coverage
|
||||
|
||||
* go test -coverprofile cover.out github.com/myesui/uuid
|
||||
* go test -coverprofile cover.out github.com/myesui/uuid/savers
|
||||
|
||||
* go tool cover -html=cover.out -o cover.html
|
||||
|
||||
## Contribution
|
||||
|
||||
1. fork from the *master* branch to create your own fork
|
||||
2. clone from *master* into $GOPATH/src/github.com/myesui/uuid
|
||||
3. git remote add `username` https://github.com/username/uuid.git
|
||||
4. push changes on your fork and track your remote
|
||||
5. Remember to create a branch
|
||||
|
||||
To ensure you get the correct packages and subpackages install in a gopath which matches *go/src/github.com/myesui/uuid*
|
||||
|
||||
## Links
|
||||
|
||||
* [RFC 4122](http://www.ietf.org/rfc/rfc4122.txt)
|
||||
* [DCE 1.1: Authentication and Security Services](http://pubs.opengroup.org/onlinepubs/9629399/apdxa.htm)
|
||||
|
||||
# Design considerations
|
||||
|
||||
* UUID is an interface which correlates to
|
||||
|
||||
* V1 UUIDs are sequential. This can cause the Generator to work
|
||||
more slowly compared to other implementations. It can however be manually tuned
|
||||
to have performance that is on par. This is achieved by setting the Timestamp
|
||||
Resolution. Benchmark tests have been provided to help determine the best
|
||||
setting for your server
|
||||
|
||||
Proper test coverage has determined thant the UUID timestamp spinner works
|
||||
correctly, across multiple clock resolutions. The generator produces
|
||||
timestamps that roll out sequentially and will only modify the clock
|
||||
sequence on very rare circumstances.
|
||||
|
||||
It is highly recommended that you register a uuid.Saver if you use V1 or V2
|
||||
UUIDs as it will ensure a higher probability of uniqueness.
|
||||
|
||||
Example V1 output:
|
||||
5fb1a280-30f0-11e6-9614-005056c00001
|
||||
5fb1a281-30f0-11e6-9614-005056c00001
|
||||
5fb1a282-30f0-11e6-9614-005056c00001
|
||||
5fb1a283-30f0-11e6-9614-005056c00001
|
||||
5fb1a284-30f0-11e6-9614-005056c00001
|
||||
5fb1a285-30f0-11e6-9614-005056c00001
|
||||
5fb1a286-30f0-11e6-9614-005056c00001
|
||||
5fb1a287-30f0-11e6-9614-005056c00001
|
||||
5fb1a288-30f0-11e6-9614-005056c00001
|
||||
5fb1a289-30f0-11e6-9614-005056c00001
|
||||
5fb1a28a-30f0-11e6-9614-005056c00001
|
||||
5fb1a28b-30f0-11e6-9614-005056c00001
|
||||
5fb1a28c-30f0-11e6-9614-005056c00001
|
||||
5fb1a28d-30f0-11e6-9614-005056c00001
|
||||
5fb1a28e-30f0-11e6-9614-005056c00001
|
||||
5fb1a28f-30f0-11e6-9614-005056c00001
|
||||
5fb1a290-30f0-11e6-9614-005056c00001
|
||||
|
||||
* The V1 UUID generator should be file system and server agnostic
|
||||
To achieve this there are:
|
||||
** No Os locking threads or file system dependant storage
|
||||
** Provided the uuid.Saver interface so a package can implement its own solution if required
|
||||
* The V4 UUID should allow a package to handle any error that can occur in the CPRNG. The default is to read from math.Rand``````.
|
||||
* The package should be able to handle multiple instances of Generators so a package can produce UUIDs from multiple sources.
|
||||
|
||||
## Copyright
|
||||
|
||||
Copyright (C) 2017 myesui@github.com
|
||||
See [LICENSE](https://github.com/myesui/uuid/tree/master/LICENSE) file for details.
|
||||
30
vendor/github.com/twinj/uuid/appveyor.yml
generated
vendored
30
vendor/github.com/twinj/uuid/appveyor.yml
generated
vendored
@@ -1,30 +0,0 @@
|
||||
# version format
|
||||
version: "{build}"
|
||||
|
||||
# Operating system (build VM template)
|
||||
os: Windows Server 2012 R2
|
||||
|
||||
clone_folder: c:\gopath\src\github.com\myesui\uuid
|
||||
|
||||
# environment variables
|
||||
environment:
|
||||
GOPATH: c:\gopath
|
||||
|
||||
# scripts that run after cloning repository
|
||||
install:
|
||||
- set PATH=%GOPATH%\bin;c:\go\bin;%PATH%
|
||||
- go version
|
||||
- go env
|
||||
- go get -t -v ./...
|
||||
|
||||
# to run your custom scripts instead of automatic MSBuild
|
||||
build_script:
|
||||
- go vet -x ./...
|
||||
- gofmt -s -l -e .
|
||||
- go test ./... -v -short -race
|
||||
|
||||
# to disable automatic tests
|
||||
test: off
|
||||
|
||||
# to disable deployment
|
||||
deploy: off
|
||||
161
vendor/github.com/twinj/uuid/format.go
generated
vendored
161
vendor/github.com/twinj/uuid/format.go
generated
vendored
@@ -1,161 +0,0 @@
|
||||
package uuid
|
||||
|
||||
import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Format represents different styles a UUID can be printed in constants
|
||||
// represent a pattern used by the package with which to print a UUID.
|
||||
type Format string
|
||||
|
||||
// The following are the default Formats supplied by the uuid package.
|
||||
const (
|
||||
FormatHex Format = "%x%x%x%x%x"
|
||||
FormatHexCurly Format = "{%x%x%x%x%x}"
|
||||
FormatHexBracket Format = "(%x%x%x%x%x)"
|
||||
|
||||
// FormatCanonical is the default format.
|
||||
FormatCanonical Format = "%x-%x-%x-%x-%x"
|
||||
|
||||
FormatCanonicalCurly Format = "{%x-%x-%x-%x-%x}"
|
||||
FormatCanonicalBracket Format = "(%x-%x-%x-%x-%x)"
|
||||
FormatUrn Format = "urn:uuid:" + FormatCanonical
|
||||
)
|
||||
|
||||
var (
|
||||
printFormat = FormatCanonical
|
||||
defaultFormats map[Format]bool = make(map[Format]bool)
|
||||
)
|
||||
|
||||
func init() {
|
||||
defaultFormats[FormatHex] = true
|
||||
defaultFormats[FormatHexCurly] = true
|
||||
defaultFormats[FormatHexBracket] = true
|
||||
defaultFormats[FormatCanonical] = true
|
||||
defaultFormats[FormatCanonicalCurly] = true
|
||||
defaultFormats[FormatCanonicalBracket] = true
|
||||
defaultFormats[FormatUrn] = true
|
||||
}
|
||||
|
||||
// SwitchFormat switches the default printing format for ALL UUIDs.
|
||||
//
|
||||
// The default is canonical uuid.Format.FormatCanonical which has been
|
||||
// optimised for use with this package. It is twice as fast compared to other
|
||||
// formats. However, non package formats are still very quick.
|
||||
//
|
||||
// A valid format will have 5 groups of [%x|%X] or follow the pattern,
|
||||
// *%[xX]*%[xX]*%[xX]*%[xX]*%[xX]*. If the supplied format does not meet this
|
||||
// standard the function will panic. Note any extra uses of [%] outside of the
|
||||
// [%x|%X] will also cause a panic.
|
||||
// Constant uuid.Formats have been provided for most likely formats.
|
||||
func SwitchFormat(form Format) {
|
||||
checkFormat(form)
|
||||
printFormat = form
|
||||
}
|
||||
|
||||
// SwitchFormatToUpper is a convenience function to set the uuid.Format to uppercase
|
||||
// versions.
|
||||
func SwitchFormatToUpper(form Format) {
|
||||
SwitchFormat(Format(strings.ToUpper(string(form))))
|
||||
}
|
||||
|
||||
// Formatter will return a string representation of the given UUID.
|
||||
//
|
||||
// Use this for one time formatting when setting the Format using
|
||||
// uuid.SwitchFormat would be overkill.
|
||||
//
|
||||
// A valid format will have 5 groups of [%x|%X] or follow the pattern,
|
||||
// *%[xX]*%[xX]*%[xX]*%[xX]*%[xX]*. If the supplied format does not meet this
|
||||
// standard the function will panic. Note any extra uses of [%] outside of the
|
||||
// [%x|%X] will also cause a panic.
|
||||
func Formatter(id Implementation, form Format) string {
|
||||
checkFormat(form)
|
||||
return formatUuid(id.Bytes(), form)
|
||||
}
|
||||
|
||||
func checkFormat(form Format) {
|
||||
if defaultFormats[form] {
|
||||
return
|
||||
}
|
||||
s := strings.ToLower(string(form))
|
||||
if strings.Count(s, "%x") != 5 {
|
||||
panic("uuid: invalid format")
|
||||
}
|
||||
s = strings.Replace(s, "%x", "", -1)
|
||||
if strings.Count(s, "%") > 0 {
|
||||
panic("uuid: invalid format")
|
||||
}
|
||||
}
|
||||
|
||||
const (
|
||||
hexTable = "0123456789abcdef"
|
||||
hexUpperTable = "0123456789ABCDEF"
|
||||
|
||||
canonicalLength = length*2 + 4
|
||||
formatArgCount = 10
|
||||
uuidStringBufferSize = length*2 - formatArgCount
|
||||
)
|
||||
|
||||
var groups = [...]int{4, 2, 2, 2, 6}
|
||||
|
||||
func formatUuid(src []byte, form Format) string {
|
||||
if form == FormatCanonical {
|
||||
return string(formatCanonical(src))
|
||||
}
|
||||
return string(format(src, string(form)))
|
||||
}
|
||||
|
||||
func format(src []byte, form string) []byte {
|
||||
end := len(form)
|
||||
buf := make([]byte, end+uuidStringBufferSize)
|
||||
|
||||
var s, ls, b, e, p int
|
||||
var u bool
|
||||
for _, v := range groups {
|
||||
ls = s
|
||||
for ; s < end && form[s] != '%'; s++ {
|
||||
}
|
||||
copy(buf[p:], form[ls:s])
|
||||
p += s - ls
|
||||
s++
|
||||
u = form[s] == 'X'
|
||||
s++
|
||||
e = b + v
|
||||
for i, t := range src[b:e] {
|
||||
j := p + i + i
|
||||
table := hexTable
|
||||
if u {
|
||||
table = hexUpperTable
|
||||
}
|
||||
buf[j] = table[t>>4]
|
||||
buf[j+1] = table[t&0x0f]
|
||||
}
|
||||
b = e
|
||||
p += v + v
|
||||
}
|
||||
ls = s
|
||||
for ; s < end && form[s] != '%'; s++ {
|
||||
}
|
||||
copy(buf[p:], form[ls:s])
|
||||
return buf
|
||||
}
|
||||
|
||||
func formatCanonical(src []byte) []byte {
|
||||
buf := make([]byte, canonicalLength)
|
||||
var b, p, e int
|
||||
for h, v := range groups {
|
||||
e = b + v
|
||||
for i, t := range src[b:e] {
|
||||
j := p + i + i
|
||||
buf[j] = hexTable[t>>4]
|
||||
buf[j+1] = hexTable[t&0x0f]
|
||||
}
|
||||
b = e
|
||||
p += v + v
|
||||
if h < 4 {
|
||||
buf[p] = '-'
|
||||
p += 1
|
||||
}
|
||||
}
|
||||
return buf
|
||||
}
|
||||
527
vendor/github.com/twinj/uuid/generator.go
generated
vendored
527
vendor/github.com/twinj/uuid/generator.go
generated
vendored
@@ -1,527 +0,0 @@
|
||||
package uuid
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/md5"
|
||||
"crypto/rand"
|
||||
"crypto/sha1"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"hash"
|
||||
"log"
|
||||
mrand "math/rand"
|
||||
"net"
|
||||
"os"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
var (
|
||||
once = new(sync.Once)
|
||||
generator = newGenerator(nil)
|
||||
)
|
||||
|
||||
func init() {
|
||||
seed := time.Now().UTC().UnixNano()
|
||||
b := [8]byte{}
|
||||
_, err := rand.Read(b[:])
|
||||
if err == nil {
|
||||
seed += int64(binary.BigEndian.Uint64(b[:]))
|
||||
}
|
||||
mrand.Seed(seed)
|
||||
|
||||
}
|
||||
|
||||
// Random provides a random number generator which reads into the given []byte, the package
|
||||
// uses crypto/rand.Read by default. You can supply your own implementation or downgrade it
|
||||
// to the match/rand package.
|
||||
//
|
||||
// The function is used by V4 UUIDs and for setting up V1 and V2 UUIDs in the
|
||||
// Generator Init or Register* functions.
|
||||
type Random func([]byte) (int, error)
|
||||
|
||||
// Next provides the next Timestamp value to be used by the next V1 or V2 UUID.
|
||||
// The default uses the uuid.spinner which spins at a resolution of
|
||||
// 100ns ticks and provides a spin resolution redundancy of 1024
|
||||
// cycles. This ensures that the system is not too quick when
|
||||
// generating V1 or V2 UUIDs. Each system requires a tuned Resolution to
|
||||
// enhance performance.
|
||||
type Next func() Timestamp
|
||||
|
||||
// Identifier provides the Node to be used during the life of a
|
||||
// uuid.Generator. If it cannot be determined nil should be returned, the
|
||||
// package will then provide a node identifier provided by the Random function.
|
||||
// The default generator gets a MAC address from the first interface that is 'up' checking
|
||||
// net.FlagUp.
|
||||
type Identifier func() Node
|
||||
|
||||
// HandleRandomError provides the ability to manage a serious error that may be
|
||||
// caused by accessing the standard crypto/rand library or the supplied uuid/Random
|
||||
// function. Due to the rarity of this occurrence the error is swallowed by the
|
||||
// uuid/NewV4 function which relies heavily on random numbers, the package will
|
||||
// panic instead if an error occurs.
|
||||
//
|
||||
// You can change this behaviour by passing in your own uuid/HandleError
|
||||
// function to a custom Generator. This function can attempt to fix the random
|
||||
// number generator. If your uuid/HandleError returns true the generator will
|
||||
// attempt to generate another V4 uuid. If another error occurs the function
|
||||
// will return a fallback v4 uuid generated from the less random math/rand standard library.
|
||||
//
|
||||
// Waiting for system entropy may be all that is required in the initial error.
|
||||
// If something more serious has occurred, handle appropriately using this function.
|
||||
type HandleRandomError func([]byte, int, error) error
|
||||
|
||||
// Generator is used to create and monitor the running of V1 and V2, and V4
|
||||
// UUIDs. It can be setup to take custom implementations for Timestamp, Node
|
||||
// and Random number retrieval by providing those functions as required.
|
||||
// You can also supply a uuid/Saver implementation for saving the state of the generator
|
||||
// and you can also provide an error policy for V4 UUIDs and possible errors in the random
|
||||
// number generator.
|
||||
type Generator struct {
|
||||
// Access to the store needs to be maintained
|
||||
sync.Mutex
|
||||
|
||||
// Once ensures that the generator is only setup and initialised once.
|
||||
// This will occur either when you explicitly call the
|
||||
// uuid.Generator.Init function or when a V1 or V2 id is generated.
|
||||
sync.Once
|
||||
|
||||
// Store contains the current values being used by the Generator.
|
||||
*Store
|
||||
|
||||
// Identifier as per the type Identifier func() Node
|
||||
Identifier
|
||||
|
||||
// HandleRandomError as per the type HandleError func(error) bool
|
||||
HandleRandomError
|
||||
|
||||
// Next as per the type Next func() Timestamp
|
||||
Next
|
||||
|
||||
// Random as per the type Random func([]byte) (int, error)
|
||||
Random
|
||||
|
||||
// Saver provides a non-volatile store to save the state of the
|
||||
// generator, the default is nil which will cause the timestamp
|
||||
// clock sequence to populate with random data. You can register your
|
||||
// own saver by using the uuid.RegisterSaver function or by creating
|
||||
// your own uuid.Generator instance.
|
||||
// UUIDs.
|
||||
Saver
|
||||
|
||||
*log.Logger
|
||||
}
|
||||
|
||||
// GeneratorConfig allows you to setup a new uuid.Generator using uuid.NewGenerator or RegisterGenerator. You can supply your own
|
||||
// implementations for the random number generator Random, Identifier and Timestamp retrieval. You can also
|
||||
// adjust the resolution of the default Timestamp spinner and supply your own
|
||||
// error handler for crypto/rand failures.
|
||||
type GeneratorConfig struct {
|
||||
Saver
|
||||
Next
|
||||
Resolution uint
|
||||
Identifier
|
||||
Random
|
||||
HandleRandomError
|
||||
*log.Logger
|
||||
}
|
||||
|
||||
// NewGenerator will create a new uuid.Generator with the given functions.
|
||||
func NewGenerator(config *GeneratorConfig) (*Generator, error) {
|
||||
return onceDo(newGenerator(config))
|
||||
}
|
||||
|
||||
func onceDo(gen *Generator) (*Generator, error) {
|
||||
var err error
|
||||
gen.Do(func() {
|
||||
err = gen.init()
|
||||
if err != nil {
|
||||
gen = nil
|
||||
}
|
||||
})
|
||||
return gen, err
|
||||
}
|
||||
|
||||
func newGenerator(config *GeneratorConfig) (gen *Generator) {
|
||||
if config == nil {
|
||||
config = new(GeneratorConfig)
|
||||
}
|
||||
gen = new(Generator)
|
||||
if config.Next == nil {
|
||||
if config.Resolution == 0 {
|
||||
config.Resolution = defaultSpinResolution
|
||||
}
|
||||
gen.Next = (&spinner{
|
||||
Resolution: config.Resolution,
|
||||
Count: 0,
|
||||
Timestamp: Now(),
|
||||
now: Now,
|
||||
}).next
|
||||
} else {
|
||||
gen.Next = config.Next
|
||||
}
|
||||
if config.Identifier == nil {
|
||||
gen.Identifier = findFirstHardwareAddress
|
||||
} else {
|
||||
gen.Identifier = config.Identifier
|
||||
}
|
||||
if config.Random == nil {
|
||||
gen.Random = rand.Read
|
||||
} else {
|
||||
gen.Random = config.Random
|
||||
}
|
||||
if config.HandleRandomError == nil {
|
||||
gen.HandleRandomError = gen.runHandleError
|
||||
} else {
|
||||
gen.HandleRandomError = config.HandleRandomError
|
||||
}
|
||||
if config.Logger == nil {
|
||||
gen.Logger = log.New(os.Stderr, "uuid: ", log.LstdFlags)
|
||||
} else {
|
||||
gen.Logger = config.Logger
|
||||
}
|
||||
gen.Saver = config.Saver
|
||||
gen.Store = new(Store)
|
||||
return
|
||||
}
|
||||
|
||||
// RegisterGenerator will set the package generator with the given configuration
|
||||
// Like uuid.Init this can only be called once. Any subsequent calls will have no
|
||||
// effect. If you call this you do not need to call uuid.Init.
|
||||
func RegisterGenerator(config *GeneratorConfig) (err error) {
|
||||
notOnce := true
|
||||
once.Do(func() {
|
||||
generator, err = NewGenerator(config)
|
||||
notOnce = false
|
||||
return
|
||||
})
|
||||
if notOnce {
|
||||
panic("uuid: Register* methods cannot be called more than once.")
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (o *Generator) read() {
|
||||
|
||||
// Save the state (current timestamp, clock sequence, and node ID)
|
||||
// back to the stable store
|
||||
if o.Saver != nil {
|
||||
defer o.save()
|
||||
}
|
||||
|
||||
// Obtain a lock
|
||||
o.Lock()
|
||||
defer o.Unlock()
|
||||
|
||||
// Get the current time as a 60-bit count of 100-nanosecond intervals
|
||||
// since 00:00:00.00, 15 October 1582.
|
||||
now := o.Next()
|
||||
|
||||
// If the last timestamp is later than
|
||||
// the current timestamp, increment the clock sequence value.
|
||||
if now <= o.Timestamp {
|
||||
o.Sequence++
|
||||
}
|
||||
|
||||
// Update the timestamp
|
||||
o.Timestamp = now
|
||||
}
|
||||
|
||||
func (o *Generator) init() error {
|
||||
// From a system-wide shared stable store (e.g., a file), read the
|
||||
// UUID generator state: the values of the timestamp, clock sequence,
|
||||
// and node ID used to generate the last UUID.
|
||||
var (
|
||||
storage Store
|
||||
err error
|
||||
)
|
||||
|
||||
o.Lock()
|
||||
defer o.Unlock()
|
||||
|
||||
if o.Saver != nil {
|
||||
storage, err = o.Read()
|
||||
if err != nil {
|
||||
o.Saver = nil
|
||||
}
|
||||
}
|
||||
|
||||
// Get the current time as a 60-bit count of 100-nanosecond intervals
|
||||
// since 00:00:00.00, 15 October 1582.
|
||||
now := o.Next()
|
||||
|
||||
// Get the current node id
|
||||
node := o.Identifier()
|
||||
|
||||
if node == nil {
|
||||
o.Println("address error generating random node id")
|
||||
|
||||
node = make([]byte, 6)
|
||||
n, err := o.Random(node)
|
||||
if err != nil {
|
||||
o.Printf("could not read random bytes into node - read [%d] %s", n, err)
|
||||
return err
|
||||
}
|
||||
// Mark as randomly generated
|
||||
node[0] |= 0x01
|
||||
}
|
||||
|
||||
// If the state was unavailable (e.g., non-existent or corrupted), or
|
||||
// the saved node ID is different than the current node ID, generate
|
||||
// a random clock sequence value.
|
||||
if o.Saver == nil || !bytes.Equal(storage.Node, node) {
|
||||
|
||||
// 4.1.5. Clock Sequence https://www.ietf.org/rfc/rfc4122.txt
|
||||
//
|
||||
// For UUID version 1, the clock sequence is used to help avoid
|
||||
// duplicates that could arise when the clock is set backwards in time
|
||||
// or if the node ID changes.
|
||||
//
|
||||
// If the clock is set backwards, or might have been set backwards
|
||||
// (e.g., while the system was powered off), and the UUID generator can
|
||||
// not be sure that no UUIDs were generated with timestamps larger than
|
||||
// the value to which the clock was set, then the clock sequence has to
|
||||
// be changed. If the previous value of the clock sequence is known, it
|
||||
// can just be incremented; otherwise it should be set to a random or
|
||||
// high-quality pseudo-random value.
|
||||
|
||||
// The clock sequence MUST be originally (i.e., once in the lifetime of
|
||||
// a system) initialized to a random number to minimize the correlation
|
||||
// across systems. This provides maximum protection against node
|
||||
// identifiers that may move or switch from system to system rapidly.
|
||||
// The initial value MUST NOT be correlated to the node identifier.
|
||||
b := make([]byte, 2)
|
||||
n, err := o.Random(b)
|
||||
if err == nil {
|
||||
storage.Sequence = Sequence(binary.BigEndian.Uint16(b))
|
||||
o.Printf("initialised random sequence [%d]", storage.Sequence)
|
||||
|
||||
} else {
|
||||
o.Printf("could not read random bytes into sequence - read [%d] %s", n, err)
|
||||
return err
|
||||
}
|
||||
} else if now < storage.Timestamp {
|
||||
// If the state was available, but the saved timestamp is later than
|
||||
// the current timestamp, increment the clock sequence value.
|
||||
storage.Sequence++
|
||||
}
|
||||
|
||||
storage.Timestamp = now
|
||||
storage.Node = node
|
||||
|
||||
o.Store = &storage
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (o *Generator) save() {
|
||||
func(state *Generator) {
|
||||
if state.Saver != nil {
|
||||
state.Lock()
|
||||
defer state.Unlock()
|
||||
state.Save(*state.Store)
|
||||
}
|
||||
}(o)
|
||||
}
|
||||
|
||||
// NewV1 generates a new RFC4122 version 1 UUID based on a 60 bit timestamp and
|
||||
// node id.
|
||||
func (o *Generator) NewV1() UUID {
|
||||
o.read()
|
||||
id := UUID{}
|
||||
|
||||
makeUuid(&id,
|
||||
uint32(o.Timestamp),
|
||||
uint16(o.Timestamp>>32),
|
||||
uint16(o.Timestamp>>48),
|
||||
uint16(o.Sequence),
|
||||
o.Node)
|
||||
|
||||
id.setRFC4122Version(VersionOne)
|
||||
return id
|
||||
}
|
||||
|
||||
// ReadV1 will read a slice of UUIDs. Be careful with the set amount.
|
||||
func (o *Generator) ReadV1(ids []UUID) {
|
||||
for i := range ids {
|
||||
ids[i] = o.NewV1()
|
||||
}
|
||||
}
|
||||
|
||||
// BulkV1 will return a slice of V1 UUIDs. Be careful with the set amount.
|
||||
func (o *Generator) BulkV1(amount int) []UUID {
|
||||
ids := make([]UUID, amount)
|
||||
o.ReadV1(ids)
|
||||
return ids
|
||||
}
|
||||
|
||||
// NewV2 generates a new DCE version 2 UUID based on a 60 bit timestamp, node id
|
||||
// and the id of the given Id type.
|
||||
func (o *Generator) NewV2(idType SystemId) UUID {
|
||||
o.read()
|
||||
|
||||
id := UUID{}
|
||||
|
||||
var osId uint32
|
||||
|
||||
switch idType {
|
||||
case SystemIdUser:
|
||||
osId = uint32(os.Getuid())
|
||||
case SystemIdGroup:
|
||||
osId = uint32(os.Getgid())
|
||||
case SystemIdEffectiveUser:
|
||||
osId = uint32(os.Geteuid())
|
||||
case SystemIdEffectiveGroup:
|
||||
osId = uint32(os.Getegid())
|
||||
case SystemIdCallerProcess:
|
||||
osId = uint32(os.Getpid())
|
||||
case SystemIdCallerProcessParent:
|
||||
osId = uint32(os.Getppid())
|
||||
}
|
||||
|
||||
makeUuid(&id,
|
||||
osId,
|
||||
uint16(o.Timestamp>>32),
|
||||
uint16(o.Timestamp>>48),
|
||||
uint16(o.Sequence),
|
||||
o.Node)
|
||||
|
||||
id[9] = byte(idType)
|
||||
id.setRFC4122Version(VersionTwo)
|
||||
return id
|
||||
}
|
||||
|
||||
// NewV3 generates a new RFC4122 version 3 UUID based on the MD5 hash of a
|
||||
// namespace UUID namespace Implementation UUID and one or more unique names.
|
||||
func (o *Generator) NewV3(namespace Implementation, names ...interface{}) UUID {
|
||||
id := UUID{}
|
||||
id.unmarshal(digest(md5.New(), namespace.Bytes(), names...))
|
||||
id.setRFC4122Version(VersionThree)
|
||||
return id
|
||||
}
|
||||
|
||||
func digest(hash hash.Hash, name []byte, names ...interface{}) []byte {
|
||||
for _, v := range names {
|
||||
switch t := v.(type) {
|
||||
case string:
|
||||
name = append(name, t...)
|
||||
continue
|
||||
case []byte:
|
||||
name = append(name, t...)
|
||||
continue
|
||||
case *string:
|
||||
name = append(name, (*t)...)
|
||||
continue
|
||||
}
|
||||
if s, ok := v.(fmt.Stringer); ok {
|
||||
name = append(name, s.String()...)
|
||||
continue
|
||||
}
|
||||
panic(fmt.Sprintf("uuid: does not support type [%T] as a name for hashed UUIDs.", v))
|
||||
}
|
||||
hash.Write(name)
|
||||
return hash.Sum(nil)
|
||||
}
|
||||
|
||||
// NewV4 generates a cryptographically secure random RFC4122 version 4 UUID. If there is an error with the random
|
||||
// number generator this will
|
||||
func (o *Generator) NewV4() (id UUID) {
|
||||
o.v4(&id)
|
||||
return
|
||||
}
|
||||
|
||||
// ReadV4 will read into a slice of UUIDs. Be careful with the set amount.
|
||||
// Note: V4 UUIDs require sufficient entropy from the generator.
|
||||
// If n == len(ids) err will be nil.
|
||||
func (o *Generator) ReadV4(ids []UUID) {
|
||||
for i := range ids {
|
||||
id := UUID{}
|
||||
o.v4(&id)
|
||||
ids[i] = id
|
||||
continue
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// BulkV4 will return a slice of V4 UUIDs. Be careful with the set amount.
|
||||
// Note: V4 UUIDs require sufficient entropy from the generator.
|
||||
// If n == len(ids) err will be nil.
|
||||
func (o *Generator) BulkV4(amount int) []UUID {
|
||||
ids := make([]UUID, amount)
|
||||
o.ReadV4(ids)
|
||||
return ids
|
||||
}
|
||||
|
||||
func (o *Generator) v4(id *UUID) {
|
||||
n, err := o.Random(id[:])
|
||||
if err != nil {
|
||||
o.Printf("there was an error getting random bytes [%s]", err)
|
||||
if err = o.HandleRandomError(id[:], n, err); err != nil {
|
||||
panic(fmt.Sprintf("random number error - %s", err))
|
||||
}
|
||||
}
|
||||
id.setRFC4122Version(VersionFour)
|
||||
}
|
||||
|
||||
|
||||
// NewV5 generates an RFC4122 version 5 UUID based on the SHA-1 hash of a
|
||||
// namespace Implementation UUID and one or more unique names.
|
||||
func (o *Generator) NewV5(namespace Implementation, names ...interface{}) UUID {
|
||||
id := UUID{}
|
||||
id.unmarshal(digest(sha1.New(), namespace.Bytes(), names...))
|
||||
id.setRFC4122Version(VersionFive)
|
||||
return id
|
||||
}
|
||||
|
||||
// NewHash generate a UUID based on the given hash implementation. The hash will
|
||||
// be of the given names. The version will be set to 0 for Unknown and the
|
||||
// variant will be set to VariantFuture.
|
||||
func (o *Generator) NewHash(hash hash.Hash, names ...interface{}) UUID {
|
||||
id := UUID{}
|
||||
id.unmarshal(digest(hash, []byte{}, names...))
|
||||
id[versionIndex] &= 0x0f
|
||||
id[versionIndex] |= uint8(0 << 4)
|
||||
id[variantIndex] &= variantSet
|
||||
id[variantIndex] |= VariantFuture
|
||||
return id
|
||||
}
|
||||
|
||||
func makeUuid(id *UUID, low uint32, mid, hiAndV, seq uint16, node Node) {
|
||||
|
||||
id[0] = byte(low >> 24)
|
||||
id[1] = byte(low >> 16)
|
||||
id[2] = byte(low >> 8)
|
||||
id[3] = byte(low)
|
||||
|
||||
id[4] = byte(mid >> 8)
|
||||
id[5] = byte(mid)
|
||||
|
||||
id[6] = byte(hiAndV >> 8)
|
||||
id[7] = byte(hiAndV)
|
||||
|
||||
id[8] = byte(seq >> 8)
|
||||
id[9] = byte(seq)
|
||||
|
||||
copy(id[10:], node)
|
||||
}
|
||||
|
||||
func findFirstHardwareAddress() (node Node) {
|
||||
interfaces, err := net.Interfaces()
|
||||
if err == nil {
|
||||
for _, i := range interfaces {
|
||||
if i.Flags&net.FlagUp != 0 && bytes.Compare(i.HardwareAddr, nil) != 0 {
|
||||
// Don't use random as we have a real address
|
||||
node = Node(i.HardwareAddr)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (o *Generator) runHandleError(id []byte, n int, err error) error {
|
||||
o.Lock()
|
||||
mrand.Read(id)
|
||||
o.Unlock()
|
||||
return nil
|
||||
}
|
||||
65
vendor/github.com/twinj/uuid/saver.go
generated
vendored
65
vendor/github.com/twinj/uuid/saver.go
generated
vendored
@@ -1,65 +0,0 @@
|
||||
package uuid
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// Sequence represents an iterated value to help ensure unique UUID generations
|
||||
// values across the same domain, server restarts and clock issues.
|
||||
type Sequence uint16
|
||||
|
||||
// Node represents the last node id setup used by the generator.
|
||||
type Node []byte
|
||||
|
||||
// Store is used for storage of UUID generation history to ensure continuous
|
||||
// running of the UUID generator between restarts and to monitor synchronicity
|
||||
// while generating new V1 or V2 UUIDs.
|
||||
type Store struct {
|
||||
Timestamp
|
||||
Sequence
|
||||
Node
|
||||
}
|
||||
|
||||
// String returns a string representation of the Store.
|
||||
func (o Store) String() string {
|
||||
return fmt.Sprintf("Timestamp[%s]-Sequence[%d]-Node[%x]", o.Timestamp, o.Sequence, o.Node)
|
||||
}
|
||||
|
||||
// Saver is an interface to setup a non volatile store within your system
|
||||
// if you wish to use V1 and V2 UUIDs based on your node id and a constant time
|
||||
// it is highly recommended to implement this.
|
||||
// A default implementation has been provided. FileSystemStorage, the default
|
||||
// behaviour of the package is to generate random sequences where a Saver is not
|
||||
// specified.
|
||||
type Saver interface {
|
||||
// Read is run once, use this to setup your UUID state machine
|
||||
// Read should also return the UUID state from the non volatile store
|
||||
Read() (Store, error)
|
||||
|
||||
// Save saves the state to the non volatile store and is called only if
|
||||
Save(Store)
|
||||
|
||||
// Init allows default setup of a new Saver
|
||||
Init() Saver
|
||||
}
|
||||
|
||||
// RegisterSaver register's a uuid.Saver implementation to the default package
|
||||
// uuid.Generator. If you wish to save the generator state, this function must
|
||||
// be run before any calls to V1 or V2 UUIDs. uuid.RegisterSaver cannot be run
|
||||
// in conjunction with uuid.Init. You may implement the uuid.Saver interface
|
||||
// or use the provided uuid.Saver's from the uuid/savers package.
|
||||
func RegisterSaver(saver Saver) (err error) {
|
||||
notOnce := true
|
||||
once.Do(func() {
|
||||
generator.Lock()
|
||||
generator.Saver = saver
|
||||
generator.Unlock()
|
||||
err = generator.init()
|
||||
notOnce = false
|
||||
return
|
||||
})
|
||||
if notOnce {
|
||||
panic("uuid: Register* methods cannot be called more than once.")
|
||||
}
|
||||
return
|
||||
}
|
||||
120
vendor/github.com/twinj/uuid/timestamp.go
generated
vendored
120
vendor/github.com/twinj/uuid/timestamp.go
generated
vendored
@@ -1,120 +0,0 @@
|
||||
package uuid
|
||||
|
||||
import (
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
gregorianToUNIXOffset = 122192928e9
|
||||
|
||||
// set the following to the number of 100ns ticks of the actual
|
||||
// resolution of your system's clock
|
||||
defaultSpinResolution = 1024
|
||||
)
|
||||
|
||||
// Timestamp as per 4.1.4. Timestamp https://www.ietf.org/rfc/rfc4122.txt
|
||||
//
|
||||
// The timestamp is a 60-bit value. For UUID version 1, this is
|
||||
//
|
||||
// represented by Coordinated Universal Time (UTC) as a count of 100-
|
||||
// nanosecond intervals since 00:00:00.00, 15 October 1582 (the date of
|
||||
// Gregorian reform to the Christian calendar).
|
||||
//
|
||||
// For systems that do not have UTC available, but do have the local
|
||||
// time, they may use that instead of UTC, as long as they do so
|
||||
// consistently throughout the system. However, this is not recommended
|
||||
// since generating the UTC from local time only needs a time zone
|
||||
// offset.
|
||||
//
|
||||
// For UUID version 3 or 5, the timestamp is a 60-bit value constructed
|
||||
// from a name as described in Section 4.3.
|
||||
//
|
||||
// For UUID version 4, the timestamp is a randomly or pseudo-randomly
|
||||
// generated 60-bit value, as described in Section 4.4.
|
||||
type Timestamp uint64
|
||||
|
||||
// Now converts Unix formatted time to RFC4122 UUID formatted times
|
||||
// UUID UTC base time is October 15, 1582.
|
||||
// Unix base time is January 1, 1970.
|
||||
// Converts time to 100 nanosecond ticks since epoch. Uses time.Now
|
||||
func Now() Timestamp {
|
||||
return Timestamp(time.Now().UnixNano()/100 + gregorianToUNIXOffset)
|
||||
}
|
||||
|
||||
// Time converts UUID Timestamp to UTC time.Time
|
||||
// Note some higher clock resolutions will lose accuracy if above 100 ns ticks
|
||||
func (o Timestamp) Time() time.Time {
|
||||
return time.Unix(0, int64((o-gregorianToUNIXOffset)*100)).UTC()
|
||||
}
|
||||
|
||||
// Add returns the timestamp as modified by the duration
|
||||
func (o Timestamp) Add(duration time.Duration) Timestamp {
|
||||
return o + Timestamp(duration/100)
|
||||
}
|
||||
|
||||
// Sub returns the timestamp as modified by the duration
|
||||
func (o Timestamp) Sub(duration time.Duration) Timestamp {
|
||||
return o - Timestamp(duration/100)
|
||||
}
|
||||
|
||||
// String Converts UUID Timestamp to time.Time and then calls the Stringer
|
||||
func (o Timestamp) String() string {
|
||||
return o.Time().String()
|
||||
}
|
||||
|
||||
// 4.2.1.2. System Clock Resolution https://www.ietf.org/rfc/rfc4122.txt
|
||||
//
|
||||
// The timestamp is generated from the system time, whose resolution may
|
||||
// be less than the resolution of the UUID timestamp.
|
||||
//
|
||||
// If UUIDs do not need to be frequently generated, the timestamp can
|
||||
// simply be the system time multiplied by the number of 100-nanosecond
|
||||
// intervals per system time interval.
|
||||
//
|
||||
// If a system overruns the generator by requesting too many UUIDs
|
||||
// within a single system time interval, the UUID service MUST either
|
||||
// return an error, or stall the UUID generator until the system clock
|
||||
// catches up.
|
||||
//
|
||||
// A high resolution timestamp can be simulated by keeping a count of
|
||||
// the number of UUIDs that have been generated with the same value of
|
||||
// the system time, and using it to construct the low order bits of the
|
||||
// timestamp. The count will range between zero and the number of
|
||||
// 100-nanosecond intervals per system time interval.
|
||||
//
|
||||
// Note: If the processors overrun the UUID generation frequently,
|
||||
// additional node identifiers can be allocated to the system, which
|
||||
// will permit higher speed allocation by making multiple UUIDs
|
||||
// potentially available for each time stamp value.
|
||||
|
||||
type spinner struct {
|
||||
// the amount of ids based on the Timestamp
|
||||
Count, Resolution uint
|
||||
|
||||
// the tracked spin stamp
|
||||
Timestamp
|
||||
|
||||
now func() Timestamp
|
||||
}
|
||||
|
||||
func (o *spinner) next() Timestamp {
|
||||
for {
|
||||
now := o.now()
|
||||
// if clock reading changed since last UUID generated
|
||||
if o.Timestamp == now {
|
||||
o.Count++
|
||||
if o.Count == o.Resolution {
|
||||
for o.now() < o.Timestamp+Timestamp(o.Resolution) {
|
||||
}
|
||||
continue
|
||||
}
|
||||
break
|
||||
}
|
||||
|
||||
// reset count of UUIDs with this timestamp
|
||||
o.Count = 0
|
||||
o.Timestamp = now
|
||||
break
|
||||
}
|
||||
return o.Timestamp + Timestamp(o.Count)
|
||||
}
|
||||
175
vendor/github.com/twinj/uuid/types.go
generated
vendored
175
vendor/github.com/twinj/uuid/types.go
generated
vendored
@@ -1,175 +0,0 @@
|
||||
package uuid
|
||||
|
||||
import (
|
||||
"database/sql/driver"
|
||||
"fmt"
|
||||
"errors"
|
||||
)
|
||||
|
||||
const (
|
||||
length = 16
|
||||
variantIndex = 8
|
||||
versionIndex = 6
|
||||
)
|
||||
|
||||
// **************************************************** Create UUIDs
|
||||
|
||||
func (o *UUID) unmarshal(data []byte) {
|
||||
copy(o[:], data)
|
||||
}
|
||||
|
||||
// Set the three most significant bits (bits 0, 1 and 2) of the
|
||||
// sequenceHiAndVariant equivalent in the array to ReservedRFC4122.
|
||||
func (o *UUID) setRFC4122Version(version Version) {
|
||||
o[versionIndex] &= 0x0f
|
||||
o[versionIndex] |= uint8(version << 4)
|
||||
o[variantIndex] &= variantSet
|
||||
o[variantIndex] |= VariantRFC4122
|
||||
}
|
||||
|
||||
// **************************************************** Default implementation
|
||||
|
||||
var _ Implementation = &UUID{}
|
||||
|
||||
// UUID is the default RFC implementation. All uuid functions will return this
|
||||
// type.
|
||||
type UUID [length]byte
|
||||
|
||||
// Size returns the octet length of the Uuid
|
||||
func (o UUID) Size() int {
|
||||
return length
|
||||
}
|
||||
|
||||
// Version returns the uuid.Version of the Uuid
|
||||
func (o UUID) Version() Version {
|
||||
return resolveVersion(o[versionIndex] >> 4)
|
||||
}
|
||||
|
||||
// Variant returns the implementation variant of the Uuid
|
||||
func (o UUID) Variant() uint8 {
|
||||
return variant(o[variantIndex])
|
||||
}
|
||||
|
||||
// Bytes return the underlying data representation of the Uuid.
|
||||
func (o UUID) Bytes() []byte {
|
||||
return o[:]
|
||||
}
|
||||
|
||||
// String returns the canonical string representation of the UUID or the
|
||||
// uuid.Format the package is set to via uuid.SwitchFormat
|
||||
func (o UUID) String() string {
|
||||
return formatUuid(o[:], printFormat)
|
||||
}
|
||||
|
||||
// **************************************************** Implementations
|
||||
|
||||
// MarshalBinary implements the encoding.BinaryMarshaler interface
|
||||
func (o UUID) MarshalBinary() ([]byte, error) {
|
||||
return o.Bytes(), nil
|
||||
}
|
||||
|
||||
// UnmarshalBinary implements the encoding.BinaryUnmarshaler interface
|
||||
func (o *UUID) UnmarshalBinary(bytes []byte) error {
|
||||
if len(bytes) != o.Size() {
|
||||
return errors.New("uuid: invalid length")
|
||||
}
|
||||
o.unmarshal(bytes)
|
||||
return nil
|
||||
}
|
||||
|
||||
// MarshalText implements the encoding.TextMarshaler interface. It will marshal
|
||||
// text into one of the known formats, if you have changed to a custom Format
|
||||
// the text be output in canonical format.
|
||||
func (o UUID) MarshalText() ([]byte, error) {
|
||||
f := FormatCanonical
|
||||
if defaultFormats[printFormat] {
|
||||
f = printFormat
|
||||
}
|
||||
return []byte(formatUuid(o.Bytes(), f)), nil
|
||||
}
|
||||
|
||||
// UnmarshalText implements the encoding.TextUnmarshaler interface. It will
|
||||
// support any text that MarshalText can produce.
|
||||
func (o *UUID) UnmarshalText(uuid []byte) error {
|
||||
id, err := parse(string(uuid))
|
||||
if err == nil {
|
||||
o.UnmarshalBinary(id)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// Value implements the driver.Valuer interface
|
||||
func (o UUID) Value() (value driver.Value, err error) {
|
||||
if IsNil(o) {
|
||||
value, err = nil, nil
|
||||
return
|
||||
}
|
||||
value, err = o.MarshalText()
|
||||
return
|
||||
}
|
||||
|
||||
// Scan implements the sql.Scanner interface
|
||||
func (o *UUID) Scan(src interface{}) error {
|
||||
if src == nil {
|
||||
return nil
|
||||
}
|
||||
if src == "" {
|
||||
return nil
|
||||
}
|
||||
switch src := src.(type) {
|
||||
|
||||
case string:
|
||||
return o.UnmarshalText([]byte(src))
|
||||
|
||||
case []byte:
|
||||
if len(src) == length {
|
||||
return o.UnmarshalBinary(src)
|
||||
} else {
|
||||
return o.UnmarshalText(src)
|
||||
}
|
||||
|
||||
default:
|
||||
return fmt.Errorf("uuid: cannot scan type [%T] into UUID", src)
|
||||
}
|
||||
}
|
||||
|
||||
// **************************************************** Immutable UUID
|
||||
|
||||
var _ Implementation = new(Immutable)
|
||||
|
||||
// Immutable is an easy to use UUID which can be used as a key or for constants
|
||||
type Immutable string
|
||||
|
||||
// Size returns the octet length of the Uuid
|
||||
func (o Immutable) Size() int {
|
||||
return length
|
||||
}
|
||||
|
||||
// Version returns the uuid.Version of the Uuid
|
||||
func (o Immutable) Version() Version {
|
||||
return resolveVersion(o[versionIndex] >> 4)
|
||||
}
|
||||
|
||||
// Variant returns the implementation variant of the Uuid
|
||||
func (o Immutable) Variant() uint8 {
|
||||
return variant(o[variantIndex])
|
||||
}
|
||||
|
||||
// Bytes return the underlying data representation of the Uuid in network byte
|
||||
// order
|
||||
func (o Immutable) Bytes() []byte {
|
||||
return []byte(o)
|
||||
}
|
||||
|
||||
// String returns the canonical string representation of the UUID or the
|
||||
// uuid.Format the package is set to via uuid.SwitchFormat
|
||||
func (o Immutable) String() string {
|
||||
return formatUuid([]byte(o), printFormat)
|
||||
}
|
||||
|
||||
// UUID converts this implementation to the default type uuid.UUID
|
||||
func (o Immutable) UUID() UUID {
|
||||
id := UUID{}
|
||||
id.unmarshal(o.Bytes())
|
||||
return id
|
||||
}
|
||||
267
vendor/github.com/twinj/uuid/uuid.go
generated
vendored
267
vendor/github.com/twinj/uuid/uuid.go
generated
vendored
@@ -1,267 +0,0 @@
|
||||
// Package uuid provides RFC4122 and DCE 1.1 UUIDs.
|
||||
//
|
||||
// Use NewV1, NewV2, NewV3, NewV4, NewV5, for generating new UUIDs.
|
||||
//
|
||||
// Use New([]byte), NewHex(string), and Parse(string) for
|
||||
// creating UUIDs from existing data.
|
||||
//
|
||||
// The original version was from Krzysztof Kowalik <chris@nu7hat.ch>
|
||||
// Unfortunately, that version was non compliant with RFC4122.
|
||||
//
|
||||
// The package has since been redesigned.
|
||||
//
|
||||
// The example code in the specification was also used as reference for design.
|
||||
//
|
||||
// Copyright (C) 2016 myesui@github.com 2016 MIT licence
|
||||
package uuid
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"encoding/hex"
|
||||
"errors"
|
||||
"hash"
|
||||
"regexp"
|
||||
)
|
||||
|
||||
// Nil represents an empty UUID.
|
||||
const Nil Immutable = "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
|
||||
|
||||
// The following Immutable UUIDs are for use with V3 or V5 UUIDs.
|
||||
|
||||
const (
|
||||
NameSpaceDNS Immutable = "k\xa7\xb8\x10\x9d\xad\x11р\xb4\x00\xc0O\xd40\xc8"
|
||||
NameSpaceURL Immutable = "k\xa7\xb8\x11\x9d\xad\x11р\xb4\x00\xc0O\xd40\xc8"
|
||||
NameSpaceOID Immutable = "k\xa7\xb8\x12\x9d\xad\x11р\xb4\x00\xc0O\xd40\xc8"
|
||||
NameSpaceX500 Immutable = "k\xa7\xb8\x14\x9d\xad\x11р\xb4\x00\xc0O\xd40\xc8"
|
||||
)
|
||||
|
||||
// SystemId denotes the type of id to retrieve from the operating system.
|
||||
// That id is then used to create an identifier UUID.
|
||||
type SystemId uint8
|
||||
|
||||
// The following SystemId's are for use with V2 UUIDs.
|
||||
const (
|
||||
SystemIdUser SystemId = iota + 1
|
||||
SystemIdEffectiveUser
|
||||
SystemIdGroup
|
||||
SystemIdEffectiveGroup
|
||||
SystemIdCallerProcess
|
||||
SystemIdCallerProcessParent
|
||||
)
|
||||
|
||||
// Implementation is the common interface implemented by all UUIDs.
|
||||
type Implementation interface {
|
||||
|
||||
// Bytes retrieves the bytes from the underlying UUID
|
||||
Bytes() []byte
|
||||
|
||||
// Size is the length of the underlying UUID implementation
|
||||
Size() int
|
||||
|
||||
// String should return the canonical UUID representation, or the a
|
||||
// given uuid.Format
|
||||
String() string
|
||||
|
||||
// Variant returns the UUID implementation variant
|
||||
Variant() uint8
|
||||
|
||||
// Version returns the version number of the algorithm used to generate
|
||||
// the UUID.
|
||||
Version() Version
|
||||
}
|
||||
|
||||
// New creates a UUID from a slice of bytes.
|
||||
func New(data []byte) UUID {
|
||||
o := UUID{}
|
||||
o.unmarshal(data)
|
||||
return o
|
||||
}
|
||||
|
||||
// NewHex creates a UUID from a hex string.
|
||||
// Will panic if hex string is invalid use Parse otherwise.
|
||||
func NewHex(uuid string) UUID {
|
||||
o := UUID{}
|
||||
o.unmarshal(fromHex(uuid))
|
||||
return o
|
||||
}
|
||||
|
||||
const (
|
||||
// Pattern used to parse string representation of the UUID.
|
||||
// Current one allows to parse string where only one opening
|
||||
// or closing bracket or any of the hyphens are optional.
|
||||
// It is only used to extract the main bytes to create a UUID,
|
||||
// so these imperfections are of no consequence.
|
||||
hexPattern = `^(urn\:uuid\:)?[\{\(\[]?([[:xdigit:]]{8})-?([[:xdigit:]]{4})-?([1-5][[:xdigit:]]{3})-?([[:xdigit:]]{4})-?([[:xdigit:]]{12})[\]\}\)]?$`
|
||||
)
|
||||
|
||||
var (
|
||||
parseUUIDRegex = regexp.MustCompile(hexPattern)
|
||||
)
|
||||
|
||||
// Parse creates a UUID from a valid string representation.
|
||||
// Accepts UUID string in following formats:
|
||||
// 6ba7b8149dad11d180b400c04fd430c8
|
||||
// 6ba7b814-9dad-11d1-80b4-00c04fd430c8
|
||||
// {6ba7b814-9dad-11d1-80b4-00c04fd430c8}
|
||||
// urn:uuid:6ba7b814-9dad-11d1-80b4-00c04fd430c8
|
||||
// [6ba7b814-9dad-11d1-80b4-00c04fd430c8]
|
||||
// (6ba7b814-9dad-11d1-80b4-00c04fd430c8)
|
||||
//
|
||||
func Parse(uuid string) (*UUID, error) {
|
||||
id, err := parse(uuid)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
a := UUID{}
|
||||
a.unmarshal(id)
|
||||
return &a, nil
|
||||
}
|
||||
|
||||
func parse(uuid string) ([]byte, error) {
|
||||
md := parseUUIDRegex.FindStringSubmatch(uuid)
|
||||
if md == nil {
|
||||
return nil, errors.New("uuid: invalid string format this is probably not a UUID")
|
||||
}
|
||||
return fromHex(md[2] + md[3] + md[4] + md[5] + md[6]), nil
|
||||
}
|
||||
|
||||
func fromHex(uuid string) []byte {
|
||||
bytes, err := hex.DecodeString(uuid)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return bytes
|
||||
}
|
||||
|
||||
// NewV1 generates a new RFC4122 version 1 UUID based on a 60 bit timestamp and
|
||||
// node ID.
|
||||
func NewV1() UUID {
|
||||
return generator.NewV1()
|
||||
}
|
||||
|
||||
// BulkV1 will return a slice of V1 UUIDs. Be careful with the set amount.
|
||||
func BulkV1(amount int) []UUID {
|
||||
return generator.BulkV1(amount)
|
||||
}
|
||||
|
||||
// ReadV1 will read a slice of UUIDs. Be careful with the set amount.
|
||||
func ReadV1(ids []UUID) {
|
||||
generator.ReadV1(ids)
|
||||
}
|
||||
|
||||
// NewV2 generates a new DCE Security version UUID based on a 60 bit timestamp,
|
||||
// node id and POSIX UID.
|
||||
func NewV2(pDomain SystemId) UUID {
|
||||
return generator.NewV2(pDomain)
|
||||
}
|
||||
|
||||
// NewV3 generates a new RFC4122 version 3 UUID based on the MD5 hash of a
|
||||
// namespace UUID namespace Implementation UUID and one or more unique names.
|
||||
func NewV3(namespace Implementation, names ...interface{}) UUID {
|
||||
return generator.NewV3(namespace, names...)
|
||||
}
|
||||
|
||||
// NewV4 generates a new RFC4122 version 4 UUID a cryptographically secure
|
||||
// random UUID.
|
||||
func NewV4() UUID {
|
||||
return generator.NewV4()
|
||||
}
|
||||
|
||||
// ReadV4 will read into a slice of UUIDs. Be careful with the set amount.
|
||||
// Note: V4 UUIDs require sufficient entropy from the generator.
|
||||
// If n == len(ids) err will be nil.
|
||||
func ReadV4(ids []UUID) {
|
||||
generator.ReadV4(ids)
|
||||
}
|
||||
|
||||
// BulkV4 will return a slice of V4 UUIDs. Be careful with the set amount.
|
||||
// Note: V4 UUIDs require sufficient entropy from the generator.
|
||||
// If n == len(ids) err will be nil.
|
||||
func BulkV4(amount int) []UUID {
|
||||
return generator.BulkV4(amount)
|
||||
}
|
||||
|
||||
// NewV5 generates an RFC4122 version 5 UUID based on the SHA-1 hash of a
|
||||
// namespace Implementation UUID and one or more unique names.
|
||||
func NewV5(namespace Implementation, names ...interface{}) UUID {
|
||||
return generator.NewV5(namespace, names...)
|
||||
}
|
||||
|
||||
// NewHash generate a UUID based on the given hash implementation. The hash will
|
||||
// be of the given names. The version will be set to 0 for Unknown and the
|
||||
// variant will be set to VariantFuture.
|
||||
func NewHash(hash hash.Hash, names ...interface{}) UUID {
|
||||
return generator.NewHash(hash, names...)
|
||||
}
|
||||
|
||||
// Compare returns an integer comparing two Implementation UUIDs
|
||||
// lexicographically.
|
||||
// The result will be 0 if pId==pId2, -1 if pId < pId2, and +1 if pId > pId2.
|
||||
// A nil argument is equivalent to the Nil Immutable UUID.
|
||||
func Compare(pId, pId2 Implementation) int {
|
||||
|
||||
var b1, b2 = []byte(Nil), []byte(Nil)
|
||||
|
||||
if pId != nil {
|
||||
b1 = pId.Bytes()
|
||||
}
|
||||
|
||||
if pId2 != nil {
|
||||
b2 = pId2.Bytes()
|
||||
}
|
||||
|
||||
// Compare the time low bytes
|
||||
tl1 := binary.BigEndian.Uint32(b1[:4])
|
||||
tl2 := binary.BigEndian.Uint32(b2[:4])
|
||||
|
||||
if tl1 != tl2 {
|
||||
if tl1 < tl2 {
|
||||
return -1
|
||||
}
|
||||
return 1
|
||||
}
|
||||
|
||||
// Compare the time hi and ver bytes
|
||||
m1 := binary.BigEndian.Uint16(b1[4:6])
|
||||
m2 := binary.BigEndian.Uint16(b2[4:6])
|
||||
|
||||
if m1 != m2 {
|
||||
if m1 < m2 {
|
||||
return -1
|
||||
}
|
||||
return 1
|
||||
}
|
||||
|
||||
// Compare the sequence and version
|
||||
m1 = binary.BigEndian.Uint16(b1[6:8])
|
||||
m2 = binary.BigEndian.Uint16(b2[6:8])
|
||||
|
||||
if m1 != m2 {
|
||||
if m1 < m2 {
|
||||
return -1
|
||||
}
|
||||
return 1
|
||||
}
|
||||
|
||||
// Compare the node id
|
||||
return bytes.Compare(b1[8:], b2[8:])
|
||||
}
|
||||
|
||||
// Equal compares whether each Implementation UUID is the same
|
||||
func Equal(p1, p2 Implementation) bool {
|
||||
return bytes.Equal(p1.Bytes(), p2.Bytes())
|
||||
}
|
||||
|
||||
// IsNil returns true if Implementation UUID is all zeros?
|
||||
func IsNil(uuid Implementation) bool {
|
||||
if uuid == nil {
|
||||
return true
|
||||
}
|
||||
for _, v := range uuid.Bytes() {
|
||||
if v != 0 {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
71
vendor/github.com/twinj/uuid/version.go
generated
vendored
71
vendor/github.com/twinj/uuid/version.go
generated
vendored
@@ -1,71 +0,0 @@
|
||||
package uuid
|
||||
|
||||
// Version represents the type of UUID.
|
||||
type Version int
|
||||
|
||||
// The following are the supported Versions.
|
||||
const (
|
||||
VersionUnknown Version = iota // Unknown
|
||||
VersionOne // Time based
|
||||
VersionTwo // DCE security via POSIX UIDs
|
||||
VersionThree // Namespace hash uses MD5
|
||||
VersionFour // Crypto random
|
||||
VersionFive // Namespace hash uses SHA-1
|
||||
)
|
||||
|
||||
// The following are the supported Variants.
|
||||
const (
|
||||
VariantNCS uint8 = 0x00
|
||||
VariantRFC4122 uint8 = 0x80 // or and A0 if masked with 1F
|
||||
VariantMicrosoft uint8 = 0xC0
|
||||
VariantFuture uint8 = 0xE0
|
||||
)
|
||||
|
||||
const (
|
||||
// 3f used by RFC4122 although 1f works for all
|
||||
variantSet = 0x3f
|
||||
|
||||
// rather than using 0xc0 we use 0xe0 to retrieve the variant
|
||||
// The result is the same for all other variants
|
||||
// 0x80 and 0xa0 are used to identify RFC4122 compliance
|
||||
variantGet = 0xe0
|
||||
)
|
||||
|
||||
// String returns English description of version.
|
||||
func (o Version) String() string {
|
||||
switch o {
|
||||
case VersionOne:
|
||||
return "Version 1: Based on a 60 Bit Timestamp."
|
||||
case VersionTwo:
|
||||
return "Version 2: Based on DCE security domain and 60 bit timestamp."
|
||||
case VersionThree:
|
||||
return "Version 3: Namespace UUID and unique names hashed by MD5."
|
||||
case VersionFour:
|
||||
return "Version 4: Crypto-random generated."
|
||||
case VersionFive:
|
||||
return "Version 5: Namespace UUID and unique names hashed by SHA-1."
|
||||
default:
|
||||
return "Unknown: Not supported"
|
||||
}
|
||||
}
|
||||
|
||||
func resolveVersion(version uint8) Version {
|
||||
switch Version(version) {
|
||||
case VersionOne, VersionTwo, VersionThree, VersionFour, VersionFive:
|
||||
return Version(version)
|
||||
default:
|
||||
return VersionUnknown
|
||||
}
|
||||
}
|
||||
|
||||
func variant(variant uint8) uint8 {
|
||||
switch variant & variantGet {
|
||||
case VariantRFC4122, 0xA0:
|
||||
return VariantRFC4122
|
||||
case VariantMicrosoft:
|
||||
return VariantMicrosoft
|
||||
case VariantFuture:
|
||||
return VariantFuture
|
||||
}
|
||||
return VariantNCS
|
||||
}
|
||||
2
vendor/modules.txt
vendored
2
vendor/modules.txt
vendored
@@ -18,7 +18,5 @@ github.com/mattn/go-sqlite3
|
||||
# github.com/mozillazg/go-unidecode v0.1.1
|
||||
github.com/mozillazg/go-unidecode
|
||||
github.com/mozillazg/go-unidecode/table
|
||||
# github.com/twinj/uuid v1.0.0
|
||||
github.com/twinj/uuid
|
||||
# github.com/wader/gormstore v0.0.0-20190302154359-acb787ba3755
|
||||
github.com/wader/gormstore
|
||||
|
||||
Reference in New Issue
Block a user