|  | @@ -0,0 +1,414 @@
 | 
	
		
			
				|  |  | +package ini
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +import (
 | 
	
		
			
				|  |  | +	"encoding"
 | 
	
		
			
				|  |  | +	"fmt"
 | 
	
		
			
				|  |  | +	"reflect"
 | 
	
		
			
				|  |  | +	"strconv"
 | 
	
		
			
				|  |  | +	"strings"
 | 
	
		
			
				|  |  | +)
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +// Types to look for ("Marshaler"/"Unmarshaler" interface)
 | 
	
		
			
				|  |  | +var (
 | 
	
		
			
				|  |  | +	marshalerType       = reflect.TypeOf(new(Marshaler)).Elem()
 | 
	
		
			
				|  |  | +	unmarshalerType     = reflect.TypeOf(new(Unmarshaler)).Elem()
 | 
	
		
			
				|  |  | +	textMarshalerType   = reflect.TypeOf(new(encoding.TextMarshaler)).Elem()
 | 
	
		
			
				|  |  | +	textUnmarshalerType = reflect.TypeOf(new(encoding.TextUnmarshaler)).Elem()
 | 
	
		
			
				|  |  | +)
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +// INIDecoderError is returned on decoding error
 | 
	
		
			
				|  |  | +type INIDecoderError struct {
 | 
	
		
			
				|  |  | +	msg string
 | 
	
		
			
				|  |  | +	err error
 | 
	
		
			
				|  |  | +	f   *field
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +// Error returns an formatted string of the INIDecoderError
 | 
	
		
			
				|  |  | +func (i *INIDecoderError) Error() string {
 | 
	
		
			
				|  |  | +	return fmt.Sprintf(
 | 
	
		
			
				|  |  | +		"INI Decoder Error: %s. %s. Field %s, namespace: %s",
 | 
	
		
			
				|  |  | +		i.msg, i.err.Error(), i.f.t.Name(), i.f.ns,
 | 
	
		
			
				|  |  | +	)
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +// INIEncoderError is returned on encoding error
 | 
	
		
			
				|  |  | +type INIEncoderError struct {
 | 
	
		
			
				|  |  | +	msg string
 | 
	
		
			
				|  |  | +	err error
 | 
	
		
			
				|  |  | +	f   *field
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +// Error returns an formatted string of the INIEncoderError
 | 
	
		
			
				|  |  | +func (i *INIEncoderError) Error() string {
 | 
	
		
			
				|  |  | +	return fmt.Sprintf(
 | 
	
		
			
				|  |  | +		"INI Encoder Error: %s. Field: %s, namespace: %s",
 | 
	
		
			
				|  |  | +		i.msg, i.err.Error(), i.f.t.Name(), i.f.ns,
 | 
	
		
			
				|  |  | +	)
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +// decoder and encoder methods
 | 
	
		
			
				|  |  | +type decodeFn func([]byte) error
 | 
	
		
			
				|  |  | +type encodeFn func() ([]byte, error)
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +type field struct {
 | 
	
		
			
				|  |  | +	ns string
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	t reflect.Type
 | 
	
		
			
				|  |  | +	v reflect.Value
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	p interface{}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	// decoder or encoder method (will be changed when a cache for "elements" is implemented)
 | 
	
		
			
				|  |  | +	fn interface{} // Use setFn to set this!
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +func newField(v reflect.Value, p interface{}, i int) *field {
 | 
	
		
			
				|  |  | +	f := &field{
 | 
	
		
			
				|  |  | +		t: v.Type(),
 | 
	
		
			
				|  |  | +		v: v,
 | 
	
		
			
				|  |  | +		p: nil,
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	if p != nil {
 | 
	
		
			
				|  |  | +		switch p.(type) {
 | 
	
		
			
				|  |  | +		case reflect.Type:
 | 
	
		
			
				|  |  | +			f.p = p.(reflect.Type).Field(i)
 | 
	
		
			
				|  |  | +		case reflect.Value:
 | 
	
		
			
				|  |  | +			f.p = p.(reflect.Value).Type().Field(i)
 | 
	
		
			
				|  |  | +		}
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	return f
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +// implements checks if the field implements the type t, or a pointer method to type t
 | 
	
		
			
				|  |  | +func (f *field) implements(t reflect.Type) bool {
 | 
	
		
			
				|  |  | +	return (f.t.Implements(t) || (f.t.Kind() != reflect.Ptr && reflect.PtrTo(f.t).Implements(t)))
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +// setNS determines the namespace for the field
 | 
	
		
			
				|  |  | +func (f *field) setNS(ns string) string {
 | 
	
		
			
				|  |  | +	if f.p == nil {
 | 
	
		
			
				|  |  | +		f.ns = ns + "." + f.t.Name()
 | 
	
		
			
				|  |  | +		return f.ns
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	if tag := f.p.(reflect.StructField).Tag.Get("ini"); len(tag) != 0 {
 | 
	
		
			
				|  |  | +		f.ns = ns + "." + tag
 | 
	
		
			
				|  |  | +		return f.ns
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	f.ns = ns + "." + f.p.(reflect.StructField).Name
 | 
	
		
			
				|  |  | +	return f.ns
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +// setFN sets the function
 | 
	
		
			
				|  |  | +func (f *field) setFn(fn interface{}) {
 | 
	
		
			
				|  |  | +	f.fn = fn
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +// decode returns the decoder-method (do not call f.fn, for future changes!)
 | 
	
		
			
				|  |  | +func (f *field) decode(b []byte) error {
 | 
	
		
			
				|  |  | +	return f.fn.(decodeFn)(b)
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +// encode returns the decoder-method (do not call f.fn directly, for future changes!)
 | 
	
		
			
				|  |  | +func (f *field) encode() ([]byte, error) {
 | 
	
		
			
				|  |  | +	return f.fn.(encodeFn)()
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +/**
 | 
	
		
			
				|  |  | + DECODER METHODS
 | 
	
		
			
				|  |  | +**/
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +func (f *field) valid() error {
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	if f.v.CanAddr() {
 | 
	
		
			
				|  |  | +		return nil
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	return fmt.Errorf("Field '%s' not addressable", f.ns)
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +func (f *field) uintDecoder(b []byte) error {
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	if err := f.valid(); err != nil {
 | 
	
		
			
				|  |  | +		return &INIDecoderError{
 | 
	
		
			
				|  |  | +			msg: "Unsigned integer decoder",
 | 
	
		
			
				|  |  | +			err: err,
 | 
	
		
			
				|  |  | +			f:   f,
 | 
	
		
			
				|  |  | +		}
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	i, err := strconv.ParseUint(string(b), 10, 64)
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	if err != nil {
 | 
	
		
			
				|  |  | +		return &INIDecoderError{
 | 
	
		
			
				|  |  | +			msg: "Unsigned integer decoder",
 | 
	
		
			
				|  |  | +			err: err,
 | 
	
		
			
				|  |  | +			f:   f,
 | 
	
		
			
				|  |  | +		}
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	f.v.SetUint(i)
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	return nil
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +func (f *field) intDecoder(b []byte) error {
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	if err := f.valid(); err != nil {
 | 
	
		
			
				|  |  | +		return &INIDecoderError{
 | 
	
		
			
				|  |  | +			msg: "Integer decoder",
 | 
	
		
			
				|  |  | +			err: err,
 | 
	
		
			
				|  |  | +			f:   f,
 | 
	
		
			
				|  |  | +		}
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	i, err := strconv.ParseInt(string(b), 10, 64)
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	if err != nil {
 | 
	
		
			
				|  |  | +		return &INIDecoderError{
 | 
	
		
			
				|  |  | +			msg: "Integer decoder",
 | 
	
		
			
				|  |  | +			err: err,
 | 
	
		
			
				|  |  | +			f:   f,
 | 
	
		
			
				|  |  | +		}
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	f.v.SetInt(i)
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	return nil
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +func (f *field) float32Decoder(b []byte) error {
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	if err := f.valid(); err != nil {
 | 
	
		
			
				|  |  | +		return &INIDecoderError{
 | 
	
		
			
				|  |  | +			msg: "Float (32) decoder",
 | 
	
		
			
				|  |  | +			err: err,
 | 
	
		
			
				|  |  | +			f:   f,
 | 
	
		
			
				|  |  | +		}
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	i, err := strconv.ParseFloat(string(b), 32)
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	if err != nil {
 | 
	
		
			
				|  |  | +		return &INIDecoderError{
 | 
	
		
			
				|  |  | +			msg: "Float (32) decoder",
 | 
	
		
			
				|  |  | +			err: err,
 | 
	
		
			
				|  |  | +			f:   f,
 | 
	
		
			
				|  |  | +		}
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	f.v.SetFloat(i)
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	return nil
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +func (f *field) float64Decoder(b []byte) error {
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	if err := f.valid(); err != nil {
 | 
	
		
			
				|  |  | +		return &INIDecoderError{
 | 
	
		
			
				|  |  | +			msg: "Float (64) decoder",
 | 
	
		
			
				|  |  | +			err: err,
 | 
	
		
			
				|  |  | +			f:   f,
 | 
	
		
			
				|  |  | +		}
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	i, err := strconv.ParseFloat(string(b), 64)
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	if err != nil {
 | 
	
		
			
				|  |  | +		return &INIDecoderError{
 | 
	
		
			
				|  |  | +			msg: "Float (64) decoder",
 | 
	
		
			
				|  |  | +			err: err,
 | 
	
		
			
				|  |  | +			f:   f,
 | 
	
		
			
				|  |  | +		}
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	f.v.SetFloat(i)
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	return nil
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +func (f *field) strDecoder(b []byte) error {
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	if err := f.valid(); err != nil {
 | 
	
		
			
				|  |  | +		return &INIDecoderError{
 | 
	
		
			
				|  |  | +			msg: "String decoder",
 | 
	
		
			
				|  |  | +			err: err,
 | 
	
		
			
				|  |  | +			f:   f,
 | 
	
		
			
				|  |  | +		}
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	f.v.SetString(string(b))
 | 
	
		
			
				|  |  | +	return nil
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +func (f *field) boolDecoder(b []byte) error {
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	if err := f.valid(); err != nil {
 | 
	
		
			
				|  |  | +		return &INIDecoderError{
 | 
	
		
			
				|  |  | +			msg: "Boolean decoder",
 | 
	
		
			
				|  |  | +			err: err,
 | 
	
		
			
				|  |  | +			f:   f,
 | 
	
		
			
				|  |  | +		}
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	f.v.SetBool(true)
 | 
	
		
			
				|  |  | +	return nil
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +func (f *field) unmarshalerDecoder(b []byte) error {
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	if err := f.valid(); err != nil {
 | 
	
		
			
				|  |  | +		return &INIDecoderError{
 | 
	
		
			
				|  |  | +			msg: "Unmarshaler decoder",
 | 
	
		
			
				|  |  | +			err: err,
 | 
	
		
			
				|  |  | +			f:   f,
 | 
	
		
			
				|  |  | +		}
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	v := f.v
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	if v.Kind() != reflect.Ptr && v.Type().Name() != "" {
 | 
	
		
			
				|  |  | +		v = v.Addr()
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	if v.IsNil() {
 | 
	
		
			
				|  |  | +		v.Set(reflect.New(v.Type().Elem()))
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	if i, ok := v.Interface().(Unmarshaler); ok {
 | 
	
		
			
				|  |  | +		if err := i.UnmarshalINI(b); err != nil {
 | 
	
		
			
				|  |  | +			return &INIDecoderError{
 | 
	
		
			
				|  |  | +				msg: "UnmarshalINI decoder",
 | 
	
		
			
				|  |  | +				err: err,
 | 
	
		
			
				|  |  | +				f:   f,
 | 
	
		
			
				|  |  | +			}
 | 
	
		
			
				|  |  | +		}
 | 
	
		
			
				|  |  | +		return nil
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	if i, ok := v.Interface().(encoding.TextUnmarshaler); ok {
 | 
	
		
			
				|  |  | +		if err := i.UnmarshalText(b); err != nil {
 | 
	
		
			
				|  |  | +			return &INIDecoderError{
 | 
	
		
			
				|  |  | +				msg: "UnmarshalText decoder",
 | 
	
		
			
				|  |  | +				err: err,
 | 
	
		
			
				|  |  | +				f:   f,
 | 
	
		
			
				|  |  | +			}
 | 
	
		
			
				|  |  | +		}
 | 
	
		
			
				|  |  | +		return nil
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	return fmt.Errorf("Cannot load Unmarshaler")
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +/**
 | 
	
		
			
				|  |  | + ENCODER METHODS
 | 
	
		
			
				|  |  | +**/
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +func (f *field) nskey() string {
 | 
	
		
			
				|  |  | +	return f.ns[strings.LastIndexByte(f.ns, '.')+1:]
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +func (f *field) uintEncoder() ([]byte, error) {
 | 
	
		
			
				|  |  | +	i := strconv.FormatUint(f.v.Uint(), 10)
 | 
	
		
			
				|  |  | +	return []byte(f.nskey() + " = " + i), nil
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +func (f *field) intEncoder() ([]byte, error) {
 | 
	
		
			
				|  |  | +	i := strconv.FormatInt(f.v.Int(), 10)
 | 
	
		
			
				|  |  | +	return []byte(f.nskey() + " = " + i), nil
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +func (f *field) float32Encoder() ([]byte, error) {
 | 
	
		
			
				|  |  | +	i := strconv.FormatFloat(f.v.Float(), 'G', -1, 32)
 | 
	
		
			
				|  |  | +	return []byte(f.nskey() + " = " + i), nil
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +func (f *field) float64Encoder() ([]byte, error) {
 | 
	
		
			
				|  |  | +	i := strconv.FormatFloat(f.v.Float(), 'G', -1, 64)
 | 
	
		
			
				|  |  | +	return []byte(f.nskey() + " = " + i), nil
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +func (f *field) strEncoder() ([]byte, error) {
 | 
	
		
			
				|  |  | +	str := strings.Replace(f.v.String(), "\n", "\\\n", -1)
 | 
	
		
			
				|  |  | +	return []byte(f.nskey() + " = " + str), nil
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +func (f *field) boolEncoder() ([]byte, error) {
 | 
	
		
			
				|  |  | +	if f.v.Bool() {
 | 
	
		
			
				|  |  | +		return []byte(f.nskey()), nil
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +	return nil, nil
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +func (f *field) structEncoder() ([]byte, error) {
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	split := strings.SplitN(f.ns, ".", 3)
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	if len(split) == 2 {
 | 
	
		
			
				|  |  | +		return nil, nil
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	if len(split) != 3 {
 | 
	
		
			
				|  |  | +		return nil, &INIEncoderError{
 | 
	
		
			
				|  |  | +			msg: "Struct encoder",
 | 
	
		
			
				|  |  | +			err: fmt.Errorf("Invalid namespace"),
 | 
	
		
			
				|  |  | +			f:   f,
 | 
	
		
			
				|  |  | +		}
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	return []byte("\n[" + split[2] + "]"), nil
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +func (f *field) marshalerDecoder() ([]byte, error) {
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	if err := f.valid(); err != nil {
 | 
	
		
			
				|  |  | +		return nil, &INIEncoderError{
 | 
	
		
			
				|  |  | +			msg: "Unmarshaler decoder",
 | 
	
		
			
				|  |  | +			err: err,
 | 
	
		
			
				|  |  | +			f:   f,
 | 
	
		
			
				|  |  | +		}
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	v := f.v
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	if v.Kind() != reflect.Ptr && v.Type().Name() != "" {
 | 
	
		
			
				|  |  | +		v = v.Addr()
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	if v.IsNil() {
 | 
	
		
			
				|  |  | +		v.Set(reflect.New(v.Type().Elem()))
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	if i, ok := v.Interface().(Marshaler); ok {
 | 
	
		
			
				|  |  | +		b, err := i.MarshalINI()
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +		if err != nil {
 | 
	
		
			
				|  |  | +			return nil, err
 | 
	
		
			
				|  |  | +		}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +		if b == nil {
 | 
	
		
			
				|  |  | +			return nil, nil
 | 
	
		
			
				|  |  | +		}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +		return append([]byte(f.nskey()+" = "), b...), nil
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	if i, ok := v.Interface().(encoding.TextMarshaler); ok {
 | 
	
		
			
				|  |  | +		b, err := i.MarshalText()
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +		if err != nil {
 | 
	
		
			
				|  |  | +			return nil, err
 | 
	
		
			
				|  |  | +		}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +		if b == nil {
 | 
	
		
			
				|  |  | +			return nil, nil
 | 
	
		
			
				|  |  | +		}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +		return append([]byte(f.nskey()+" = "), b...), nil
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	return nil, fmt.Errorf("Cannot load Marshaler")
 | 
	
		
			
				|  |  | +}
 |