github.com/storacha/go-ucanto@v0.7.2/core/result/failure/datamodel/failure.go (about) 1 package datamodel 2 3 import ( 4 // to use go:embed 5 _ "embed" 6 "fmt" 7 8 "github.com/ipld/go-ipld-prime" 9 "github.com/ipld/go-ipld-prime/schema" 10 ucanipld "github.com/storacha/go-ucanto/core/ipld" 11 ) 12 13 //go:embed failure.ipldsch 14 var failureSchema []byte 15 16 // FailureModel is a generic failure 17 type FailureModel struct { 18 Name *string 19 Message string 20 Stack *string 21 } 22 23 func (f FailureModel) Error() string { 24 return f.Message 25 } 26 27 func (f *FailureModel) ToIPLD() (ipld.Node, error) { 28 return ucanipld.WrapWithRecovery(f, typ) 29 } 30 31 var typ schema.Type 32 33 func init() { 34 ts, err := ipld.LoadSchemaBytes(failureSchema) 35 if err != nil { 36 panic(fmt.Errorf("loading failure schema: %w", err)) 37 } 38 typ = ts.TypeByName("Failure") 39 } 40 41 func FailureType() schema.Type { 42 return typ 43 } 44 45 func Schema() []byte { 46 return failureSchema 47 } 48 49 // Bind binds the IPLD node to a [datamodel.FailureModel]. This works around 50 // IPLD requiring data to match the schema _exactly_. 51 // 52 // Note: the IPLD node is expected to be a map kind, with a "message" key and 53 // optionally a "name" and "stack" (all values strings). If none of these are 54 // true then you get back a nil value [datamodel.FailureModel]. 55 func Bind(n ipld.Node) FailureModel { 56 f := FailureModel{} 57 nn, err := n.LookupByString("name") 58 if err == nil { 59 name, err := nn.AsString() 60 if err == nil { 61 f.Name = &name 62 } 63 } 64 mn, err := n.LookupByString("message") 65 if err == nil { 66 msg, err := mn.AsString() 67 if err == nil { 68 f.Message = msg 69 } 70 } 71 sn, err := n.LookupByString("stack") 72 if err == nil { 73 stack, err := sn.AsString() 74 if err == nil { 75 f.Stack = &stack 76 } 77 } 78 return f 79 }