github.com/nevalang/neva@v0.23.1-0.20240507185603-7696a9bb8dda/internal/runtime/funcs/match.go (about) 1 package funcs 2 3 import ( 4 "context" 5 "errors" 6 7 "github.com/nevalang/neva/internal/runtime" 8 ) 9 10 type match struct{} 11 12 func (match) Create(io runtime.FuncIO, _ runtime.Msg) (func(ctx context.Context), error) { 13 dataIn, err := io.In.Port("data") 14 if err != nil { 15 return nil, err 16 } 17 18 caseIn, ok := io.In["case"] 19 if !ok { 20 return nil, errors.New("inport 'case' is required") 21 } 22 23 caseOut, ok := io.Out["case"] 24 if !ok { 25 return nil, errors.New("outport 'case' is required") 26 } 27 28 elseOut, err := io.Out.Port("else") 29 if err != nil { 30 return nil, err 31 } 32 33 if len(caseIn) != len(caseOut) { 34 return nil, errors.New("number of 'case' inports must match number of 'then' outports") 35 } 36 37 return func(ctx context.Context) { 38 var data runtime.Msg 39 40 for { 41 select { 42 case <-ctx.Done(): 43 return 44 case data = <-dataIn: 45 } 46 47 cases := make([]runtime.Msg, len(caseIn)) 48 for i, slot := range caseIn { 49 select { 50 case <-ctx.Done(): 51 return 52 case caseMsg := <-slot: 53 cases[i] = caseMsg 54 } 55 } 56 57 matchIdx := -1 58 for i, caseMsg := range cases { 59 if data == caseMsg { 60 matchIdx = i 61 break 62 } 63 } 64 65 if matchIdx != -1 { 66 select { 67 case <-ctx.Done(): 68 return 69 case caseOut[matchIdx] <- data: 70 continue 71 } 72 } 73 74 select { 75 case <-ctx.Done(): 76 return 77 case elseOut <- data: 78 } 79 } 80 }, nil 81 }