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 }