mirror of
https://github.com/hanzoai/volume.git
synced 2026-10-01 00:48:00 +00:00
A fork of Rancher's local-path-provisioner at v0.0.36. The behaviour is unchanged and deliberately so — a directory on the node a pod lands on is the right thing for a disk. What changes is identity. The provisioner answers to hanzo.ai/volume rather than rancher.io/local-path. That is not branding: two provisioners sharing one name race for the same claims, and a stock k3s carries the upstream one, so a cluster running both would settle our storage by chance. Data lives at /var/lib/hanzo/volume, so reading a Hanzo cluster does not mean learning another vendor's directory. Apache-2.0 as published, unaltered, with Rancher's attribution in NOTICE. The README says what this is not: durability. A volume here dies with its node. That is hanzoai/replicate's question, one layer up, and keeping the two apart is what lets the disk stay this simple.
226 lines
5.8 KiB
Go
226 lines
5.8 KiB
Go
package jsoniter
|
|
|
|
import (
|
|
"encoding"
|
|
"encoding/json"
|
|
"unsafe"
|
|
|
|
"github.com/modern-go/reflect2"
|
|
)
|
|
|
|
var marshalerType = reflect2.TypeOfPtr((*json.Marshaler)(nil)).Elem()
|
|
var unmarshalerType = reflect2.TypeOfPtr((*json.Unmarshaler)(nil)).Elem()
|
|
var textMarshalerType = reflect2.TypeOfPtr((*encoding.TextMarshaler)(nil)).Elem()
|
|
var textUnmarshalerType = reflect2.TypeOfPtr((*encoding.TextUnmarshaler)(nil)).Elem()
|
|
|
|
func createDecoderOfMarshaler(ctx *ctx, typ reflect2.Type) ValDecoder {
|
|
ptrType := reflect2.PtrTo(typ)
|
|
if ptrType.Implements(unmarshalerType) {
|
|
return &referenceDecoder{
|
|
&unmarshalerDecoder{ptrType},
|
|
}
|
|
}
|
|
if ptrType.Implements(textUnmarshalerType) {
|
|
return &referenceDecoder{
|
|
&textUnmarshalerDecoder{ptrType},
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func createEncoderOfMarshaler(ctx *ctx, typ reflect2.Type) ValEncoder {
|
|
if typ == marshalerType {
|
|
checkIsEmpty := createCheckIsEmpty(ctx, typ)
|
|
var encoder ValEncoder = &directMarshalerEncoder{
|
|
checkIsEmpty: checkIsEmpty,
|
|
}
|
|
return encoder
|
|
}
|
|
if typ.Implements(marshalerType) {
|
|
checkIsEmpty := createCheckIsEmpty(ctx, typ)
|
|
var encoder ValEncoder = &marshalerEncoder{
|
|
valType: typ,
|
|
checkIsEmpty: checkIsEmpty,
|
|
}
|
|
return encoder
|
|
}
|
|
ptrType := reflect2.PtrTo(typ)
|
|
if ctx.prefix != "" && ptrType.Implements(marshalerType) {
|
|
checkIsEmpty := createCheckIsEmpty(ctx, ptrType)
|
|
var encoder ValEncoder = &marshalerEncoder{
|
|
valType: ptrType,
|
|
checkIsEmpty: checkIsEmpty,
|
|
}
|
|
return &referenceEncoder{encoder}
|
|
}
|
|
if typ == textMarshalerType {
|
|
checkIsEmpty := createCheckIsEmpty(ctx, typ)
|
|
var encoder ValEncoder = &directTextMarshalerEncoder{
|
|
checkIsEmpty: checkIsEmpty,
|
|
stringEncoder: ctx.EncoderOf(reflect2.TypeOf("")),
|
|
}
|
|
return encoder
|
|
}
|
|
if typ.Implements(textMarshalerType) {
|
|
checkIsEmpty := createCheckIsEmpty(ctx, typ)
|
|
var encoder ValEncoder = &textMarshalerEncoder{
|
|
valType: typ,
|
|
stringEncoder: ctx.EncoderOf(reflect2.TypeOf("")),
|
|
checkIsEmpty: checkIsEmpty,
|
|
}
|
|
return encoder
|
|
}
|
|
// if prefix is empty, the type is the root type
|
|
if ctx.prefix != "" && ptrType.Implements(textMarshalerType) {
|
|
checkIsEmpty := createCheckIsEmpty(ctx, ptrType)
|
|
var encoder ValEncoder = &textMarshalerEncoder{
|
|
valType: ptrType,
|
|
stringEncoder: ctx.EncoderOf(reflect2.TypeOf("")),
|
|
checkIsEmpty: checkIsEmpty,
|
|
}
|
|
return &referenceEncoder{encoder}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
type marshalerEncoder struct {
|
|
checkIsEmpty checkIsEmpty
|
|
valType reflect2.Type
|
|
}
|
|
|
|
func (encoder *marshalerEncoder) Encode(ptr unsafe.Pointer, stream *Stream) {
|
|
obj := encoder.valType.UnsafeIndirect(ptr)
|
|
if encoder.valType.IsNullable() && reflect2.IsNil(obj) {
|
|
stream.WriteNil()
|
|
return
|
|
}
|
|
marshaler := obj.(json.Marshaler)
|
|
bytes, err := marshaler.MarshalJSON()
|
|
if err != nil {
|
|
stream.Error = err
|
|
} else {
|
|
// html escape was already done by jsoniter
|
|
// but the extra '\n' should be trimed
|
|
l := len(bytes)
|
|
if l > 0 && bytes[l-1] == '\n' {
|
|
bytes = bytes[:l-1]
|
|
}
|
|
stream.Write(bytes)
|
|
}
|
|
}
|
|
|
|
func (encoder *marshalerEncoder) IsEmpty(ptr unsafe.Pointer) bool {
|
|
return encoder.checkIsEmpty.IsEmpty(ptr)
|
|
}
|
|
|
|
type directMarshalerEncoder struct {
|
|
checkIsEmpty checkIsEmpty
|
|
}
|
|
|
|
func (encoder *directMarshalerEncoder) Encode(ptr unsafe.Pointer, stream *Stream) {
|
|
marshaler := *(*json.Marshaler)(ptr)
|
|
if marshaler == nil {
|
|
stream.WriteNil()
|
|
return
|
|
}
|
|
bytes, err := marshaler.MarshalJSON()
|
|
if err != nil {
|
|
stream.Error = err
|
|
} else {
|
|
stream.Write(bytes)
|
|
}
|
|
}
|
|
|
|
func (encoder *directMarshalerEncoder) IsEmpty(ptr unsafe.Pointer) bool {
|
|
return encoder.checkIsEmpty.IsEmpty(ptr)
|
|
}
|
|
|
|
type textMarshalerEncoder struct {
|
|
valType reflect2.Type
|
|
stringEncoder ValEncoder
|
|
checkIsEmpty checkIsEmpty
|
|
}
|
|
|
|
func (encoder *textMarshalerEncoder) Encode(ptr unsafe.Pointer, stream *Stream) {
|
|
obj := encoder.valType.UnsafeIndirect(ptr)
|
|
if encoder.valType.IsNullable() && reflect2.IsNil(obj) {
|
|
stream.WriteNil()
|
|
return
|
|
}
|
|
marshaler := (obj).(encoding.TextMarshaler)
|
|
bytes, err := marshaler.MarshalText()
|
|
if err != nil {
|
|
stream.Error = err
|
|
} else {
|
|
str := string(bytes)
|
|
encoder.stringEncoder.Encode(unsafe.Pointer(&str), stream)
|
|
}
|
|
}
|
|
|
|
func (encoder *textMarshalerEncoder) IsEmpty(ptr unsafe.Pointer) bool {
|
|
return encoder.checkIsEmpty.IsEmpty(ptr)
|
|
}
|
|
|
|
type directTextMarshalerEncoder struct {
|
|
stringEncoder ValEncoder
|
|
checkIsEmpty checkIsEmpty
|
|
}
|
|
|
|
func (encoder *directTextMarshalerEncoder) Encode(ptr unsafe.Pointer, stream *Stream) {
|
|
marshaler := *(*encoding.TextMarshaler)(ptr)
|
|
if marshaler == nil {
|
|
stream.WriteNil()
|
|
return
|
|
}
|
|
bytes, err := marshaler.MarshalText()
|
|
if err != nil {
|
|
stream.Error = err
|
|
} else {
|
|
str := string(bytes)
|
|
encoder.stringEncoder.Encode(unsafe.Pointer(&str), stream)
|
|
}
|
|
}
|
|
|
|
func (encoder *directTextMarshalerEncoder) IsEmpty(ptr unsafe.Pointer) bool {
|
|
return encoder.checkIsEmpty.IsEmpty(ptr)
|
|
}
|
|
|
|
type unmarshalerDecoder struct {
|
|
valType reflect2.Type
|
|
}
|
|
|
|
func (decoder *unmarshalerDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) {
|
|
valType := decoder.valType
|
|
obj := valType.UnsafeIndirect(ptr)
|
|
unmarshaler := obj.(json.Unmarshaler)
|
|
iter.nextToken()
|
|
iter.unreadByte() // skip spaces
|
|
bytes := iter.SkipAndReturnBytes()
|
|
err := unmarshaler.UnmarshalJSON(bytes)
|
|
if err != nil {
|
|
iter.ReportError("unmarshalerDecoder", err.Error())
|
|
}
|
|
}
|
|
|
|
type textUnmarshalerDecoder struct {
|
|
valType reflect2.Type
|
|
}
|
|
|
|
func (decoder *textUnmarshalerDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) {
|
|
valType := decoder.valType
|
|
obj := valType.UnsafeIndirect(ptr)
|
|
if reflect2.IsNil(obj) {
|
|
ptrType := valType.(*reflect2.UnsafePtrType)
|
|
elemType := ptrType.Elem()
|
|
elem := elemType.UnsafeNew()
|
|
ptrType.UnsafeSet(ptr, unsafe.Pointer(&elem))
|
|
obj = valType.UnsafeIndirect(ptr)
|
|
}
|
|
unmarshaler := (obj).(encoding.TextUnmarshaler)
|
|
str := iter.ReadString()
|
|
err := unmarshaler.UnmarshalText([]byte(str))
|
|
if err != nil {
|
|
iter.ReportError("textUnmarshalerDecoder", err.Error())
|
|
}
|
|
}
|