github.com/storacha/go-ucanto@v0.7.2/core/schema/or.go (about) 1 package schema 2 3 import ( 4 "errors" 5 "fmt" 6 "strings" 7 8 "github.com/storacha/go-ucanto/core/result/failure" 9 ) 10 11 type unionError struct { 12 failures []failure.Failure 13 } 14 15 func (ue unionError) Unwrap() []error { 16 errors := make([]error, 0, len(ue.failures)) 17 for _, failure := range ue.failures { 18 errors = append(errors, failure) 19 } 20 return errors 21 } 22 23 func indent(message string) string { 24 indent := " " 25 return indent + strings.Join(strings.Split(message, "\n"), "\n"+indent) 26 } 27 28 func li(message string) string { 29 return indent("- " + message) 30 } 31 32 func (ue unionError) Error() string { 33 return fmt.Sprintf("Value does not match any type of the union:\n%s", li(errors.Join(ue.Unwrap()...).Error())) 34 } 35 36 func (ue unionError) Name() string { 37 return "Union Error" 38 } 39 40 type orReader[I, O any] struct { 41 readers []Reader[I, O] 42 } 43 44 func (or orReader[I, O]) Read(input I) (O, failure.Failure) { 45 failures := make([]failure.Failure, 0, len(or.readers)) 46 for _, reader := range or.readers { 47 o, err := reader.Read(input) 48 if err != nil { 49 failures = append(failures, err) 50 } else { 51 return o, nil 52 } 53 } 54 var o O 55 return o, failure.FromError(unionError{failures: failures}) 56 } 57 58 func Or[I, O any](readers ...Reader[I, O]) Reader[I, O] { 59 return orReader[I, O]{readers} 60 }