mirror of
				https://gitea.com/Lydanne/buildx.git
				synced 2025-11-04 18:13:42 +08:00 
			
		
		
		
	Update modules: go mod edit -require github.com/moby/buildkit@master go mod tidy -compat=1.17 && ./hack/update-vendor Signed-off-by: Justin Chadwell <me@jedevc.com>
		
			
				
	
	
		
			229 lines
		
	
	
		
			5.8 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			229 lines
		
	
	
		
			5.8 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
// +build windows
 | 
						|
 | 
						|
// Package guid provides a GUID type. The backing structure for a GUID is
 | 
						|
// identical to that used by the golang.org/x/sys/windows GUID type.
 | 
						|
// There are two main binary encodings used for a GUID, the big-endian encoding,
 | 
						|
// and the Windows (mixed-endian) encoding. See here for details:
 | 
						|
// https://en.wikipedia.org/wiki/Universally_unique_identifier#Encoding
 | 
						|
package guid
 | 
						|
 | 
						|
import (
 | 
						|
	"crypto/rand"
 | 
						|
	"crypto/sha1"
 | 
						|
	"encoding"
 | 
						|
	"encoding/binary"
 | 
						|
	"fmt"
 | 
						|
	"strconv"
 | 
						|
)
 | 
						|
 | 
						|
// Variant specifies which GUID variant (or "type") of the GUID. It determines
 | 
						|
// how the entirety of the rest of the GUID is interpreted.
 | 
						|
type Variant uint8
 | 
						|
 | 
						|
// The variants specified by RFC 4122.
 | 
						|
const (
 | 
						|
	// VariantUnknown specifies a GUID variant which does not conform to one of
 | 
						|
	// the variant encodings specified in RFC 4122.
 | 
						|
	VariantUnknown Variant = iota
 | 
						|
	VariantNCS
 | 
						|
	VariantRFC4122
 | 
						|
	VariantMicrosoft
 | 
						|
	VariantFuture
 | 
						|
)
 | 
						|
 | 
						|
// Version specifies how the bits in the GUID were generated. For instance, a
 | 
						|
// version 4 GUID is randomly generated, and a version 5 is generated from the
 | 
						|
// hash of an input string.
 | 
						|
type Version uint8
 | 
						|
 | 
						|
var _ = (encoding.TextMarshaler)(GUID{})
 | 
						|
var _ = (encoding.TextUnmarshaler)(&GUID{})
 | 
						|
 | 
						|
// NewV4 returns a new version 4 (pseudorandom) GUID, as defined by RFC 4122.
 | 
						|
func NewV4() (GUID, error) {
 | 
						|
	var b [16]byte
 | 
						|
	if _, err := rand.Read(b[:]); err != nil {
 | 
						|
		return GUID{}, err
 | 
						|
	}
 | 
						|
 | 
						|
	g := FromArray(b)
 | 
						|
	g.setVersion(4) // Version 4 means randomly generated.
 | 
						|
	g.setVariant(VariantRFC4122)
 | 
						|
 | 
						|
	return g, nil
 | 
						|
}
 | 
						|
 | 
						|
// NewV5 returns a new version 5 (generated from a string via SHA-1 hashing)
 | 
						|
// GUID, as defined by RFC 4122. The RFC is unclear on the encoding of the name,
 | 
						|
// and the sample code treats it as a series of bytes, so we do the same here.
 | 
						|
//
 | 
						|
// Some implementations, such as those found on Windows, treat the name as a
 | 
						|
// big-endian UTF16 stream of bytes. If that is desired, the string can be
 | 
						|
// encoded as such before being passed to this function.
 | 
						|
func NewV5(namespace GUID, name []byte) (GUID, error) {
 | 
						|
	b := sha1.New()
 | 
						|
	namespaceBytes := namespace.ToArray()
 | 
						|
	b.Write(namespaceBytes[:])
 | 
						|
	b.Write(name)
 | 
						|
 | 
						|
	a := [16]byte{}
 | 
						|
	copy(a[:], b.Sum(nil))
 | 
						|
 | 
						|
	g := FromArray(a)
 | 
						|
	g.setVersion(5) // Version 5 means generated from a string.
 | 
						|
	g.setVariant(VariantRFC4122)
 | 
						|
 | 
						|
	return g, nil
 | 
						|
}
 | 
						|
 | 
						|
func fromArray(b [16]byte, order binary.ByteOrder) GUID {
 | 
						|
	var g GUID
 | 
						|
	g.Data1 = order.Uint32(b[0:4])
 | 
						|
	g.Data2 = order.Uint16(b[4:6])
 | 
						|
	g.Data3 = order.Uint16(b[6:8])
 | 
						|
	copy(g.Data4[:], b[8:16])
 | 
						|
	return g
 | 
						|
}
 | 
						|
 | 
						|
func (g GUID) toArray(order binary.ByteOrder) [16]byte {
 | 
						|
	b := [16]byte{}
 | 
						|
	order.PutUint32(b[0:4], g.Data1)
 | 
						|
	order.PutUint16(b[4:6], g.Data2)
 | 
						|
	order.PutUint16(b[6:8], g.Data3)
 | 
						|
	copy(b[8:16], g.Data4[:])
 | 
						|
	return b
 | 
						|
}
 | 
						|
 | 
						|
// FromArray constructs a GUID from a big-endian encoding array of 16 bytes.
 | 
						|
func FromArray(b [16]byte) GUID {
 | 
						|
	return fromArray(b, binary.BigEndian)
 | 
						|
}
 | 
						|
 | 
						|
// ToArray returns an array of 16 bytes representing the GUID in big-endian
 | 
						|
// encoding.
 | 
						|
func (g GUID) ToArray() [16]byte {
 | 
						|
	return g.toArray(binary.BigEndian)
 | 
						|
}
 | 
						|
 | 
						|
// FromWindowsArray constructs a GUID from a Windows encoding array of bytes.
 | 
						|
func FromWindowsArray(b [16]byte) GUID {
 | 
						|
	return fromArray(b, binary.LittleEndian)
 | 
						|
}
 | 
						|
 | 
						|
// ToWindowsArray returns an array of 16 bytes representing the GUID in Windows
 | 
						|
// encoding.
 | 
						|
func (g GUID) ToWindowsArray() [16]byte {
 | 
						|
	return g.toArray(binary.LittleEndian)
 | 
						|
}
 | 
						|
 | 
						|
func (g GUID) String() string {
 | 
						|
	return fmt.Sprintf(
 | 
						|
		"%08x-%04x-%04x-%04x-%012x",
 | 
						|
		g.Data1,
 | 
						|
		g.Data2,
 | 
						|
		g.Data3,
 | 
						|
		g.Data4[:2],
 | 
						|
		g.Data4[2:])
 | 
						|
}
 | 
						|
 | 
						|
// FromString parses a string containing a GUID and returns the GUID. The only
 | 
						|
// format currently supported is the `xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx`
 | 
						|
// format.
 | 
						|
func FromString(s string) (GUID, error) {
 | 
						|
	if len(s) != 36 {
 | 
						|
		return GUID{}, fmt.Errorf("invalid GUID %q", s)
 | 
						|
	}
 | 
						|
	if s[8] != '-' || s[13] != '-' || s[18] != '-' || s[23] != '-' {
 | 
						|
		return GUID{}, fmt.Errorf("invalid GUID %q", s)
 | 
						|
	}
 | 
						|
 | 
						|
	var g GUID
 | 
						|
 | 
						|
	data1, err := strconv.ParseUint(s[0:8], 16, 32)
 | 
						|
	if err != nil {
 | 
						|
		return GUID{}, fmt.Errorf("invalid GUID %q", s)
 | 
						|
	}
 | 
						|
	g.Data1 = uint32(data1)
 | 
						|
 | 
						|
	data2, err := strconv.ParseUint(s[9:13], 16, 16)
 | 
						|
	if err != nil {
 | 
						|
		return GUID{}, fmt.Errorf("invalid GUID %q", s)
 | 
						|
	}
 | 
						|
	g.Data2 = uint16(data2)
 | 
						|
 | 
						|
	data3, err := strconv.ParseUint(s[14:18], 16, 16)
 | 
						|
	if err != nil {
 | 
						|
		return GUID{}, fmt.Errorf("invalid GUID %q", s)
 | 
						|
	}
 | 
						|
	g.Data3 = uint16(data3)
 | 
						|
 | 
						|
	for i, x := range []int{19, 21, 24, 26, 28, 30, 32, 34} {
 | 
						|
		v, err := strconv.ParseUint(s[x:x+2], 16, 8)
 | 
						|
		if err != nil {
 | 
						|
			return GUID{}, fmt.Errorf("invalid GUID %q", s)
 | 
						|
		}
 | 
						|
		g.Data4[i] = uint8(v)
 | 
						|
	}
 | 
						|
 | 
						|
	return g, nil
 | 
						|
}
 | 
						|
 | 
						|
func (g *GUID) setVariant(v Variant) {
 | 
						|
	d := g.Data4[0]
 | 
						|
	switch v {
 | 
						|
	case VariantNCS:
 | 
						|
		d = (d & 0x7f)
 | 
						|
	case VariantRFC4122:
 | 
						|
		d = (d & 0x3f) | 0x80
 | 
						|
	case VariantMicrosoft:
 | 
						|
		d = (d & 0x1f) | 0xc0
 | 
						|
	case VariantFuture:
 | 
						|
		d = (d & 0x0f) | 0xe0
 | 
						|
	case VariantUnknown:
 | 
						|
		fallthrough
 | 
						|
	default:
 | 
						|
		panic(fmt.Sprintf("invalid variant: %d", v))
 | 
						|
	}
 | 
						|
	g.Data4[0] = d
 | 
						|
}
 | 
						|
 | 
						|
// Variant returns the GUID variant, as defined in RFC 4122.
 | 
						|
func (g GUID) Variant() Variant {
 | 
						|
	b := g.Data4[0]
 | 
						|
	if b&0x80 == 0 {
 | 
						|
		return VariantNCS
 | 
						|
	} else if b&0xc0 == 0x80 {
 | 
						|
		return VariantRFC4122
 | 
						|
	} else if b&0xe0 == 0xc0 {
 | 
						|
		return VariantMicrosoft
 | 
						|
	} else if b&0xe0 == 0xe0 {
 | 
						|
		return VariantFuture
 | 
						|
	}
 | 
						|
	return VariantUnknown
 | 
						|
}
 | 
						|
 | 
						|
func (g *GUID) setVersion(v Version) {
 | 
						|
	g.Data3 = (g.Data3 & 0x0fff) | (uint16(v) << 12)
 | 
						|
}
 | 
						|
 | 
						|
// Version returns the GUID version, as defined in RFC 4122.
 | 
						|
func (g GUID) Version() Version {
 | 
						|
	return Version((g.Data3 & 0xF000) >> 12)
 | 
						|
}
 | 
						|
 | 
						|
// MarshalText returns the textual representation of the GUID.
 | 
						|
func (g GUID) MarshalText() ([]byte, error) {
 | 
						|
	return []byte(g.String()), nil
 | 
						|
}
 | 
						|
 | 
						|
// UnmarshalText takes the textual representation of a GUID, and unmarhals it
 | 
						|
// into this GUID.
 | 
						|
func (g *GUID) UnmarshalText(text []byte) error {
 | 
						|
	g2, err := FromString(string(text))
 | 
						|
	if err != nil {
 | 
						|
		return err
 | 
						|
	}
 | 
						|
	*g = g2
 | 
						|
	return nil
 | 
						|
}
 |