github.com/machinefi/w3bstream@v1.6.5-rc9.0.20240426031326-b8c7c4876e72/pkg/depends/kit/httptransport/transformer/tsfm_super.go (about) 1 package transformer 2 3 import ( 4 "context" 5 "io" 6 "reflect" 7 8 pkgerr "github.com/pkg/errors" 9 10 vldterr "github.com/machinefi/w3bstream/pkg/depends/kit/validator/errors" 11 "github.com/machinefi/w3bstream/pkg/depends/x/reflectx" 12 ) 13 14 func NewSuper(tsfm Transformer, opt *CommonOption) *Super { 15 return &Super{ 16 tsfm: tsfm, 17 CommonOption: *opt, 18 } 19 } 20 21 type Super struct { 22 tsfm Transformer 23 CommonOption 24 } 25 26 func (t *Super) EncodeTo(ctx context.Context, w io.Writer, v interface{}) error { 27 rv, ok := v.(reflect.Value) 28 if !ok { 29 rv = reflect.ValueOf(v) 30 } 31 32 if t.Explode { 33 rv = reflectx.Indirect(rv) 34 // for create slice 35 if setter, ok := w.(interface{ SetN(n int) }); ok { 36 setter.SetN(rv.Len()) 37 } 38 39 if next, ok := w.(CanNextWriter); ok { 40 errs := vldterr.NewErrorSet() 41 for i := 0; i < rv.Len(); i++ { 42 nw := next.NextWriter() 43 if err := t.tsfm.EncodeTo(ctx, nw, rv.Index(i)); err != nil { 44 errs.AddErr(err, i) 45 } 46 } 47 return errs.Err() 48 } 49 return nil 50 } 51 52 // should skip empty value when omitempty 53 if !(t.Omitempty && reflectx.IsEmptyValue(rv)) { 54 writer, ok := w.(CanNextWriter) 55 if ok { 56 return t.tsfm.EncodeTo(ctx, writer.NextWriter(), rv) 57 } 58 return t.tsfm.EncodeTo(ctx, w, rv) 59 } 60 61 return nil 62 } 63 64 func (t *Super) DecodeFrom(ctx context.Context, r io.Reader, v interface{}) error { 65 if rv, ok := v.(reflect.Value); ok { 66 v = rv.Interface() 67 } 68 69 if reflect.TypeOf(v).Kind() != reflect.Ptr { 70 return pkgerr.Errorf("decode target must be ptr value") 71 } 72 73 if t.Explode { 74 valc := 0 75 if with, ok := r.(interface{ Len() int }); ok { 76 valc = with.Len() 77 } 78 if valc == 0 { 79 return nil 80 } 81 if x, ok := v.(*[]string); ok { 82 if with, ok := r.(CanInterface); ok { 83 if values, ok := with.Interface().([]string); ok { 84 *x = values 85 return nil 86 } 87 } 88 } 89 90 rv := reflectx.Indirect(reflect.ValueOf(v)) 91 92 // make slice (ignore array) 93 if rv.Kind() == reflect.Slice { 94 rv.Set(reflect.MakeSlice(rv.Type(), valc, valc)) 95 } 96 97 reader, ok := r.(CanNextReader) 98 if !ok { 99 return nil 100 } 101 102 errs := vldterr.NewErrorSet() 103 // ignore when values length greater than array len 104 for i := 0; i < rv.Len() && i < valc; i++ { 105 if err := t.tsfm.DecodeFrom( 106 ctx, 107 reader.NextReader(), 108 rv.Index(i).Addr(), 109 ); err != nil { 110 errs.AddErr(err, i) 111 } 112 } 113 return errs.Err() 114 } 115 116 reader, ok := r.(CanNextReader) 117 if ok { 118 return t.tsfm.DecodeFrom(ctx, reader.NextReader(), v) 119 } 120 return t.tsfm.DecodeFrom(ctx, r, v) 121 } 122 123 type CanNextWriter interface { 124 NextWriter() io.Writer 125 } 126 127 type CanNextReader interface { 128 NextReader() io.Reader 129 }