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  }