github.com/machinefi/w3bstream@v1.6.5-rc9.0.20240426031326-b8c7c4876e72/pkg/depends/conf/section_config/section_config_encoder.go (about) 1 package section_config 2 3 import ( 4 "bytes" 5 "go/ast" 6 "os" 7 "reflect" 8 9 "github.com/machinefi/w3bstream/pkg/depends/base/types" 10 "github.com/machinefi/w3bstream/pkg/depends/x/reflectx" 11 "github.com/machinefi/w3bstream/pkg/depends/x/textx" 12 ) 13 14 type Encoder struct { 15 Sep byte 16 Values map[string]string 17 } 18 19 func NewEncoder(sep byte) *Encoder { return &Encoder{Sep: sep} } 20 21 func (e *Encoder) Marshal(c SectionConfig) ([]byte, error) { 22 rv := reflectx.Indirect(reflect.ValueOf(c)) 23 24 if rv.Kind() != reflect.Struct { 25 panic("input value should be a struct") 26 } 27 28 buf := bytes.NewBuffer(nil) 29 buf.WriteString(c.GetSection().String()) 30 buf.WriteRune('\n') 31 32 if err := e.scan(rv, buf); err != nil { 33 return nil, err 34 } 35 return buf.Bytes(), nil 36 } 37 38 func (e *Encoder) MarshalToFile(c SectionConfig, path string) error { 39 data, err := e.Marshal(c) 40 if err != nil { 41 return err 42 } 43 return os.WriteFile(path, data, os.ModePerm) 44 } 45 46 func (e *Encoder) scan(rv reflect.Value, buf *bytes.Buffer) error { 47 kind := rv.Kind() 48 49 switch kind { 50 case reflect.Ptr: 51 if rv.IsNil() { 52 return nil 53 } 54 return e.scan(rv.Elem(), buf) 55 case reflect.Struct: 56 rt := rv.Type() 57 for i := 0; i < rv.NumField(); i++ { 58 ft, fv := rt.Field(i), rv.Field(i) 59 if !ast.IsExported(ft.Name) { 60 continue 61 } 62 if ft.Anonymous { 63 if err := e.scan(fv, buf); err != nil { 64 return err 65 } 66 } 67 tag, ok := ft.Tag.Lookup("name") 68 if !ok { 69 continue 70 } 71 key, _ := reflectx.TagValueAndFlags(tag) 72 var ( 73 val []byte 74 err error 75 ) 76 if v, ok := fv.Interface().(types.TextMarshaler); ok { 77 val, err = v.MarshalText() 78 } else { 79 val, err = textx.MarshalText(fv.Interface()) 80 } 81 if err != nil { 82 return err 83 } 84 buf.Write([]byte(key)) 85 buf.WriteByte(e.Sep) 86 buf.Write(val) 87 buf.WriteByte('\n') 88 } 89 default: 90 // skip 91 } 92 return nil 93 }