Skip to content
Browse files

more cassandra type support

  • Loading branch information...
1 parent 2cb0860 commit c54beaa21c7f190ef76da8908f57f7ee66f36fe6 @carloscm committed Apr 28, 2012
View
6 schema-test.txt
@@ -34,3 +34,9 @@ create column family Reasonable with
key_validation_class = UTF8Type and
default_validation_class = BytesType
;
+
+create column family Timeseries with
+ comparator = 'CompositeType(TimeUUIDType(reversed=true),AsciiType)' and
+ key_validation_class = UTF8Type and
+ default_validation_class = BytesType
+;
View
6 src/gossie/connection.go
@@ -3,13 +3,13 @@ package gossie
import (
"cassandra"
"errors"
+ "fmt"
"math/rand"
"net"
+ "strconv"
+ "strings"
"thrift"
"time"
- "strings"
- "strconv"
- "fmt"
)
/*
View
60 src/gossie/cursor.go
@@ -24,7 +24,7 @@ var (
)
const (
- DEFAULT_LIMIT_COLUMNS = 100
+ DEFAULT_LIMIT_COLUMNS = 100
)
// Cursor is a simple cursor-based interface for reading and writing structs from a Cassandra column family.
@@ -45,47 +45,47 @@ type Cursor interface {
//Delete()
- // Options sets the options for this Cursor
- Options(CursorOptions)
+ // Options sets the options for this Cursor
+ Options(CursorOptions)
}
// CursorOptions stores some options that modify the behaviour of the queries a Cursor performs
type CursorOptions struct {
- // LimitColumns is the max number of columns that will be read from Cassandra. Default is 100.
- LimitColumns int
+ // LimitColumns is the max number of columns that will be read from Cassandra. Default is 100.
+ LimitColumns int
- // WriteConsistency overrides the default write consistency level for the underlying connection pool.
- // Default is 0 which means to not override the consistenct level.
- WriteConsistency int
+ // WriteConsistency overrides the default write consistency level for the underlying connection pool.
+ // Default is 0 which means to not override the consistenct level.
+ WriteConsistency int
- // ReadConsistency overrides the default read consistency level for the underlying connection pool.
- // Default is 0 which means to not override the consistenct level.
- ReadConsistency int
+ // ReadConsistency overrides the default read consistency level for the underlying connection pool.
+ // Default is 0 which means to not override the consistenct level.
+ ReadConsistency int
}
type cursor struct {
- pool *connectionPool
- options CursorOptions
+ pool *connectionPool
+ options CursorOptions
}
func (co *CursorOptions) defaults() {
- if co.LimitColumns == 0 {
- co.LimitColumns = DEFAULT_LIMIT_COLUMNS
- }
+ if co.LimitColumns == 0 {
+ co.LimitColumns = DEFAULT_LIMIT_COLUMNS
+ }
}
func newCursor(cp *connectionPool) *cursor {
- c := &cursor{
- pool: cp,
- }
- c.options.defaults()
+ c := &cursor{
+ pool: cp,
+ }
+ c.options.defaults()
return c
}
func (c *cursor) Options(options CursorOptions) {
- options.defaults()
- c.options = options
+ options.defaults()
+ c.options = options
}
func (c *cursor) Write(source interface{}) error {
@@ -95,13 +95,13 @@ func (c *cursor) Write(source interface{}) error {
return err
}
- m := c.pool.Mutation().Insert(mi.m.cf, row)
+ m := c.pool.Mutation().Insert(mi.m.cf, row)
- if c.options.WriteConsistency != 0 {
- m.ConsistencyLevel(c.options.WriteConsistency)
- }
+ if c.options.WriteConsistency != 0 {
+ m.ConsistencyLevel(c.options.WriteConsistency)
+ }
- return m.Run()
+ return m.Run()
}
func (c *cursor) Read(source interface{}) error {
@@ -122,9 +122,9 @@ func (c *cursor) Read(source interface{}) error {
// start building the query
q := c.pool.Query().Cf(mi.m.cf)
- if c.options.ReadConsistency != 0 {
- q.ConsistencyLevel(c.options.ReadConsistency)
- }
+ if c.options.ReadConsistency != 0 {
+ q.ConsistencyLevel(c.options.ReadConsistency)
+ }
// build a slice composite comparator if needed
if len(mi.m.composite) > 0 {
View
1 src/gossie/query.go
@@ -11,6 +11,7 @@ import (
to do:
support Where for RangeGet in Cassandra 1.1
figure out what's the deal with get_paged_slice in 1.1 and try to implement it in a sane way
+ override retries to 1 for mutations that include DeltaCounters, document it?
*/
// Columns encapsulate the individual columns from/to Cassandra reads and writes
View
4 src/gossie/query_test.go
@@ -49,7 +49,7 @@ func buildCounterRow(key string) *Row {
}
func buildAllTypesTestRow(key string) *testRow {
- u, _ := NewUUID("00112233-4455-6677-8899-aabbccddeeff")
+ u, _ := ParseUUID("00112233-4455-6677-8899-aabbccddeeff")
return &testRow{
key: key, keyType: BytesType, columns: []testColumn{
testColumn{"colAsciiType", AsciiType, "hi!", AsciiType},
@@ -65,7 +65,7 @@ func buildAllTypesTestRow(key string) *testRow {
}
func buildAllTypesAfterDeletesTestRow(key string) *testRow {
- u, _ := NewUUID("00112233-4455-6677-8899-aabbccddeeff")
+ u, _ := ParseUUID("00112233-4455-6677-8899-aabbccddeeff")
return &testRow{
key: key, keyType: BytesType, columns: []testColumn{
testColumn{"colBytesType", AsciiType, []byte{1, 2, 3}, BytesType},
View
41 src/gossie/schema_test.go
@@ -16,8 +16,8 @@ func TestSchema(t *testing.T) {
schema := newSchema(ksDef)
defer c.close()
- if len(schema.ColumnFamilies) != 4 {
- t.Error("Test schema must have 3 CFs")
+ if len(schema.ColumnFamilies) != 5 {
+ t.Error("Test schema must have 5 CFs")
}
if schema.ColumnFamilies["AllTypes"] == nil {
@@ -58,7 +58,6 @@ func TestSchema(t *testing.T) {
t.Error("Test CF AllTypes column ", name, " is not the expected type")
}
}
-
}
if schema.ColumnFamilies["Counters"] == nil {
@@ -111,6 +110,42 @@ func TestSchema(t *testing.T) {
t.Error("Test CF Composite comparator has incorrect comparator in position ", i)
}
}
+ }
+
+ if schema.ColumnFamilies["Timeseries"] == nil {
+ t.Error("Test CF Timeseries is nil")
+ } else {
+ cf := schema.ColumnFamilies["Timeseries"]
+
+ if cf.DefaultComparator.Desc != CompositeType {
+ t.Error("Test CF Timeseries DefaultComparator is not CompositeType")
+ }
+ if cf.DefaultValidator.Desc != BytesType {
+ t.Error("Test CF Timeseries DefaultValidator is not BytesType")
+ }
+ if cf.KeyValidator.Desc != UTF8Type {
+ t.Error("Test CF Timeseries KeyValidator is not BytesType")
+ }
+
+ if len(cf.NamedColumns) != 0 {
+ t.Error("Test CF Timeseries has named columns")
+ }
+
+ var check = []TypeDesc{TimeUUIDType, AsciiType}
+ var reversed = []bool{true, false}
+
+ if len(cf.DefaultComparator.Components) != len(check) {
+ t.Error("Test CF Timeseries has incorrect number of components")
+ }
+
+ for i, desc := range check {
+ if cf.DefaultComparator.Components[i].Desc != desc {
+ t.Error("Test CF Timeseries comparator has incorrect comparator in position ", i)
+ }
+ if cf.DefaultComparator.Components[i].Reversed != reversed[i] {
+ t.Error("Test CF Timeseries comparator has incorrect Reversed flag in position ", i)
+ }
+ }
}
View
183 src/gossie/types.go
@@ -4,27 +4,26 @@ import (
"bytes"
enc "encoding/binary"
"errors"
- "fmt"
"strconv"
"strings"
+ "time"
)
/*
- to do:
+ to do:
- ReversedType
+ Int32Type
- IntegerType
- DecimalType
+ IntegerType
+ DecimalType
- don't assume int is int32 (tho it's prob ok)
- uints, support them?
+ don't assume int is int32 (tho it's prob ok)
+ uints, support them?
- maybe add ascii/utf8 types support UUIDType, string native support?
- maybe something better for DateType, instead of just int64 conv (go v1)?
- maybe some more (un)marshalings?
+ maybe add ascii/utf8 types support UUIDType, string native support?
+ maybe some more (un)marshalings?
- more error checking, pass along all strconv errors
+ more error checking, pass along all strconv errors
*/
const (
@@ -34,9 +33,12 @@ const (
AsciiType
UTF8Type
LongType
+ Int32Type
IntegerType
DecimalType
UUIDType
+ TimeUUIDType
+ LexicalUUIDType
BooleanType
FloatType
DoubleType
@@ -56,48 +58,6 @@ var (
type TypeDesc int
-type UUID [16]byte
-
-func (value UUID) String() string {
- var r []string
- var s int
- for _, size := range [5]int{4, 2, 2, 2, 6} {
- var v int64
- for i := 0; i < size; i++ {
- v = v << 8
- v = v | int64(value[s+i])
- }
- r = append(r, fmt.Sprintf("%0*x", size*2, v))
- s += size
- }
- return strings.Join(r, "-")
-}
-
-func NewUUID(value string) (UUID, error) {
- var r []byte
- var ru UUID
-
- if len(value) != 36 {
- return ru, ErrorUnsupportedMarshaling
- }
- ints := strings.Split(value, "-")
- if len(ints) != 5 {
- return ru, ErrorUnsupportedMarshaling
- }
-
- for i, size := range [5]int{4, 2, 2, 2, 6} {
- t, err := strconv.ParseInt(ints[i], 16, 64)
- if err != nil {
- return ru, ErrorUnsupportedMarshaling
- }
- b, _ := marshalInt(t, size, BytesType)
- r = append(r, b...)
- }
-
- unmarshalUUID(r, BytesType, &ru)
- return ru, nil
-}
-
func Marshal(value interface{}, typeDesc TypeDesc) ([]byte, error) {
// plain nil case
if value == nil {
@@ -162,6 +122,11 @@ func Marshal(value interface{}, typeDesc TypeDesc) ([]byte, error) {
return nil, ErrorUnsupportedNilMarshaling
}
dvalue = *v
+ case *time.Time:
+ if v == nil {
+ return nil, ErrorUnsupportedNilMarshaling
+ }
+ dvalue = *v
default:
dvalue = v
}
@@ -189,6 +154,8 @@ func Marshal(value interface{}, typeDesc TypeDesc) ([]byte, error) {
return marshalFloat32(v, typeDesc)
case float64:
return marshalFloat64(v, typeDesc)
+ case time.Time:
+ return marshalTime(v, typeDesc)
}
return nil, ErrorUnsupportedMarshaling
}
@@ -217,6 +184,13 @@ func marshalBool(value bool, typeDesc TypeDesc) ([]byte, error) {
b[7] = 1
}
return b, nil
+
+ case Int32Type:
+ b := make([]byte, 4)
+ if value {
+ b[3] = 1
+ }
+ return b, nil
}
return nil, ErrorUnsupportedMarshaling
}
@@ -229,6 +203,11 @@ func marshalInt(value int64, size int, typeDesc TypeDesc) ([]byte, error) {
enc.BigEndian.PutUint64(b, uint64(value))
return b, nil
+ case Int32Type:
+ b := make([]byte, 4)
+ enc.BigEndian.PutUint32(b, uint32(value))
+ return b, nil
+
case BytesType:
b := make([]byte, 8)
enc.BigEndian.PutUint64(b, uint64(value))
@@ -248,6 +227,26 @@ func marshalInt(value int64, size int, typeDesc TypeDesc) ([]byte, error) {
return nil, ErrorUnsupportedMarshaling
}
+func marshalTime(value time.Time, typeDesc TypeDesc) ([]byte, error) {
+ switch typeDesc {
+ // following Java conventions Cassandra standarizes this as millis
+ case LongType, BytesType, DateType:
+ valueI := value.UnixNano() / 1e6
+ b := make([]byte, 8)
+ enc.BigEndian.PutUint64(b, uint64(valueI))
+ return b, nil
+
+ // 32 bit, so assume regular unix time
+ case Int32Type:
+ valueI := value.Unix()
+ b := make([]byte, 4)
+ enc.BigEndian.PutUint32(b, uint32(valueI))
+ return b, nil
+
+ }
+ return nil, ErrorUnsupportedMarshaling
+}
+
func marshalString(value string, typeDesc TypeDesc) ([]byte, error) {
// let cassandra check the ascii-ness of the []byte
switch typeDesc {
@@ -266,7 +265,7 @@ func marshalString(value string, typeDesc TypeDesc) ([]byte, error) {
func marshalUUID(value UUID, typeDesc TypeDesc) ([]byte, error) {
switch typeDesc {
- case BytesType, UUIDType:
+ case BytesType, UUIDType, TimeUUIDType, LexicalUUIDType:
return []byte(value[:]), nil
}
return nil, ErrorUnsupportedMarshaling
@@ -340,6 +339,8 @@ func Unmarshal(b []byte, typeDesc TypeDesc, value interface{}) error {
return unmarshalFloat32(b, typeDesc, v)
case *float64:
return unmarshalFloat64(b, typeDesc, v)
+ case *time.Time:
+ return unmarshalTime(b, typeDesc, v)
}
return ErrorUnsupportedNativeTypeUnmarshaling
}
@@ -378,6 +379,18 @@ func unmarshalBool(b []byte, typeDesc TypeDesc, value *bool) error {
*value = true
}
return nil
+
+ case Int32Type:
+ if len(b) != 4 {
+ return ErrorCassandraTypeSerializationUnmarshaling
+ }
+ if b[3] == 0 {
+ *value = false
+ } else {
+ *value = true
+ }
+ return nil
+
}
return ErrorUnsupportedCassandraTypeUnmarshaling
}
@@ -406,6 +419,29 @@ func unmarshalInt64(b []byte, typeDesc TypeDesc, value *int64) error {
return ErrorUnsupportedCassandraTypeUnmarshaling
}
+func unmarshalTime(b []byte, typeDesc TypeDesc, value *time.Time) error {
+ switch typeDesc {
+ case LongType, BytesType, DateType:
+ if len(b) != 8 {
+ return ErrorCassandraTypeSerializationUnmarshaling
+ }
+ valueI := int64(enc.BigEndian.Uint64(b))
+ // following Java conventions Cassandra standarizes this as millis
+ *value = time.Unix(valueI/1000, (valueI%1000)*1e6)
+ return nil
+
+ case Int32Type:
+ if len(b) != 4 {
+ return ErrorCassandraTypeSerializationUnmarshaling
+ }
+ valueI := int64(enc.BigEndian.Uint32(b))
+ // 32 bit, so assume regular unix time
+ *value = time.Unix(valueI*1e9, 0)
+ return nil
+ }
+ return ErrorUnsupportedCassandraTypeUnmarshaling
+}
+
func unmarshalInt32(b []byte, typeDesc TypeDesc, value *int32) error {
switch typeDesc {
case LongType:
@@ -415,7 +451,7 @@ func unmarshalInt32(b []byte, typeDesc TypeDesc, value *int32) error {
*value = int32(enc.BigEndian.Uint64(b))
return nil
- case BytesType:
+ case BytesType, Int32Type:
if len(b) != 4 {
return ErrorCassandraTypeSerializationUnmarshaling
}
@@ -447,6 +483,13 @@ func unmarshalInt16(b []byte, typeDesc TypeDesc, value *int16) error {
*value = int16(enc.BigEndian.Uint64(b))
return nil
+ case Int32Type:
+ if len(b) != 4 {
+ return ErrorCassandraTypeSerializationUnmarshaling
+ }
+ *value = int16(enc.BigEndian.Uint32(b))
+ return nil
+
case BytesType:
if len(b) != 2 {
return ErrorCassandraTypeSerializationUnmarshaling
@@ -479,6 +522,13 @@ func unmarshalInt8(b []byte, typeDesc TypeDesc, value *int8) error {
*value = int8(b[7])
return nil
+ case Int32Type:
+ if len(b) != 4 {
+ return ErrorCassandraTypeSerializationUnmarshaling
+ }
+ *value = int8(b[3])
+ return nil
+
case BytesType:
if len(b) != 1 {
return ErrorCassandraTypeSerializationUnmarshaling
@@ -522,7 +572,7 @@ func unmarshalString(b []byte, typeDesc TypeDesc, value *string) error {
func unmarshalUUID(b []byte, typeDesc TypeDesc, value *UUID) error {
switch typeDesc {
- case BytesType, UUIDType:
+ case BytesType, UUIDType, TimeUUIDType, LexicalUUIDType:
if len(b) != 16 {
return ErrorCassandraTypeSerializationUnmarshaling
}
@@ -571,6 +621,17 @@ func unmarshalFloat64(b []byte, typeDesc TypeDesc, value *float64) error {
type TypeClass struct {
Desc TypeDesc
Components []TypeClass
+ Reversed bool
+}
+
+func extractReversed(cassType string) (string, bool) {
+ reversed := false
+ if strings.HasPrefix(cassType, "org.apache.cassandra.db.marshal.ReversedType(") {
+ // extract the inner type
+ cassType = cassType[strings.Index(cassType, "(")+1 : len(cassType)-1]
+ reversed = true
+ }
+ return cassType, reversed
}
func parseTypeDesc(cassType string) TypeDesc {
@@ -583,12 +644,18 @@ func parseTypeDesc(cassType string) TypeDesc {
return UTF8Type
case "LongType", "org.apache.cassandra.db.marshal.LongType":
return LongType
+ case "Int32Type", "org.apache.cassandra.db.marshal.Int32Type":
+ return Int32Type
case "IntegerType", "org.apache.cassandra.db.marshal.IntegerType":
return IntegerType
case "DecimalType", "org.apache.cassandra.db.marshal.DecimalType":
return DecimalType
case "UUIDType", "org.apache.cassandra.db.marshal.UUIDType":
return UUIDType
+ case "TimeUUIDType", "org.apache.cassandra.db.marshal.TimeUUIDType":
+ return TimeUUIDType
+ case "LexicalUUIDType", "org.apache.cassandra.db.marshal.LexicalUUIDType":
+ return LexicalUUIDType
case "BooleanType", "org.apache.cassandra.db.marshal.BooleanType":
return BooleanType
case "FloatType", "org.apache.cassandra.db.marshal.FloatType":
@@ -604,7 +671,8 @@ func parseTypeDesc(cassType string) TypeDesc {
}
func parseTypeClass(cassType string) TypeClass {
- r := TypeClass{Desc: BytesType}
+ cassType, reversed := extractReversed(cassType)
+ r := TypeClass{Reversed: reversed}
// check for composite and parse it
if strings.HasPrefix(cassType, "org.apache.cassandra.db.marshal.CompositeType(") {
@@ -625,7 +693,6 @@ func parseTypeClass(cassType string) TypeClass {
}
const (
- _ = iota
eocEquals byte = 0
eocGreater byte = 1
eocLower byte = 0xff
View
44 src/gossie/types_test.go
@@ -3,8 +3,14 @@ package gossie
import (
"reflect"
"testing"
+ "time"
)
+/*
+ to do:
+ Int32Type tests - they must handle lossy comparison for time.Time marshalling
+*/
+
func checkMarshal(t *testing.T, value interface{}, good []byte, typeDesc TypeDesc) {
b, err := Marshal(value, typeDesc)
if err != nil {
@@ -303,19 +309,6 @@ func TestMarshalUUID(t *testing.T) {
errorMarshal(t, v, FloatType)
errorMarshal(t, v, DoubleType)
errorMarshal(t, v, DateType)
-
- // test utility functions
-
- s := "00112233-4455-6677-8899-aabbccddeeff"
- v2, err := NewUUID(s)
- if err != nil {
- t.Error("Unexpected error in NewUUID")
- }
- checkFullMarshal(t, b, BytesType, &v2, &r)
-
- if v2.String() != s {
- t.Error("Wrong UUID to string conversion ", v2.String())
- }
}
func TestMarshalFloat(t *testing.T) {
@@ -356,3 +349,28 @@ func TestMarshalFloat(t *testing.T) {
errorMarshal(t, v64, FloatType)
errorMarshal(t, v64, DateType)
}
+
+func TestMarshalTime(t *testing.T) {
+ var b []byte
+ var v time.Time = time.Unix(1e9, 2e8)
+ var r time.Time
+
+ b = []byte{0x00, 0x00, 0x00, 0xE8, 0xD4, 0xA5, 0x10, 0xC8}
+ checkFullMarshal(t, b, BytesType, &v, &r)
+ checkFullMarshal(t, b, LongType, &v, &r)
+ checkFullMarshal(t, b, DateType, &v, &r)
+
+ v = time.Unix(-1e9, -2e8)
+ b = []byte{0xFF, 0xFF, 0xFF, 0x17, 0x2B, 0x5A, 0xEF, 0x38}
+ checkFullMarshal(t, b, BytesType, &v, &r)
+ checkFullMarshal(t, b, LongType, &v, &r)
+ checkFullMarshal(t, b, DateType, &v, &r)
+
+ errorMarshal(t, v, UUIDType)
+ errorMarshal(t, v, AsciiType)
+ errorMarshal(t, v, UTF8Type)
+ errorMarshal(t, v, IntegerType)
+ errorMarshal(t, v, DecimalType)
+ errorMarshal(t, v, BooleanType)
+ errorMarshal(t, v, DoubleType)
+}
View
116 src/gossie/uuid.go
@@ -0,0 +1,116 @@
+package gossie
+
+import (
+ "crypto/rand"
+ "fmt"
+ "io"
+ "strconv"
+ "strings"
+ "time"
+)
+
+/*
+ to do:
+ check correctness of NewTimeUUID
+ comparison
+ comp func
+ NewTimeUUIDMax and NewTimeUUIDMin for building slice comps
+*/
+
+type UUID [16]byte
+
+var ZeroUUID UUID = [16]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
+var LowestTimeUUID UUID = [16]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80}
+var HighestTimeUUID UUID = [16]byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0xff, 0xbf, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f}
+
+func (value UUID) String() string {
+ var r []string
+ var s int
+ for _, size := range [5]int{4, 2, 2, 2, 6} {
+ var v int64
+ for i := 0; i < size; i++ {
+ v = v << 8
+ v = v | int64(value[s+i])
+ }
+ r = append(r, fmt.Sprintf("%0*x", size*2, v))
+ s += size
+ }
+ return strings.Join(r, "-")
+}
+
+func ParseUUID(value string) (UUID, error) {
+ var r []byte
+ var ru UUID
+
+ if len(value) != 36 {
+ return ZeroUUID, ErrorUnsupportedMarshaling
+ }
+ ints := strings.Split(value, "-")
+ if len(ints) != 5 {
+ return ZeroUUID, ErrorUnsupportedMarshaling
+ }
+
+ for i, size := range [5]int{4, 2, 2, 2, 6} {
+ t, err := strconv.ParseInt(ints[i], 16, 64)
+ if err != nil {
+ return ZeroUUID, ErrorUnsupportedMarshaling
+ }
+ b, _ := marshalInt(t, size, BytesType)
+ r = append(r, b...)
+ }
+
+ unmarshalUUID(r, BytesType, &ru)
+ return ru, nil
+}
+
+func randomBase() ([]byte, error) {
+ r := make([]byte, 16)
+ _, err := io.ReadFull(rand.Reader, r)
+ if err != nil {
+ return nil, err
+ }
+ return r, nil
+}
+
+func NewRandomUUID() (UUID, error) {
+ var ru UUID
+
+ r, err := randomBase()
+ if err != nil {
+ return ZeroUUID, err
+ }
+ r[6] = (r[6] & 0x0F) | 0x40
+ r[8] = (r[8] &^ 0x40) | 0x80
+
+ unmarshalUUID(r, BytesType, &ru)
+ return ru, nil
+}
+
+// http://johannburkard.de/software/uuid/
+
+func NewTimeUUID(t time.Time) (UUID, error) {
+ var ru UUID
+
+ r, err := randomBase()
+ if err != nil {
+ return ZeroUUID, err
+ }
+
+ var hundredNSBlock int64 = (t.UnixNano() / 100) + 0x01B21DD213814000
+
+ stamp := hundredNSBlock << 32
+ stamp = stamp | ((hundredNSBlock & 0xFFFF00000000) >> 16)
+ stamp = stamp | (0x1000 | ((hundredNSBlock >> 48) & 0x0FFF))
+
+ r[0] = byte(stamp >> 56)
+ r[1] = byte((stamp >> 48) & 0xff)
+ r[2] = byte((stamp >> 40) & 0xff)
+ r[3] = byte((stamp >> 32) & 0xff)
+ r[4] = byte((stamp >> 24) & 0xff)
+ r[5] = byte((stamp >> 16) & 0xff)
+ r[6] = byte((stamp >> 8) & 0xff)
+ r[7] = byte(stamp & 0xff)
+
+ unmarshalUUID(r, BytesType, &ru)
+ return ru, nil
+}
View
27 src/gossie/uuid_test.go
@@ -0,0 +1,27 @@
+package gossie
+
+import (
+ "testing"
+)
+
+/*
+ to do: test New*
+*/
+
+func TestUUID(t *testing.T) {
+ var b []byte
+ var r UUID
+
+ b = []byte{0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff}
+
+ s := "00112233-4455-6677-8899-aabbccddeeff"
+ v, err := ParseUUID(s)
+ if err != nil {
+ t.Error("Unexpected error in NewUUID")
+ }
+ checkFullMarshal(t, b, BytesType, &v, &r)
+
+ if v.String() != s {
+ t.Error("Wrong UUID to string conversion ", v.String())
+ }
+}

0 comments on commit c54beaa

Please sign in to comment.
Something went wrong with that request. Please try again.