blob: 393e5481a18e237f4128bc177aeaf29eb05317f3 [file] [log] [blame]
package gatt
import (
"bytes"
"encoding/binary"
"encoding/hex"
"fmt"
"strings"
)
// A UUID is a BLE UUID.
type UUID struct {
// Hide the bytes, so that we can enforce that they have length 2 or 16,
// and that they are immutable. This simplifies the code and API.
b []byte
}
// UUID16 converts a uint16 (such as 0x1800) to a UUID.
func UUID16(i uint16) UUID {
b := make([]byte, 2)
binary.LittleEndian.PutUint16(b, i)
return UUID{b}
}
// ParseUUID parses a standard-format UUID string, such
// as "1800" or "34DA3AD1-7110-41A1-B1EF-4430F509CDE7".
func ParseUUID(s string) (UUID, error) {
s = strings.Replace(s, "-", "", -1)
b, err := hex.DecodeString(s)
if err != nil {
return UUID{}, err
}
if err := lenErr(len(b)); err != nil {
return UUID{}, err
}
return UUID{reverse(b)}, nil
}
// MustParseUUID parses a standard-format UUID string,
// like ParseUUID, but panics in case of error.
func MustParseUUID(s string) UUID {
u, err := ParseUUID(s)
if err != nil {
panic(err)
}
return u
}
// lenErr returns an error if n is an invalid UUID length.
func lenErr(n int) error {
switch n {
case 2, 16:
return nil
}
return fmt.Errorf("UUIDs must have length 2 or 16, got %d", n)
}
// Len returns the length of the UUID, in bytes.
// BLE UUIDs are either 2 or 16 bytes.
func (u UUID) Len() int {
return len(u.b)
}
// String hex-encodes a UUID.
func (u UUID) String() string {
return fmt.Sprintf("%x", reverse(u.b))
}
// Equal returns a boolean reporting whether v represent the same UUID as u.
func (u UUID) Equal(v UUID) bool {
return bytes.Equal(u.b, v.b)
}
// reverse returns a reversed copy of u.
func reverse(u []byte) []byte {
// Special-case 16 bit UUIDS for speed.
l := len(u)
if l == 2 {
return []byte{u[1], u[0]}
}
b := make([]byte, l)
for i := 0; i < l/2+1; i++ {
b[i], b[l-i-1] = u[l-i-1], u[i]
}
return b
}