github.com/trim21/go-phpserialize@v0.0.22-0.20240301204449-2fca0319b3f0/internal/encoder/ptr.go (about)

     1  package encoder
     2  
     3  import (
     4  	"fmt"
     5  	"reflect"
     6  
     7  	"github.com/trim21/go-phpserialize/internal/runtime"
     8  )
     9  
    10  // MUST call `compilePtr` directly when compile encoder for struct field.
    11  func compilePtr(rt *runtime.Type, seen seenMap) (encoder, error) {
    12  	switch rt.Elem().Kind() {
    13  	case reflect.Ptr:
    14  		return nil, fmt.Errorf("encoding nested ptr is not supported *%s", rt.Elem().String())
    15  
    16  	case reflect.Bool:
    17  		return encodeBool, nil
    18  	case reflect.Uint8:
    19  		return encodeUint8, nil
    20  	case reflect.Uint16:
    21  		return encodeUint16, nil
    22  	case reflect.Uint32:
    23  		return encodeUint32, nil
    24  	case reflect.Uint64:
    25  		return encodeUint64, nil
    26  	case reflect.Uint:
    27  		return encodeUint, nil
    28  	case reflect.Int8:
    29  		return encodeInt8, nil
    30  	case reflect.Int16:
    31  		return encodeInt16, nil
    32  	case reflect.Int32:
    33  		return encodeInt32, nil
    34  	case reflect.Int64:
    35  		return encodeInt64, nil
    36  	case reflect.Int:
    37  		return encodeInt, nil
    38  	case reflect.Float32:
    39  		return encodeFloat32, nil
    40  	case reflect.Float64:
    41  		return encodeFloat64, nil
    42  	case reflect.String:
    43  		return encodeString, nil
    44  	case reflect.Interface:
    45  		return compileInterface(rt.Elem())
    46  	case reflect.Map:
    47  		enc, err := compileMap(rt.Elem(), seen)
    48  		return deRefNilEncoder(enc), err
    49  	case reflect.Struct:
    50  		enc, err := compileStruct(rt.Elem(), seen)
    51  		indirect := runtime.IfaceIndir(rt.Elem())
    52  		if indirect {
    53  			return wrapNilEncoder(enc), err
    54  		}
    55  
    56  		return deRefNilEncoder(enc), err
    57  	}
    58  
    59  	enc, err := compile(rt.Elem(), seen)
    60  	if err != nil {
    61  		return nil, err
    62  	}
    63  
    64  	return deRefNilEncoder(enc), nil
    65  }
    66  
    67  func deRefNilEncoder(enc encoder) encoder {
    68  	return func(ctx *Ctx, b []byte, p uintptr) ([]byte, error) {
    69  		if p == 0 {
    70  			return appendNull(b), nil
    71  		}
    72  		p = PtrDeRef(p)
    73  		return enc(ctx, b, p)
    74  	}
    75  }
    76  
    77  func wrapNilEncoder(enc encoder) encoder {
    78  	return func(ctx *Ctx, b []byte, p uintptr) ([]byte, error) {
    79  		if p == 0 {
    80  			return appendNull(b), nil
    81  		}
    82  		return enc(ctx, b, p)
    83  	}
    84  }