mirror of
https://github.com/tmedwards/tweego.git
synced 2025-07-04 21:50:33 -04:00
Initial Bitbucket→GitHub migration commit, based on release v2.0.0.
This commit is contained in:
commit
57e1aa52ff
36 changed files with 5026 additions and 0 deletions
85
ifid.go
Normal file
85
ifid.go
Normal file
|
@ -0,0 +1,85 @@
|
|||
/*
|
||||
Copyright © 2014–2019 Thomas Michael Edwards. All rights reserved.
|
||||
Use of this source code is governed by a Simplified BSD License which
|
||||
can be found in the LICENSE file.
|
||||
*/
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"fmt"
|
||||
"io"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// IFIDs are defined in The Treaty of Babel.
|
||||
// SEE: http://babel.ifarchive.org/
|
||||
//
|
||||
// Most IFIDs, and certainly those generated by Tweego, are simply the
|
||||
// string form of a v4 random UUID.
|
||||
|
||||
// newIFID generates a new IFID (UUID v4).
|
||||
func newIFID() (string, error) {
|
||||
var uuid [16]byte
|
||||
if _, err := io.ReadFull(rand.Reader, uuid[:]); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
uuid[6] = (uuid[6] & 0x0f) | 0x40 // version 4
|
||||
uuid[8] = (uuid[8] & 0x3f) | 0x80 // variant 10
|
||||
|
||||
return fmt.Sprintf("%X-%X-%X-%X-%X", uuid[0:4], uuid[4:6], uuid[6:8], uuid[8:10], uuid[10:]), nil
|
||||
}
|
||||
|
||||
// validateIFID validates ifid or returns an error.
|
||||
func validateIFID(ifid string) error {
|
||||
switch len(ifid) {
|
||||
case 36: // xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
|
||||
case 36 + 9: // UUID://xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx//
|
||||
if strings.ToUpper(ifid[:7]) != "UUID://" || ifid[43:] != "//" {
|
||||
return fmt.Errorf("invalid IFID UUID://…// format")
|
||||
}
|
||||
ifid = ifid[7:43]
|
||||
|
||||
default:
|
||||
return fmt.Errorf("invalid IFID length: %d", len(ifid))
|
||||
}
|
||||
|
||||
b := []byte(ifid)
|
||||
for i := 0; i < len(b); i++ {
|
||||
switch i {
|
||||
// hyphens
|
||||
case 8, 13, 18, 23:
|
||||
if b[i] != '-' {
|
||||
return fmt.Errorf("invalid IFID character %#U at position %d", b[i], i+1)
|
||||
}
|
||||
|
||||
// version
|
||||
case 14:
|
||||
if '1' > b[i] || b[i] > '5' {
|
||||
return fmt.Errorf("invalid version %#U at position %d", b[i], i+1)
|
||||
}
|
||||
|
||||
// variant
|
||||
case 19:
|
||||
switch b[i] {
|
||||
case '8', '9', 'a', 'A', 'b', 'B':
|
||||
default:
|
||||
return fmt.Errorf("invalid variant %#U at position %d", b[i], i+1)
|
||||
}
|
||||
|
||||
// regular hex character
|
||||
default:
|
||||
switch {
|
||||
case '0' <= b[i] && b[i] <= '9':
|
||||
case 'a' <= b[i] && b[i] <= 'f':
|
||||
case 'A' <= b[i] && b[i] <= 'F':
|
||||
default:
|
||||
return fmt.Errorf("invalid IFID hex value %#U at position %d", b[i], i+1)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue