github.com/janelia-flyem/dvid@v1.0.0/datatype/annotation/keys.go (about) 1 /* 2 This file supports keyspaces for point annotation data type. 3 */ 4 5 package annotation 6 7 import ( 8 "encoding/binary" 9 "fmt" 10 11 "github.com/janelia-flyem/dvid/datastore" 12 "github.com/janelia-flyem/dvid/dvid" 13 "github.com/janelia-flyem/dvid/storage" 14 ) 15 16 const ( 17 // keyUnknown should never be used and is a check for corrupt or incorrectly set keys 18 keyUnknown storage.TKeyClass = iota 19 20 // reserved type-specific key for metadata 21 keyProperties = datastore.PropertyTKeyClass 22 23 // key is tag id. value is serialization of the tag name and all synaptic elements it contains. 24 keyTag = 70 25 26 // key is label. value is serialization of all synaptic elements associated with a label. 27 keyLabel = 71 28 29 // key is block coordinate. value is serialization of synaptic elements. 30 keyBlock = 72 31 ) 32 33 // DescribeTKeyClass returns a string explanation of what a particular TKeyClass 34 // is used for. Implements the datastore.TKeyClassDescriber interface. 35 func (d *Data) DescribeTKeyClass(tkc storage.TKeyClass) string { 36 switch tkc { 37 case keyTag: 38 return "annotation tag key" 39 case keyLabel: 40 return "annotation label key" 41 case keyBlock: 42 return "annotation block coord key" 43 default: 44 } 45 return "unknown annotation key" 46 } 47 48 // NewTagTKey returns a TKey for a given tag. 49 func NewTagTKey(tag Tag) (storage.TKey, error) { 50 if len(tag) == 0 { 51 return nil, fmt.Errorf("empty tag not permitted") 52 } 53 return storage.NewTKey(keyTag, append([]byte(tag), 0)), nil 54 } 55 56 // DecodeTagTKey returns the Tag corresponding to this type-specific key. 57 func DecodeTagTKey(tk storage.TKey) (Tag, error) { 58 ibytes, err := tk.ClassBytes(keyTag) 59 if err != nil { 60 return "", err 61 } 62 sz := len(ibytes) - 1 63 if sz <= 0 { 64 return "", fmt.Errorf("empty tag") 65 } 66 if ibytes[sz] != 0 { 67 return "", fmt.Errorf("expected 0 byte ending tag key, got %d", ibytes[sz]) 68 } 69 return Tag(ibytes[:sz]), nil 70 } 71 72 func NewLabelTKey(label uint64) storage.TKey { 73 buf := make([]byte, 8) 74 binary.BigEndian.PutUint64(buf, label) 75 return storage.NewTKey(keyLabel, buf) 76 } 77 78 func DecodeLabelTKey(tk storage.TKey) (label uint64, err error) { 79 ibytes, err := tk.ClassBytes(keyLabel) 80 if err != nil { 81 return 82 } 83 label = binary.BigEndian.Uint64(ibytes[0:8]) 84 return 85 } 86 87 func BlockTKeyRange() (min, max storage.TKey) { 88 return NewBlockTKey(dvid.MinChunkPoint3d), NewBlockTKey(dvid.MaxChunkPoint3d) 89 } 90 91 func BlockTKeyZRange(begBlockCoord, endBlockCoord dvid.ChunkPoint3d) (min, max storage.TKey) { 92 begTKey := NewBlockTKey(dvid.ChunkPoint3d{dvid.MinChunkPoint3d[0], dvid.MinChunkPoint3d[1], begBlockCoord[2]}) 93 endTKey := NewBlockTKey(dvid.ChunkPoint3d{dvid.MaxChunkPoint3d[0], dvid.MaxChunkPoint3d[1], endBlockCoord[2]}) 94 return begTKey, endTKey 95 } 96 97 func NewBlockTKey(pt dvid.ChunkPoint3d) storage.TKey { 98 idx := dvid.IndexZYX(pt) 99 return storage.NewTKey(keyBlock, idx.Bytes()) 100 } 101 102 func DecodeBlockTKey(tk storage.TKey) (pt dvid.ChunkPoint3d, err error) { 103 ibytes, err := tk.ClassBytes(keyBlock) 104 if err != nil { 105 return 106 } 107 var idx dvid.IndexZYX 108 if err = idx.IndexFromBytes(ibytes); err != nil { 109 return 110 } 111 pt = dvid.ChunkPoint3d(idx) 112 return 113 }