mirror of
https://github.com/PretendoNetwork/nex-go.git
synced 2025-04-02 11:02:14 -04:00
186 lines
4.6 KiB
Go
186 lines
4.6 KiB
Go
package types
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/hex"
|
|
"errors"
|
|
"fmt"
|
|
"slices"
|
|
"strings"
|
|
)
|
|
|
|
// QUUID is an implementation of rdv::qUUID.
|
|
// Type alias of []byte.
|
|
// Encodes a UUID in little-endian byte order.
|
|
type QUUID []byte
|
|
|
|
// WriteTo writes the QUUID to the given writable
|
|
func (qu QUUID) WriteTo(writable Writable) {
|
|
writable.Write(qu)
|
|
}
|
|
|
|
// ExtractFrom extracts the QUUID from the given readable
|
|
func (qu *QUUID) ExtractFrom(readable Readable) error {
|
|
if readable.Remaining() < 16 {
|
|
return errors.New("Not enough data left to read qUUID")
|
|
}
|
|
|
|
*qu, _ = readable.Read(16)
|
|
return nil
|
|
}
|
|
|
|
// Copy returns a new copied instance of qUUID
|
|
func (qu QUUID) Copy() RVType {
|
|
return NewQUUID(qu)
|
|
}
|
|
|
|
// Equals checks if the passed Structure contains the same data as the current instance
|
|
func (qu QUUID) Equals(o RVType) bool {
|
|
if _, ok := o.(QUUID); !ok {
|
|
return false
|
|
}
|
|
|
|
return bytes.Equal(qu, o.(QUUID))
|
|
}
|
|
|
|
// CopyRef copies the current value of the QUUID
|
|
// and returns a pointer to the new copy
|
|
func (qu QUUID) CopyRef() RVTypePtr {
|
|
copied := qu.Copy().(QUUID)
|
|
return &copied
|
|
}
|
|
|
|
// Deref takes a pointer to the QUUID
|
|
// and dereferences it to the raw value.
|
|
// Only useful when working with an instance of RVTypePtr
|
|
func (qu *QUUID) Deref() RVType {
|
|
return *qu
|
|
}
|
|
|
|
// String returns a string representation of the struct
|
|
func (qu QUUID) String() string {
|
|
return qu.FormatToString(0)
|
|
}
|
|
|
|
// FormatToString pretty-prints the struct data using the provided indentation level
|
|
func (qu QUUID) FormatToString(indentationLevel int) string {
|
|
indentationValues := strings.Repeat("\t", indentationLevel+1)
|
|
indentationEnd := strings.Repeat("\t", indentationLevel)
|
|
|
|
var b strings.Builder
|
|
|
|
b.WriteString("qUUID{\n")
|
|
b.WriteString(fmt.Sprintf("%sUUID: %s\n", indentationValues, qu.GetStringValue()))
|
|
b.WriteString(fmt.Sprintf("%s}", indentationEnd))
|
|
|
|
return b.String()
|
|
}
|
|
|
|
// GetStringValue returns the UUID encoded in the qUUID
|
|
func (qu QUUID) GetStringValue() string {
|
|
// * Create copy of the data since slices.Reverse modifies the slice in-line
|
|
data := make([]byte, len(qu))
|
|
copy(data, qu)
|
|
|
|
if len(data) != 16 {
|
|
// * Default dummy UUID as found in WATCH_DOGS
|
|
return "00000000-0000-0000-0000-000000000002"
|
|
}
|
|
|
|
section1 := data[0:4]
|
|
section2 := data[4:6]
|
|
section3 := data[6:8]
|
|
section4 := data[8:10]
|
|
section5_1 := data[10:12]
|
|
section5_2 := data[12:14]
|
|
section5_3 := data[14:16]
|
|
|
|
slices.Reverse(section1)
|
|
slices.Reverse(section2)
|
|
slices.Reverse(section3)
|
|
slices.Reverse(section4)
|
|
slices.Reverse(section5_1)
|
|
slices.Reverse(section5_2)
|
|
slices.Reverse(section5_3)
|
|
|
|
var b strings.Builder
|
|
|
|
b.WriteString(hex.EncodeToString(section1))
|
|
b.WriteString("-")
|
|
b.WriteString(hex.EncodeToString(section2))
|
|
b.WriteString("-")
|
|
b.WriteString(hex.EncodeToString(section3))
|
|
b.WriteString("-")
|
|
b.WriteString(hex.EncodeToString(section4))
|
|
b.WriteString("-")
|
|
b.WriteString(hex.EncodeToString(section5_1))
|
|
b.WriteString(hex.EncodeToString(section5_2))
|
|
b.WriteString(hex.EncodeToString(section5_3))
|
|
|
|
return b.String()
|
|
}
|
|
|
|
// FromString converts a UUID string to a qUUID
|
|
func (qu *QUUID) FromString(uuid string) error {
|
|
sections := strings.Split(uuid, "-")
|
|
if len(sections) != 5 {
|
|
return fmt.Errorf("Invalid UUID. Not enough sections. Expected 5, got %d", len(sections))
|
|
}
|
|
|
|
data := make([]byte, 0, 16)
|
|
|
|
var appendSection = func(section string, expectedSize int) error {
|
|
sectionBytes, err := hex.DecodeString(section)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if len(sectionBytes) != expectedSize {
|
|
return fmt.Errorf("Unexpected section size. Expected %d, got %d", expectedSize, len(sectionBytes))
|
|
}
|
|
|
|
data = append(data, sectionBytes...)
|
|
|
|
return nil
|
|
}
|
|
|
|
if err := appendSection(sections[0], 4); err != nil {
|
|
return fmt.Errorf("Failed to read UUID section 1. %s", err.Error())
|
|
}
|
|
|
|
if err := appendSection(sections[1], 2); err != nil {
|
|
return fmt.Errorf("Failed to read UUID section 2. %s", err.Error())
|
|
}
|
|
|
|
if err := appendSection(sections[2], 2); err != nil {
|
|
return fmt.Errorf("Failed to read UUID section 3. %s", err.Error())
|
|
}
|
|
|
|
if err := appendSection(sections[3], 2); err != nil {
|
|
return fmt.Errorf("Failed to read UUID section 4. %s", err.Error())
|
|
}
|
|
|
|
if err := appendSection(sections[4], 6); err != nil {
|
|
return fmt.Errorf("Failed to read UUID section 5. %s", err.Error())
|
|
}
|
|
|
|
slices.Reverse(data[0:4])
|
|
slices.Reverse(data[4:6])
|
|
slices.Reverse(data[6:8])
|
|
slices.Reverse(data[8:10])
|
|
slices.Reverse(data[10:12])
|
|
slices.Reverse(data[12:14])
|
|
slices.Reverse(data[14:16])
|
|
|
|
*qu = data
|
|
|
|
return nil
|
|
}
|
|
|
|
// NewQUUID returns a new qUUID
|
|
func NewQUUID(input []byte) QUUID {
|
|
qu := make(QUUID, len(input))
|
|
copy(qu, input)
|
|
|
|
return qu
|
|
}
|