github.com/storacha/go-ucanto@v0.7.2/core/schema/struct.go (about) 1 package schema 2 3 import ( 4 "github.com/ipld/go-ipld-prime/node/bindnode" 5 "github.com/ipld/go-ipld-prime/schema" 6 "github.com/storacha/go-ucanto/core/ipld" 7 "github.com/storacha/go-ucanto/core/result/failure" 8 "github.com/ucan-wg/go-ucan/capability/policy" 9 ) 10 11 type strukt[T any] struct { 12 typ schema.Type 13 policy policy.Policy 14 opts []bindnode.Option 15 } 16 17 func (s strukt[T]) Read(input any) (T, failure.Failure) { 18 var bind T 19 node, ok := input.(ipld.Node) 20 if !ok { 21 // If input is not an IPLD node, can it be converted to one? 22 if builder, ok := input.(ipld.Builder); ok { 23 n, err := builder.ToIPLD() 24 if err != nil { 25 return bind, NewSchemaError(err.Error()) 26 } 27 node = n 28 } else { 29 return bind, NewSchemaError("unexpected input: not an IPLD node") 30 } 31 } 32 33 if s.policy != nil { 34 ok := policy.Match(s.policy, node) 35 if !ok { 36 return bind, NewSchemaError("input did not match policy") 37 } 38 } 39 40 bind, err := ipld.Rebind[T](node, s.typ, s.opts...) 41 if err != nil { 42 return bind, NewSchemaError(err.Error()) 43 } 44 45 return bind, nil 46 } 47 48 func Struct[T any](typ schema.Type, policy policy.Policy, opts ...bindnode.Option) Reader[any, T] { 49 return strukt[T]{typ, policy, opts} 50 }