package ini import ( "bytes" "encoding" "fmt" "reflect" ) var ( marshalerType = reflect.TypeOf(new(Marshaler)).Elem() textMarshalerType = reflect.TypeOf(new(encoding.TextMarshaler)).Elem() ) type Marshaler interface { MarshalINI() ([]byte, error) } type encoder interface { encode() } type encode struct { bytes.Buffer scratch [64]byte /*cache sync.Map TODO */ } func Marshal(v interface{}) ([]byte, error) { fmt.Println("Interface", v) enc := &encode{} if err := enc.marshal(v); err != nil { return nil, err } return enc.Bytes(), nil } func (e *encode) marshal(v interface{}) error { s := "Text" e.reflectValue(reflect.ValueOf(v)) e.reflectValue(reflect.ValueOf(1)) e.reflectValue(reflect.ValueOf(s)) return nil } func (e *encode) reflectValue(v reflect.Value) { fmt.Println("ReflectValue", v) valueEncoder(e, v).encode() } func valueEncoder(e *encode, v reflect.Value) encoder { if !v.IsValid() { return invalidValueEncoder{e, v, v.Type()} } return e.encoder(v) } func (e *encode) encoder(v reflect.Value) encoder { t := v.Type() if t.Implements(marshalerType) { fmt.Println("t.Implements(marshalerType)", t.Implements(marshalerType)) return marshalerEncoder{e, v, t} } if t.Kind() != reflect.Ptr { if reflect.PtrTo(t).Implements(marshalerType) { fmt.Println("Allow marshalType") } } if t.Implements(textMarshalerType) { fmt.Println("t.Implements(textMarshalerType)", t.Implements(textMarshalerType)) return &textMarshalerEncoder{e, v, t} } if t.Kind() != reflect.Ptr { if reflect.PtrTo(t).Implements(textMarshalerType) { fmt.Println("Allow TextmarshalType") } } switch t.Kind() { case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: fmt.Println("INT") case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: fmt.Println("UINT") case reflect.Float32, reflect.Float64: fmt.Println("Float32/64") case reflect.String: fmt.Println("STRING") return &stringEncoder{e, v, t} case reflect.Struct: fmt.Println("STRUCT") return &structEncoder{e, v, t} case reflect.Interface: fmt.Println("Interface") case reflect.Slice, reflect.Array: fmt.Println("Array or slice") default: fmt.Printf("Other kind: %s", t.Kind()) } return &invalidValueEncoder{e, v, t} } type marshalerEncoder struct { e *encode v reflect.Value t reflect.Type } func (m marshalerEncoder) encode() { } type textMarshalerEncoder struct { e *encode v reflect.Value t reflect.Type } func (m textMarshalerEncoder) encode() { } type structEncoder struct { e *encode v reflect.Value t reflect.Type } func (s structEncoder) encode() { //fmt.Println("STRUCT", s.t) fmt.Printf("NAME: %s", s.t) for i := 0; i < s.v.NumField(); i++ { s.e.encoder(s.v.Field(i)).encode() } } type stringEncoder struct { e *encode v reflect.Value t reflect.Type } func (t *stringEncoder) encode() { fmt.Println("STRING ENCODER", t.v, t.t) } type invalidValueEncoder struct { e *encode v reflect.Value t reflect.Type } func (i invalidValueEncoder) encode() { }