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

     1  package encoder
     2  
     3  import (
     4  	"fmt"
     5  	"reflect"
     6  	"unsafe"
     7  
     8  	"github.com/trim21/go-phpserialize/internal/runtime"
     9  )
    10  
    11  type emptyFunc func(ctx *Ctx, p uintptr) (isEmpty bool, err error)
    12  
    13  func compileEmptyFunc(rt *runtime.Type) (emptyFunc, error) {
    14  	switch rt.Kind() {
    15  	case reflect.Bool:
    16  		return func(ctx *Ctx, p uintptr) (bool, error) {
    17  			value := **(**bool)(unsafe.Pointer(&p))
    18  			return !value, nil
    19  		}, nil
    20  	case reflect.Int8:
    21  		return func(ctx *Ctx, p uintptr) (bool, error) {
    22  			value := **(**int8)(unsafe.Pointer(&p))
    23  			return value == 0, nil
    24  		}, nil
    25  	case reflect.Int16:
    26  		return func(ctx *Ctx, p uintptr) (bool, error) {
    27  			value := **(**int16)(unsafe.Pointer(&p))
    28  			return value == 0, nil
    29  		}, nil
    30  	case reflect.Int32:
    31  		return func(ctx *Ctx, p uintptr) (bool, error) {
    32  			value := **(**int32)(unsafe.Pointer(&p))
    33  			return value == 0, nil
    34  		}, nil
    35  	case reflect.Int64:
    36  		return func(ctx *Ctx, p uintptr) (bool, error) {
    37  			value := **(**int64)(unsafe.Pointer(&p))
    38  			return value == 0, nil
    39  		}, nil
    40  	case reflect.Int:
    41  		return func(ctx *Ctx, p uintptr) (bool, error) {
    42  			value := **(**int)(unsafe.Pointer(&p))
    43  			return value == 0, nil
    44  		}, nil
    45  	case reflect.String:
    46  		return func(ctx *Ctx, p uintptr) (bool, error) {
    47  			s := *(**reflect.StringHeader)(unsafe.Pointer(&p))
    48  			return s.Len == 0, nil
    49  		}, nil
    50  	case reflect.Uint8:
    51  		return func(ctx *Ctx, p uintptr) (bool, error) {
    52  			value := **(**uint8)(unsafe.Pointer(&p))
    53  			return value == 0, nil
    54  		}, nil
    55  	case reflect.Uint16:
    56  		return func(ctx *Ctx, p uintptr) (bool, error) {
    57  			value := **(**uint16)(unsafe.Pointer(&p))
    58  			return value == 0, nil
    59  		}, nil
    60  	case reflect.Uint32:
    61  		return func(ctx *Ctx, p uintptr) (bool, error) {
    62  			value := **(**uint32)(unsafe.Pointer(&p))
    63  			return value == 0, nil
    64  		}, nil
    65  	case reflect.Uint64:
    66  		return func(ctx *Ctx, p uintptr) (bool, error) {
    67  			value := **(**uint64)(unsafe.Pointer(&p))
    68  			return value == 0, nil
    69  		}, nil
    70  	case reflect.Uint:
    71  		return func(ctx *Ctx, p uintptr) (bool, error) {
    72  			value := **(**uint)(unsafe.Pointer(&p))
    73  			return value == 0, nil
    74  		}, nil
    75  	case reflect.Float32:
    76  		return func(ctx *Ctx, p uintptr) (bool, error) {
    77  			value := **(**float32)(unsafe.Pointer(&p))
    78  			return value == 0, nil
    79  		}, nil
    80  	case reflect.Float64:
    81  		return func(ctx *Ctx, p uintptr) (bool, error) {
    82  			value := **(**float64)(unsafe.Pointer(&p))
    83  			return value == 0, nil
    84  		}, nil
    85  	case reflect.Struct:
    86  		return func(ctx *Ctx, p uintptr) (bool, error) {
    87  			return false, nil
    88  		}, nil
    89  	case reflect.Slice:
    90  		return func(ctx *Ctx, p uintptr) (bool, error) {
    91  			dataPtr := **(**uintptr)(unsafe.Pointer(&p))
    92  			return dataPtr == 0, nil
    93  		}, nil
    94  	case reflect.Map:
    95  		return func(ctx *Ctx, p uintptr) (bool, error) {
    96  			return p == 0, nil
    97  		}, nil
    98  	case reflect.Interface:
    99  		return func(ctx *Ctx, p uintptr) (bool, error) {
   100  			p = unpackIface(p)
   101  			return p == 0, nil
   102  		}, nil
   103  	case reflect.Ptr:
   104  		return func(ctx *Ctx, p uintptr) (bool, error) {
   105  			p = **(**uintptr)(unsafe.Pointer(&p))
   106  			return p == 0, nil
   107  		}, nil
   108  	case reflect.Array:
   109  		return EmptyPtr, nil
   110  	}
   111  
   112  	return nil, fmt.Errorf("failed to build encoder, unsupported type %s (kind %s) with tag `omitempty`", rt.String(), rt.Kind())
   113  }
   114  
   115  func EmptyPtr(ctx *Ctx, p uintptr) (bool, error) {
   116  	return p == 0, nil
   117  }
   118  
   119  func AlwaysHasValue(_ *Ctx, _ uintptr) (bool, error) {
   120  	return true, nil
   121  }