From 4779da6a0de335edd9c43094e409fd53e4681666 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20Mur=C3=A9?= Date: Wed, 20 Nov 2024 18:27:01 +0100 Subject: [PATCH] meta,args: add missing Include, add iterator to use normal or Readonly the same way --- pkg/args/args.go | 22 +++++++++++++--- pkg/args/readonly.go | 10 +++++++- pkg/meta/meta.go | 46 +++++++++++++++++++++++++++++++++- pkg/meta/readonly.go | 32 +++++++++++++++-------- token/invocation/invocation.go | 2 ++ 5 files changed, 96 insertions(+), 16 deletions(-) diff --git a/pkg/args/args.go b/pkg/args/args.go index d046d93..eddb9cc 100644 --- a/pkg/args/args.go +++ b/pkg/args/args.go @@ -5,6 +5,7 @@ package args import ( "fmt" + "iter" "sort" "strings" @@ -54,21 +55,36 @@ func (a *Args) Add(key string, val any) error { return nil } +type Iterator interface { + Iter() iter.Seq2[string, ipld.Node] +} + // Include merges the provided arguments into the existing arguments. // // If duplicate keys are encountered, the new value is silently dropped // without causing an error. -func (a *Args) Include(other *Args) { - for _, key := range other.Keys { +func (a *Args) Include(other Iterator) { + for key, value := range other.Iter() { if _, ok := a.Values[key]; ok { // don't overwrite continue } - a.Values[key] = other.Values[key] + a.Values[key] = value a.Keys = append(a.Keys, key) } } +// Iter iterates over the args key/values +func (a *Args) Iter() iter.Seq2[string, ipld.Node] { + return func(yield func(string, ipld.Node) bool) { + for _, key := range a.Keys { + if !yield(key, a.Values[key]) { + return + } + } + } +} + // ToIPLD wraps an instance of an Args with an ipld.Node. func (a *Args) ToIPLD() (ipld.Node, error) { sort.Strings(a.Keys) diff --git a/pkg/args/readonly.go b/pkg/args/readonly.go index a708807..29c2a98 100644 --- a/pkg/args/readonly.go +++ b/pkg/args/readonly.go @@ -1,11 +1,19 @@ package args -import "github.com/ipld/go-ipld-prime" +import ( + "iter" + + "github.com/ipld/go-ipld-prime" +) type ReadOnly struct { args *Args } +func (r ReadOnly) Iter() iter.Seq2[string, ipld.Node] { + return r.args.Iter() +} + func (r ReadOnly) ToIPLD() (ipld.Node, error) { return r.args.ToIPLD() } diff --git a/pkg/meta/meta.go b/pkg/meta/meta.go index 913530f..8590645 100644 --- a/pkg/meta/meta.go +++ b/pkg/meta/meta.go @@ -3,6 +3,7 @@ package meta import ( "errors" "fmt" + "iter" "strings" "github.com/ipld/go-ipld-prime" @@ -171,6 +172,36 @@ func (m *Meta) AddEncrypted(key string, val any, encryptionKey []byte) error { return m.Add(key, encrypted) } +type Iterator interface { + Iter() iter.Seq2[string, ipld.Node] +} + +// Include merges the provided meta into the existing one. +// +// If duplicate keys are encountered, the new value is silently dropped +// without causing an error. +func (m *Meta) Include(other Iterator) { + for key, value := range other.Iter() { + if _, ok := m.Values[key]; ok { + // don't overwrite + continue + } + m.Values[key] = value + m.Keys = append(m.Keys, key) + } +} + +// Iter iterates over the meta key/values +func (m *Meta) Iter() iter.Seq2[string, ipld.Node] { + return func(yield func(string, ipld.Node) bool) { + for _, key := range m.Keys { + if !yield(key, m.Values[key]) { + return + } + } + } +} + // Equals tells if two Meta hold the same key/values. func (m *Meta) Equals(other *Meta) bool { if len(m.Keys) != len(other.Keys) { @@ -209,5 +240,18 @@ func (m *Meta) String() string { // ReadOnly returns a read-only version of Meta. func (m *Meta) ReadOnly() ReadOnly { - return ReadOnly{m: m} + return ReadOnly{meta: m} +} + +// Clone makes a deep copy. +func (m *Meta) Clone() *Meta { + res := &Meta{ + Keys: make([]string, len(m.Keys)), + Values: make(map[string]ipld.Node, len(m.Values)), + } + copy(res.Keys, m.Keys) + for k, v := range m.Values { + res.Values[k] = v + } + return res } diff --git a/pkg/meta/readonly.go b/pkg/meta/readonly.go index ce3674e..26d667d 100644 --- a/pkg/meta/readonly.go +++ b/pkg/meta/readonly.go @@ -1,50 +1,60 @@ package meta import ( + "iter" + "github.com/ipld/go-ipld-prime" ) // ReadOnly wraps a Meta into a read-only facade. type ReadOnly struct { - m *Meta + meta *Meta } func (r ReadOnly) GetBool(key string) (bool, error) { - return r.m.GetBool(key) + return r.meta.GetBool(key) } func (r ReadOnly) GetString(key string) (string, error) { - return r.m.GetString(key) + return r.meta.GetString(key) } func (r ReadOnly) GetEncryptedString(key string, encryptionKey []byte) (string, error) { - return r.m.GetEncryptedString(key, encryptionKey) + return r.meta.GetEncryptedString(key, encryptionKey) } func (r ReadOnly) GetInt64(key string) (int64, error) { - return r.m.GetInt64(key) + return r.meta.GetInt64(key) } func (r ReadOnly) GetFloat64(key string) (float64, error) { - return r.m.GetFloat64(key) + return r.meta.GetFloat64(key) } func (r ReadOnly) GetBytes(key string) ([]byte, error) { - return r.m.GetBytes(key) + return r.meta.GetBytes(key) } func (r ReadOnly) GetEncryptedBytes(key string, encryptionKey []byte) ([]byte, error) { - return r.m.GetEncryptedBytes(key, encryptionKey) + return r.meta.GetEncryptedBytes(key, encryptionKey) } func (r ReadOnly) GetNode(key string) (ipld.Node, error) { - return r.m.GetNode(key) + return r.meta.GetNode(key) +} + +func (r ReadOnly) Iter() iter.Seq2[string, ipld.Node] { + return r.meta.Iter() } func (r ReadOnly) Equals(other ReadOnly) bool { - return r.m.Equals(other.m) + return r.meta.Equals(other.meta) } func (r ReadOnly) String() string { - return r.m.String() + return r.meta.String() +} + +func (r ReadOnly) WriteableClone() *Meta { + return r.meta.Clone() } diff --git a/token/invocation/invocation.go b/token/invocation/invocation.go index 12f0a08..ee85a94 100644 --- a/token/invocation/invocation.go +++ b/token/invocation/invocation.go @@ -164,6 +164,8 @@ func (t *Token) Arguments() args.ReadOnly { // Proof() returns the ordered list of cid.Cid which reference the // delegation Tokens that authorize this invocation. +// Ordering is from the leaf Delegation (with aud matching the invocation's iss) +// to the root delegation. func (t *Token) Proof() []cid.Cid { return t.proof }