mirror of
https://github.com/mudler/luet.git
synced 2025-06-27 07:50:18 +00:00
Instead of using gox on one side and an action to release, we can merge them together with goreleaser which will build for extra targets (arm, mips if needed in the future) and it also takes care of creating checksums, a source archive, and a changelog and creating a release with all the artifacts. All binaries should respect the old naming convention, so any scripts out there should still work. Signed-off-by: Itxaka <igarcia@suse.com>
238 lines
6.1 KiB
Go
238 lines
6.1 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"
|
|
|
|
"golang.org/x/sys/windows"
|
|
)
|
|
|
|
// 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{})
|
|
|
|
// GUID represents a GUID/UUID. It has the same structure as
|
|
// golang.org/x/sys/windows.GUID so that it can be used with functions expecting
|
|
// that type. It is defined as its own type so that stringification and
|
|
// marshaling can be supported. The representation matches that used by native
|
|
// Windows code.
|
|
type GUID windows.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
|
|
}
|