mirror of https://github.com/gogits/gogs.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
133 lines
3.4 KiB
133 lines
3.4 KiB
package jsoniter |
|
|
|
import ( |
|
"github.com/modern-go/reflect2" |
|
"reflect" |
|
"unsafe" |
|
) |
|
|
|
func decoderOfOptional(ctx *ctx, typ reflect2.Type) ValDecoder { |
|
ptrType := typ.(*reflect2.UnsafePtrType) |
|
elemType := ptrType.Elem() |
|
decoder := decoderOfType(ctx, elemType) |
|
if ctx.prefix == "" && elemType.Kind() == reflect.Ptr { |
|
return &dereferenceDecoder{elemType, decoder} |
|
} |
|
return &OptionalDecoder{elemType, decoder} |
|
} |
|
|
|
func encoderOfOptional(ctx *ctx, typ reflect2.Type) ValEncoder { |
|
ptrType := typ.(*reflect2.UnsafePtrType) |
|
elemType := ptrType.Elem() |
|
elemEncoder := encoderOfType(ctx, elemType) |
|
encoder := &OptionalEncoder{elemEncoder} |
|
return encoder |
|
} |
|
|
|
type OptionalDecoder struct { |
|
ValueType reflect2.Type |
|
ValueDecoder ValDecoder |
|
} |
|
|
|
func (decoder *OptionalDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) { |
|
if iter.ReadNil() { |
|
*((*unsafe.Pointer)(ptr)) = nil |
|
} else { |
|
if *((*unsafe.Pointer)(ptr)) == nil { |
|
//pointer to null, we have to allocate memory to hold the value |
|
newPtr := decoder.ValueType.UnsafeNew() |
|
decoder.ValueDecoder.Decode(newPtr, iter) |
|
*((*unsafe.Pointer)(ptr)) = newPtr |
|
} else { |
|
//reuse existing instance |
|
decoder.ValueDecoder.Decode(*((*unsafe.Pointer)(ptr)), iter) |
|
} |
|
} |
|
} |
|
|
|
type dereferenceDecoder struct { |
|
// only to deference a pointer |
|
valueType reflect2.Type |
|
valueDecoder ValDecoder |
|
} |
|
|
|
func (decoder *dereferenceDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) { |
|
if *((*unsafe.Pointer)(ptr)) == nil { |
|
//pointer to null, we have to allocate memory to hold the value |
|
newPtr := decoder.valueType.UnsafeNew() |
|
decoder.valueDecoder.Decode(newPtr, iter) |
|
*((*unsafe.Pointer)(ptr)) = newPtr |
|
} else { |
|
//reuse existing instance |
|
decoder.valueDecoder.Decode(*((*unsafe.Pointer)(ptr)), iter) |
|
} |
|
} |
|
|
|
type OptionalEncoder struct { |
|
ValueEncoder ValEncoder |
|
} |
|
|
|
func (encoder *OptionalEncoder) Encode(ptr unsafe.Pointer, stream *Stream) { |
|
if *((*unsafe.Pointer)(ptr)) == nil { |
|
stream.WriteNil() |
|
} else { |
|
encoder.ValueEncoder.Encode(*((*unsafe.Pointer)(ptr)), stream) |
|
} |
|
} |
|
|
|
func (encoder *OptionalEncoder) IsEmpty(ptr unsafe.Pointer) bool { |
|
return *((*unsafe.Pointer)(ptr)) == nil |
|
} |
|
|
|
type dereferenceEncoder struct { |
|
ValueEncoder ValEncoder |
|
} |
|
|
|
func (encoder *dereferenceEncoder) Encode(ptr unsafe.Pointer, stream *Stream) { |
|
if *((*unsafe.Pointer)(ptr)) == nil { |
|
stream.WriteNil() |
|
} else { |
|
encoder.ValueEncoder.Encode(*((*unsafe.Pointer)(ptr)), stream) |
|
} |
|
} |
|
|
|
func (encoder *dereferenceEncoder) IsEmpty(ptr unsafe.Pointer) bool { |
|
dePtr := *((*unsafe.Pointer)(ptr)) |
|
if dePtr == nil { |
|
return true |
|
} |
|
return encoder.ValueEncoder.IsEmpty(dePtr) |
|
} |
|
|
|
func (encoder *dereferenceEncoder) IsEmbeddedPtrNil(ptr unsafe.Pointer) bool { |
|
deReferenced := *((*unsafe.Pointer)(ptr)) |
|
if deReferenced == nil { |
|
return true |
|
} |
|
isEmbeddedPtrNil, converted := encoder.ValueEncoder.(IsEmbeddedPtrNil) |
|
if !converted { |
|
return false |
|
} |
|
fieldPtr := unsafe.Pointer(deReferenced) |
|
return isEmbeddedPtrNil.IsEmbeddedPtrNil(fieldPtr) |
|
} |
|
|
|
type referenceEncoder struct { |
|
encoder ValEncoder |
|
} |
|
|
|
func (encoder *referenceEncoder) Encode(ptr unsafe.Pointer, stream *Stream) { |
|
encoder.encoder.Encode(unsafe.Pointer(&ptr), stream) |
|
} |
|
|
|
func (encoder *referenceEncoder) IsEmpty(ptr unsafe.Pointer) bool { |
|
return encoder.encoder.IsEmpty(unsafe.Pointer(&ptr)) |
|
} |
|
|
|
type referenceDecoder struct { |
|
decoder ValDecoder |
|
} |
|
|
|
func (decoder *referenceDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) { |
|
decoder.decoder.Decode(unsafe.Pointer(&ptr), iter) |
|
}
|
|
|