mirror of
				https://codeberg.org/forgejo/forgejo.git
				synced 2025-10-30 22:11:07 +00:00 
			
		
		
		
	* Dropped unused codekit config * Integrated dynamic and static bindata for public * Ignore public bindata * Add a general generate make task * Integrated flexible public assets into web command * Updated vendoring, added all missiong govendor deps * Made the linter happy with the bindata and dynamic code * Moved public bindata definition to modules directory * Ignoring the new bindata path now * Updated to the new public modules import path * Updated public bindata command and drop the new prefix
		
			
				
	
	
		
			296 lines
		
	
	
	
		
			7.7 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			296 lines
		
	
	
	
		
			7.7 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| // This package provides RFC4122 UUIDs.
 | |
| //
 | |
| // NewV1, NewV3, NewV4, NewV5, for generating versions 1, 3, 4
 | |
| // and 5 UUIDs as specified in RFC-4122.
 | |
| //
 | |
| // New([]byte), unsafe; 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.
 | |
| // I forked it but have since heavily redesigned it.
 | |
| //
 | |
| // The example code in the specification was also used as reference
 | |
| // for design.
 | |
| //
 | |
| // Copyright (C) 2014 twinj@github.com  2014 MIT style licence
 | |
| package uuid
 | |
| 
 | |
| /****************
 | |
|  * Date: 31/01/14
 | |
|  * Time: 3:35 PM
 | |
|  ***************/
 | |
| 
 | |
| import (
 | |
| 	"encoding"
 | |
| 	"encoding/hex"
 | |
| 	"errors"
 | |
| 	"fmt"
 | |
| 	"hash"
 | |
| 	"regexp"
 | |
| 	"strings"
 | |
| 	"bytes"
 | |
| )
 | |
| 
 | |
| const (
 | |
| 	ReservedNCS       byte = 0x00
 | |
| 	ReservedRFC4122   byte = 0x80 // or and A0 if masked with 1F
 | |
| 	ReservedMicrosoft byte = 0xC0
 | |
| 	ReservedFuture    byte = 0xE0
 | |
| 	TakeBack          byte = 0xF0
 | |
| )
 | |
| 
 | |
| 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\:)?[\{(\[]?([A-Fa-f0-9]{8})-?([A-Fa-f0-9]{4})-?([1-5][A-Fa-f0-9]{3})-?([A-Fa-f0-9]{4})-?([A-Fa-f0-9]{12})[\]\})]?$`
 | |
| )
 | |
| 
 | |
| var (
 | |
| 	parseUUIDRegex = regexp.MustCompile(hexPattern)
 | |
| 	format         string
 | |
| )
 | |
| 
 | |
| func init() {
 | |
| 	SwitchFormat(CleanHyphen)
 | |
| }
 | |
| 
 | |
| // ******************************************************  UUID
 | |
| 
 | |
| // The main interface for UUIDs
 | |
| // Each implementation must also implement the UniqueName interface
 | |
| type UUID interface {
 | |
| 	encoding.BinaryMarshaler
 | |
| 	encoding.BinaryUnmarshaler
 | |
| 
 | |
| 	// Marshals the UUID bytes or data
 | |
| 	Bytes() (data []byte)
 | |
| 
 | |
| 	// Organises data into a new UUID
 | |
| 	Unmarshal(pData []byte)
 | |
| 
 | |
| 	// Size is used where different implementations require
 | |
| 	// different sizes. Should return the number of bytes in
 | |
| 	// the implementation.
 | |
| 	// Enables unmarshal and Bytes to screen for size
 | |
| 	Size() int
 | |
| 
 | |
| 	// Version returns a version number of the algorithm used
 | |
| 	// to generate the UUID.
 | |
| 	// This may may behave independently across non RFC4122 UUIDs
 | |
| 	Version() int
 | |
| 
 | |
| 	// Variant returns the UUID Variant
 | |
| 	// This will be one of the constants:
 | |
| 	// ReservedRFC4122,
 | |
| 	// ReservedMicrosoft,
 | |
| 	// ReservedFuture,
 | |
| 	// ReservedNCS.
 | |
| 	// This may behave differently across non RFC4122 UUIDs
 | |
| 	Variant() byte
 | |
| 
 | |
| 	// UUID can be used as a Name within a namespace
 | |
| 	// Is simply just a String() string method
 | |
| 	// Returns a formatted version of the UUID.
 | |
| 	String() string
 | |
| }
 | |
| 
 | |
| // New creates a UUID from a slice of bytes.
 | |
| // Truncates any bytes past the default length of 16
 | |
| // Will panic if data slice is too small.
 | |
| func New(pData []byte) UUID {
 | |
| 	o := new(Array)
 | |
| 	o.Unmarshal(pData[:length])
 | |
| 	return o
 | |
| }
 | |
| 
 | |
| 
 | |
| // Creates a UUID from a hex string
 | |
| // Will panic if hex string is invalid - will panic even with hyphens and brackets
 | |
| // Expects a clean string use Parse otherwise.
 | |
| func NewHex(pUuid string) UUID {
 | |
| 	bytes, err := hex.DecodeString(pUuid)
 | |
| 	if err != nil {
 | |
| 		panic(err)
 | |
| 	}
 | |
| 	return New(bytes)
 | |
| }
 | |
| 
 | |
| // 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]
 | |
| //
 | |
| func Parse(pUUID string) (UUID, error) {
 | |
| 	md := parseUUIDRegex.FindStringSubmatch(pUUID)
 | |
| 	if md == nil {
 | |
| 		return nil, errors.New("uuid.Parse: invalid string")
 | |
| 	}
 | |
| 	return NewHex(md[2] + md[3] + md[4] + md[5] + md[6]), nil
 | |
| }
 | |
| 
 | |
| // Digest a namespace UUID and a UniqueName, which then marshals to
 | |
| // a new UUID
 | |
| func Digest(o, pNs UUID, pName UniqueName, pHash hash.Hash) {
 | |
| 	// Hash writer never returns an error
 | |
| 	pHash.Write(pNs.Bytes())
 | |
| 	pHash.Write([]byte(pName.String()))
 | |
| 	o.Unmarshal(pHash.Sum(nil)[:o.Size()])
 | |
| }
 | |
| 
 | |
| // Function provides a safe way to unmarshal bytes into an
 | |
| // existing UUID.
 | |
| // Checks for length.
 | |
| func UnmarshalBinary(o UUID, pData []byte) error {
 | |
| 	if len(pData) != o.Size() {
 | |
| 		return errors.New("uuid.UnmarshalBinary: invalid length")
 | |
| 	}
 | |
| 	o.Unmarshal(pData)
 | |
| 	return nil
 | |
| }
 | |
| 
 | |
| // **********************************************  UUID Names
 | |
| 
 | |
| // A UUID Name is a simple string which implements UniqueName
 | |
| // which satisfies the Stringer interface.
 | |
| type Name string
 | |
| 
 | |
| // Returns the name as a string. Satisfies the Stringer interface.
 | |
| func (o Name) String() string {
 | |
| 	return string(o)
 | |
| }
 | |
| 
 | |
| // NewName will create a unique name from several sources
 | |
| func NewName(salt string, pNames ...UniqueName) UniqueName {
 | |
| 	var s string
 | |
| 	for _, s2 := range pNames {
 | |
| 		s += s2.String()
 | |
| 	}
 | |
| 	return Name(s + salt)
 | |
| }
 | |
| 
 | |
| // UniqueName is a Stinger interface
 | |
| // Made for easy passing of IPs, URLs, the several Address types,
 | |
| // Buffers and any other type which implements Stringer
 | |
| // string, []byte types and Hash sums will need to be cast to
 | |
| // the Name type or some other type which implements
 | |
| // Stringer or UniqueName
 | |
| type UniqueName interface {
 | |
| 
 | |
| 	// Many go types implement this method for use with printing
 | |
| 	// Will convert the current type to its native string format
 | |
| 	String() string
 | |
| }
 | |
| 
 | |
| // **********************************************  UUID Printing
 | |
| 
 | |
| // A Format is a pattern used by the stringer interface with which to print
 | |
| // the UUID.
 | |
| type Format string
 | |
| 
 | |
| const (
 | |
| 	Clean  Format = "%x%x%x%x%x%x"
 | |
| 	Curly  Format = "{%x%x%x%x%x%x}"
 | |
| 	Bracket Format = "(%x%x%x%x%x%x)"
 | |
| 
 | |
| 	// This is the default format.
 | |
| 	CleanHyphen Format = "%x-%x-%x-%x%x-%x"
 | |
| 
 | |
| 	CurlyHyphen   Format = "{%x-%x-%x-%x%x-%x}"
 | |
| 	BracketHyphen Format = "(%x-%x-%x-%x%x-%x)"
 | |
| 	GoIdFormat    Format = "[%X-%X-%x-%X%X-%x]"
 | |
| )
 | |
| 
 | |
| // Gets the current default format pattern
 | |
| func GetFormat() string {
 | |
| 	return format
 | |
| }
 | |
| 
 | |
| // Switches the default printing format for ALL UUID strings
 | |
| // A valid format will have 6 groups if the supplied Format does not
 | |
| func SwitchFormat(pFormat Format) {
 | |
| 	form := string(pFormat)
 | |
| 	if strings.Count(form, "%") != 6 {
 | |
| 		panic(errors.New("uuid.switchFormat: invalid formatting"))
 | |
| 	}
 | |
| 	format = form
 | |
| }
 | |
| 
 | |
| // Same as SwitchFormat but will make it uppercase
 | |
| func SwitchFormatUpperCase(pFormat Format) {
 | |
| 	form := strings.ToUpper(string(pFormat))
 | |
| 	SwitchFormat(Format(form))
 | |
| }
 | |
| 
 | |
| // Compares whether each UUID is the same
 | |
| func Equal(p1 UUID, p2 UUID) bool {
 | |
| 	return 	bytes.Equal(p1.Bytes(), p2.Bytes())
 | |
| }
 | |
| 
 | |
| // Format a UUID into a human readable string which matches the given Format
 | |
| // Use this for one time formatting when setting the default using SwitchFormat
 | |
| // is overkill.
 | |
| func Formatter(pUUID UUID, pFormat Format) string {
 | |
| 	form := string(pFormat)
 | |
| 	if strings.Count(form, "%") != 6 {
 | |
| 		panic(errors.New("uuid.Formatter: invalid formatting"))
 | |
| 	}
 | |
| 	return formatter(pUUID, form)
 | |
| }
 | |
| 
 | |
| // **********************************************  UUID Versions
 | |
| 
 | |
| type UUIDVersion int
 | |
| 
 | |
| const (
 | |
| 	NONE UUIDVersion = iota
 | |
| 	RFC4122v1
 | |
| 	DunnoYetv2
 | |
| 	RFC4122v3
 | |
| 	RFC4122v4
 | |
| 	RFC4122v5
 | |
| )
 | |
| 
 | |
| // ***************************************************  Helpers
 | |
| 
 | |
| // Retrieves the variant from the given byte
 | |
| func variant(pVariant byte) byte {
 | |
| 	switch pVariant & variantGet {
 | |
| 	case ReservedRFC4122, 0xA0:
 | |
| 		return ReservedRFC4122
 | |
| 	case ReservedMicrosoft:
 | |
| 		return ReservedMicrosoft
 | |
| 	case ReservedFuture:
 | |
| 		return ReservedFuture
 | |
| 	}
 | |
| 	return ReservedNCS
 | |
| }
 | |
| 
 | |
| // not strictly required
 | |
| func setVariant(pByte *byte, pVariant byte) {
 | |
| 	switch pVariant {
 | |
| 	case ReservedRFC4122:
 | |
| 		*pByte &= variantSet
 | |
| 	case ReservedFuture, ReservedMicrosoft:
 | |
| 		*pByte &= 0x1F
 | |
| 	case ReservedNCS:
 | |
| 		*pByte &= 0x7F
 | |
| 	default:
 | |
| 		panic(errors.New("uuid.setVariant: invalid variant mask"))
 | |
| 	}
 | |
| 	*pByte |= pVariant
 | |
| }
 | |
| 
 | |
| // format a UUID into a human readable string
 | |
| func formatter(pUUID UUID, pFormat string) string {
 | |
| 	b := pUUID.Bytes()
 | |
| 	return fmt.Sprintf(pFormat, b[0:4], b[4:6], b[6:8], b[8:9], b[9:10], b[10:pUUID.Size()])
 | |
| }
 | |
| 
 |