Skip to content

Commit f7106b0

Browse files
api: implement namer
Closes TNTP-4190
1 parent c36b4a8 commit f7106b0

File tree

9 files changed

+348
-48
lines changed

9 files changed

+348
-48
lines changed

hasher/hasher_test.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -61,9 +61,9 @@ func TestSHA256Hasher(t *testing.T) {
6161
t.Parallel()
6262

6363
tests := []struct {
64-
name string
65-
in []byte
66-
out string
64+
name string
65+
in []byte
66+
expected string
6767
}{
6868
{"empty", []byte(""), "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"},
6969
{"abc", []byte("abc"), "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"},
@@ -77,7 +77,7 @@ func TestSHA256Hasher(t *testing.T) {
7777

7878
result, _ := h.Hash(test.in)
7979

80-
assert.Equal(t, test.out, hex.EncodeToString(result))
80+
assert.Equal(t, test.expected, hex.EncodeToString(result))
8181
})
8282
}
8383
}

kv/kv.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ type KeyValue struct {
99
Key []byte
1010
// Value is the serialized representation of the value.
1111
Value []byte
12-
1312
// ModRevision is the revision number of the last modification to this key.
1413
ModRevision int64
1514
}

marshaller/marshaller.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,24 +17,24 @@ var ErrUnmarshall = errors.New("failed to unmarshal")
1717
// implements one time for all objects.
1818
// Required for `integrity.Storage` to set marshalling format for any type object
1919
// and as recommendation for developers of `Storage` wrappers.
20-
type DefaultMarshaller interface {
20+
type DefaultMarshaller interface { //nolint:iface
2121
Marshal(data any) ([]byte, error)
2222
Unmarshal(data []byte, out any) error
2323
}
2424

2525
// Marshallable - custom object serialization, implements for each object.
2626
// Required for `integrity.Storage` type to set marshalling format to specific object
2727
// and as recommendation for developers of `Storage` wrappers.
28-
type Marshallable interface {
29-
Marshal() ([]byte, error)
28+
type Marshallable interface { //nolint:iface
29+
Marshal(data any) ([]byte, error)
3030
Unmarshal(data []byte, out any) error
3131
}
3232

3333
// YAMLMarshaller struct represent realization.
3434
type YAMLMarshaller struct{}
3535

3636
// NewYamlMarshaller creates new NewYamlMarshaller object.
37-
func NewYamlMarshaller() YAMLMarshaller {
37+
func NewYamlMarshaller() Marshallable {
3838
return YAMLMarshaller{}
3939
}
4040

namer/key.go

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
package namer
2+
3+
// KeyType represents key types.
4+
type KeyType int
5+
6+
const (
7+
// KeyTypeValue represents data type.
8+
KeyTypeValue KeyType = iota + 1
9+
// KeyTypeHash represents hash of the data type.
10+
KeyTypeHash
11+
// KeyTypeSignature represents signature of the data type.
12+
KeyTypeSignature
13+
)
14+
15+
// Key defines the minimal interface required by keys.
16+
type Key interface {
17+
Name() string // Get object name.
18+
Type() KeyType // Get key type.
19+
Property() string // Get metadata (e.g., algorithm version).
20+
Raw() []byte // Get raw data.
21+
Build() string // Reconstruct raw key string.
22+
}
23+
24+
// DefaultKey implements default realization.
25+
type DefaultKey struct {
26+
name string // Object identifier.
27+
keytype KeyType // Type of object (hash/signature/value).
28+
property string // Additional metadata (version/algorithm).
29+
raw []byte // Raw key string.
30+
}
31+
32+
// NewDefaultKey returns new Key object.
33+
func NewDefaultKey(name string, keytype KeyType, property string, raw []byte) DefaultKey {
34+
return DefaultKey{
35+
name: name,
36+
keytype: keytype,
37+
property: property,
38+
raw: raw,
39+
}
40+
}
41+
42+
// Name returns name of the key.
43+
func (k DefaultKey) Name() string {
44+
return k.name
45+
}
46+
47+
// Type returns type of the key.
48+
func (k DefaultKey) Type() KeyType {
49+
return k.keytype
50+
}
51+
52+
// Property returns property of the key.
53+
func (k DefaultKey) Property() string {
54+
return k.property
55+
}
56+
57+
// Raw returns raw of the key.
58+
func (k DefaultKey) Raw() []byte {
59+
return k.raw
60+
}
61+
62+
// Build should reconstruct key from signature and digest or not?
63+
func (k DefaultKey) Build() string {
64+
return string(k.raw)
65+
}
66+
67+
// String returns string representation of the `raw` field.
68+
func (k DefaultKey) String() string {
69+
return string(k.raw)
70+
}

namer/namer.go

Lines changed: 165 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -2,41 +2,180 @@
22
package namer
33

44
import (
5-
"github.com/tarantool/go-storage/kv"
5+
"errors"
6+
"fmt"
7+
"iter"
8+
"strings"
69
)
710

8-
// KeyType represents key types.
9-
type KeyType int
10-
1111
const (
12-
// KeyTypeValue represents data type.
13-
KeyTypeValue KeyType = iota + 1
14-
// KeyTypeHash represents hash of the data type.
15-
KeyTypeHash
16-
// KeyTypeSignature represents signature of the data type.
17-
KeyTypeSignature
12+
hashName = "hash"
13+
signatureName = "sig"
14+
keysPerName = 3
15+
)
16+
17+
var (
18+
// ErrInvalidKey is returned when missing key, hash or signature.
19+
ErrInvalidKey = errors.New("missing key, hash or signature")
20+
// ErrInvalidInput is returned when input data is invalid.
21+
ErrInvalidInput = errors.New("failed to generate: invalid input data")
22+
// ErrInvalidPrefix is returned when prefix didn't match.
23+
ErrInvalidPrefix = errors.New("invalid prefix")
1824
)
1925

20-
// Key implements internal realization.
21-
type Key struct {
22-
Name string // Object identificator.
23-
Type KeyType // Type of the object.
24-
Property string // Additional information (version/algorithm).
26+
// Results represents Namer working result.
27+
type Results struct {
28+
IsSingle bool // True if result contains only one object name.
29+
IsSingleName string // Cached name when isSingle=true.
30+
Result map[string][]Key // Grouped keys: object name -> key list.
2531
}
2632

27-
// Namer represents keys naming strategy.
28-
type Namer interface {
29-
GenerateNames(name string) []string // Object's keys generation.
30-
ParseNames(names []string) []Key // Convert names into keys.
33+
// SelectSingle gets keys for single-name case (if applicable).
34+
func (r *Results) SelectSingle() ([]Key, bool) {
35+
if r.IsSingle {
36+
return r.Result[r.IsSingleName], true
37+
}
38+
39+
return nil, false
40+
}
41+
42+
// Items return iterator over all name->keys groups.
43+
func (r *Results) Items() iter.Seq2[string, []Key] {
44+
return func(yield func(str string, res []Key) bool) {
45+
for i, v := range r.Result {
46+
if !yield(i, v) {
47+
return
48+
}
49+
}
50+
}
51+
}
52+
53+
// Select gets keys for a specific object name.
54+
func (r *Results) Select(name string) ([]Key, bool) {
55+
if i, ok := r.Result[name]; ok {
56+
return i, true
57+
}
58+
59+
return nil, false
3160
}
3261

33-
// Generator generates signer K/V pairs.
34-
// Implementation should use `generic` and will used for strong typing of the solution.
35-
type Generator[T any] interface {
36-
Generate(name string, value T) ([]kv.KeyValue, error)
62+
// Len returns the number of unique object names.
63+
func (r *Results) Len() int {
64+
return len(r.Result)
65+
}
66+
67+
// DefaultNamer represents default namer.
68+
type DefaultNamer struct {
69+
prefix string // Key prefix (e.g., "storage/").
70+
hashNames []string
71+
sigNames []string
72+
}
73+
74+
// NewDefaultNamer returns new DefaultNamer object with hash/signature names configuration.
75+
func NewDefaultNamer(prefix string, hashNames []string, sigNames []string) *DefaultNamer {
76+
prefix = strings.TrimPrefix(prefix, "/")
77+
prefix = strings.TrimSuffix(prefix, "/")
78+
79+
return &DefaultNamer{
80+
prefix: prefix, // "storage/".
81+
hashNames: hashNames, // "sha256".
82+
sigNames: sigNames, // "RSAPSS".
83+
}
84+
}
85+
86+
// GenerateNames all keys for an object name.
87+
func (n *DefaultNamer) GenerateNames(name string) []Key {
88+
name = strings.TrimPrefix(name, "/")
89+
90+
out := make([]Key, 0, len(n.hashNames)+len(n.sigNames)+1)
91+
92+
out = append(out,
93+
NewDefaultKey(
94+
fmt.Sprintf("/%s/%s", n.prefix, name),
95+
KeyTypeValue,
96+
"",
97+
[]byte{},
98+
))
99+
100+
for _, hash := range n.hashNames {
101+
out = append(out,
102+
NewDefaultKey(
103+
fmt.Sprintf("/%s/%s/%s/%s", n.prefix, hashName, hash, name),
104+
KeyTypeHash,
105+
hash,
106+
[]byte{},
107+
),
108+
)
109+
}
110+
111+
for _, sig := range n.sigNames {
112+
out = append(out,
113+
NewDefaultKey(
114+
fmt.Sprintf("/%s/%s/%s/%s", n.prefix, signatureName, sig, name),
115+
KeyTypeSignature,
116+
sig,
117+
[]byte{},
118+
),
119+
)
120+
}
121+
122+
return out
37123
}
38124

39-
// Validator validates and build the object from K/V.
40-
type Validator[T any] interface {
41-
Validate(pairs []kv.KeyValue) (T, error)
125+
// ParseKeys combine multiple raw keys into grouped results.
126+
func (n *DefaultNamer) ParseKeys(names []string) (Results, error) {
127+
var out Results
128+
129+
out.Result = map[string][]Key{}
130+
131+
if len(names) == 0 {
132+
return out, ErrInvalidInput
133+
}
134+
135+
if len(names) == 1 {
136+
out.IsSingle = true
137+
out.IsSingleName = names[0]
138+
}
139+
140+
for _, name := range names {
141+
originName := name
142+
143+
name, found := strings.CutPrefix(name, n.prefix)
144+
if !found {
145+
return out, ErrInvalidInput
146+
}
147+
148+
name = strings.TrimPrefix(name, "/")
149+
name = strings.TrimSuffix(name, "/")
150+
151+
parts := strings.Split(name, "/")
152+
partslen := len(parts)
153+
154+
var keyType KeyType
155+
156+
var keyProp string
157+
158+
switch parts[0] {
159+
case hashName:
160+
keyType = KeyTypeHash
161+
keyProp = parts[1]
162+
case signatureName:
163+
keyType = KeyTypeSignature
164+
keyProp = parts[1]
165+
default:
166+
keyType = KeyTypeValue
167+
keyProp = ""
168+
}
169+
170+
key := NewDefaultKey(
171+
originName,
172+
keyType,
173+
keyProp,
174+
[]byte{},
175+
)
176+
177+
out.Result[parts[partslen-1]] = append(out.Result[parts[partslen-1]], key)
178+
}
179+
180+
return out, nil
42181
}

0 commit comments

Comments
 (0)