Skip to content

Commit

Permalink
WIP - extract
Browse files Browse the repository at this point in the history
  • Loading branch information
AndrewSisley committed Oct 29, 2024
1 parent e8101bf commit 483e8df
Show file tree
Hide file tree
Showing 27 changed files with 1,609 additions and 1,207 deletions.
186 changes: 0 additions & 186 deletions internal/core/encoding.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ import (
"github.com/sourcenetwork/immutable"

"github.com/sourcenetwork/defradb/client"
"github.com/sourcenetwork/defradb/internal/encoding"
)

// NormalizeFieldValue takes a field value and description and converts it to the
Expand Down Expand Up @@ -232,188 +231,3 @@ func convertToJSON(propertyName string, untypedValue any) (any, error) {
return untypedValue, nil
}
}

// DecodeIndexDataStoreKey decodes a IndexDataStoreKey from bytes.
// It expects the input bytes is in the following format:
//
// /[CollectionID]/[IndexID]/[FieldValue](/[FieldValue]...)
//
// Where [CollectionID] and [IndexID] are integers
//
// All values of the fields are converted to standardized Defra Go type
// according to fields description.
func DecodeIndexDataStoreKey(
data []byte,
indexDesc *client.IndexDescription,
fields []client.FieldDefinition,
) (IndexDataStoreKey, error) {
if len(data) == 0 {
return IndexDataStoreKey{}, ErrEmptyKey
}

if data[0] != '/' {
return IndexDataStoreKey{}, ErrInvalidKey
}
data = data[1:]

data, colID, err := encoding.DecodeUvarintAscending(data)
if err != nil {
return IndexDataStoreKey{}, err
}

key := IndexDataStoreKey{CollectionID: uint32(colID)}

if data[0] != '/' {
return IndexDataStoreKey{}, ErrInvalidKey
}
data = data[1:]

data, indID, err := encoding.DecodeUvarintAscending(data)
if err != nil {
return IndexDataStoreKey{}, err
}
key.IndexID = uint32(indID)

if len(data) == 0 {
return key, nil
}

for len(data) > 0 {
if data[0] != '/' {
return IndexDataStoreKey{}, ErrInvalidKey
}
data = data[1:]

i := len(key.Fields)
descending := false
var kind client.FieldKind = client.FieldKind_DocID
// If the key has more values encoded then fields on the index description, the last
// value must be the docID and we treat it as a string.
if i < len(indexDesc.Fields) {
descending = indexDesc.Fields[i].Descending
kind = fields[i].Kind
} else if i > len(indexDesc.Fields) {
return IndexDataStoreKey{}, ErrInvalidKey
}

if kind != nil && kind.IsArray() {
if arrKind, ok := kind.(client.ScalarArrayKind); ok {
kind = arrKind.SubKind()
}
}

var val client.NormalValue
data, val, err = encoding.DecodeFieldValue(data, descending, kind)
if err != nil {
return IndexDataStoreKey{}, err
}

key.Fields = append(key.Fields, IndexedField{Value: val, Descending: descending})
}

return key, nil
}

// EncodeIndexDataStoreKey encodes a IndexDataStoreKey to bytes to be stored as a key
// for secondary indexes.
func EncodeIndexDataStoreKey(key *IndexDataStoreKey) []byte {
if key.CollectionID == 0 {
return []byte{}
}

b := encoding.EncodeUvarintAscending([]byte{'/'}, uint64(key.CollectionID))

if key.IndexID == 0 {
return b
}
b = append(b, '/')
b = encoding.EncodeUvarintAscending(b, uint64(key.IndexID))

for _, field := range key.Fields {
b = append(b, '/')
b = encoding.EncodeFieldValue(b, field.Value, field.Descending)
}

return b
}

// DecodeDataStoreKey decodes a store key into a [DataStoreKey].
func DecodeDataStoreKey(data []byte) (DataStoreKey, error) {
if len(data) == 0 {
return DataStoreKey{}, ErrEmptyKey
}

if data[0] != '/' {
return DataStoreKey{}, ErrInvalidKey
}
data = data[1:]

data, colRootID, err := encoding.DecodeUvarintAscending(data)
if err != nil {
return DataStoreKey{}, err
}

var instanceType InstanceType
if len(data) > 1 {
if data[0] == '/' {
data = data[1:]
}
instanceType = InstanceType(data[0])
data = data[1:]
}

const docKeyLength int = 40
var docID string
if len(data) > docKeyLength {
if data[0] == '/' {
data = data[1:]
}
docID = string(data[:docKeyLength])
data = data[docKeyLength:]
}

var fieldID string
if len(data) > 1 {
if data[0] == '/' {
data = data[1:]
}
// Todo: This should be encoded/decoded properly in
// https://github.com/sourcenetwork/defradb/issues/2818
fieldID = string(data)
}

return DataStoreKey{
CollectionRootID: uint32(colRootID),
InstanceType: (instanceType),
DocID: docID,
FieldID: fieldID,
}, nil
}

// EncodeDataStoreKey encodes a [*DataStoreKey] to a byte array suitable for sorting in the store.
func EncodeDataStoreKey(key *DataStoreKey) []byte {
var result []byte

if key.CollectionRootID != 0 {
result = encoding.EncodeUvarintAscending([]byte{'/'}, uint64(key.CollectionRootID))
}

if key.InstanceType != "" {
result = append(result, '/')
result = append(result, []byte(string(key.InstanceType))...)
}

if key.DocID != "" {
result = append(result, '/')
result = append(result, []byte(key.DocID)...)
}

if key.FieldID != "" {
result = append(result, '/')
// Todo: This should be encoded/decoded properly in
// https://github.com/sourcenetwork/defradb/issues/2818
result = append(result, []byte(key.FieldID)...)
}

return result
}
Loading

0 comments on commit 483e8df

Please sign in to comment.