@@ -7,11 +7,14 @@ import (
77 "errors"
88 "fmt"
99 "io"
10+ "slices"
1011
1112 "github.com/alanshaw/ucantone/ucan"
1213 "github.com/alanshaw/ucantone/ucan/container/datamodel"
14+ "github.com/alanshaw/ucantone/ucan/delegation"
1315 "github.com/alanshaw/ucantone/ucan/invocation"
1416 "github.com/ipfs/go-cid"
17+ "github.com/multiformats/go-multihash"
1518)
1619
1720const (
@@ -46,21 +49,36 @@ func FormatCodec(codec byte) string {
4649}
4750
4851type Container struct {
52+ model * datamodel.ContainerModel
4953 invs []ucan.Invocation
5054 rcpts []ucan.Receipt
5155 dlgs []ucan.Delegation
5256}
5357
54- func (c * Container ) Invocations () []ucan.Invocation {
55- return c .invs
56- }
57-
5858func (c * Container ) Delegations () []ucan.Delegation {
5959 return c .dlgs
6060}
6161
6262func (c * Container ) Delegation (root cid.Cid ) (ucan.Delegation , error ) {
63- panic ("not implemented" )
63+ for _ , b := range c .model .Ctn1 {
64+ digest , err := multihash .Sum (b , multihash .SHA2_256 , - 1 )
65+ if err != nil {
66+ return nil , err
67+ }
68+ if bytes .Equal (root .Hash (), digest ) {
69+ return delegation .Decode (b )
70+ }
71+ }
72+ return nil , ErrNotFound
73+ }
74+
75+ func (c * Container ) Invocations () []ucan.Invocation {
76+ return c .invs
77+ }
78+
79+ // The datamodel this container is built from.
80+ func (c * Container ) Model () * datamodel.ContainerModel {
81+ return c .model
6482}
6583
6684func (c * Container ) Receipts () []ucan.Receipt {
@@ -98,13 +116,38 @@ func WithReceipts(receipts ...ucan.Receipt) Option {
98116 }
99117}
100118
101- // TODO: create and store model on container and add accessor (`Model()`)
102- func New (options ... Option ) * Container {
119+ func New (options ... Option ) (* Container , error ) {
103120 ct := Container {}
104121 for _ , opt := range options {
105122 opt (& ct )
106123 }
107- return & ct
124+
125+ var tokens [][]byte
126+ for _ , inv := range ct .invs {
127+ b , err := invocation .Encode (inv )
128+ if err != nil {
129+ return nil , fmt .Errorf ("encoding invocation: %w" , err )
130+ }
131+ tokens = append (tokens , b )
132+ }
133+ for _ , dlg := range ct .dlgs {
134+ b , err := delegation .Encode (dlg )
135+ if err != nil {
136+ return nil , fmt .Errorf ("encoding delegation: %w" , err )
137+ }
138+ tokens = append (tokens , b )
139+ }
140+ slices .SortFunc (tokens , bytes .Compare )
141+
142+ model := datamodel.ContainerModel {Ctn1 : tokens }
143+ var buf bytes.Buffer
144+ err := model .MarshalCBOR (& buf )
145+ if err != nil {
146+ return nil , fmt .Errorf ("marshaling container to CBOR: %w" , err )
147+ }
148+ ct .model = & model
149+
150+ return & ct , nil
108151}
109152
110153func Encode (codec byte , container ucan.Container ) ([]byte , error ) {
@@ -116,20 +159,22 @@ func Encode(codec byte, container ucan.Container) ([]byte, error) {
116159 }
117160 tokens = append (tokens , b )
118161 }
119- // for _, dlg := range container.Delegations() {
120- // b, err := delegation.Encode(dlg)
121- // if err != nil {
122- // return nil, fmt.Errorf("encoding delegation: %w", err)
123- // }
124- // tokens = append(tokens, b)
125- // }
162+ for _ , dlg := range container .Delegations () {
163+ b , err := delegation .Encode (dlg )
164+ if err != nil {
165+ return nil , fmt .Errorf ("encoding delegation: %w" , err )
166+ }
167+ tokens = append (tokens , b )
168+ }
126169 // for _, rcpt := range container.Receipts() {
127170 // b, err := receipt.Encode(rcpt)
128171 // if err != nil {
129172 // return nil, fmt.Errorf("encoding receipt: %w", err)
130173 // }
131174 // tokens = append(tokens, b)
132175 // }
176+ slices .SortFunc (tokens , bytes .Compare )
177+
133178 model := datamodel.ContainerModel {Ctn1 : tokens }
134179 var buf bytes.Buffer
135180 err := model .MarshalCBOR (& buf )
@@ -213,10 +258,14 @@ func Decode(input []byte) (*Container, error) {
213258 return nil , fmt .Errorf ("unmarshalling container from CBOR: %w" , err )
214259 }
215260
261+ var dlgs []ucan.Delegation
216262 var invs []ucan.Invocation
217263 var rcpts []ucan.Receipt
218- var dlgs []ucan.Delegation
219264 for _ , b := range model .Ctn1 {
265+ if dlg , err := delegation .Decode (b ); err == nil {
266+ dlgs = append (dlgs , dlg )
267+ continue
268+ }
220269 if inv , err := invocation .Decode (b ); err == nil {
221270 invs = append (invs , inv )
222271 continue
@@ -226,11 +275,12 @@ func Decode(input []byte) (*Container, error) {
226275 // rcpts = append(rcpts, rcpt)
227276 // continue
228277 // }
229- // if dlg, err := delegation.Decode(b); err != nil {
230- // dlgs = append(dlgs, dlg)
231- // continue
232- // }
233278 }
234279
235- return New (WithInvocations (invs ... ), WithDelegations (dlgs ... ), WithReceipts (rcpts ... )), nil
280+ return & Container {
281+ model : model ,
282+ invs : invs ,
283+ dlgs : dlgs ,
284+ rcpts : rcpts ,
285+ }, nil
236286}
0 commit comments