162 lines
4.0 KiB
Go
162 lines
4.0 KiB
Go
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
|
|
}
|