Fix MarshalNoEscape

This commit is contained in:
Masaaki Goshima 2021-01-31 22:53:01 +09:00
parent 61e533dca2
commit ffc954d356
2 changed files with 48 additions and 1 deletions

View File

@ -133,6 +133,23 @@ func marshal(v interface{}, opt EncodeOption) ([]byte, error) {
return copied, nil return copied, nil
} }
func marshalNoEscape(v interface{}, opt EncodeOption) ([]byte, error) {
buf, err := encodeNoEscapeWithOpt(v, EncodeOptionHTMLEscape)
if err != nil {
return nil, err
}
// this line exists to escape call of `runtime.makeslicecopy` .
// if use `make([]byte, len(buf)-1)` and `copy(copied, buf)`,
// dst buffer size and src buffer size are differrent.
// in this case, compiler uses `runtime.makeslicecopy`, but it is slow.
buf = buf[:len(buf)-1]
copied := make([]byte, len(buf))
copy(copied, buf)
return copied, nil
}
func marshalIndent(v interface{}, prefix, indent string, opt EncodeOption) ([]byte, error) { func marshalIndent(v interface{}, prefix, indent string, opt EncodeOption) ([]byte, error) {
buf, err := encodeIndentWithOpt(v, prefix, indent, EncodeOptionHTMLEscape) buf, err := encodeIndentWithOpt(v, prefix, indent, EncodeOptionHTMLEscape)
if err != nil { if err != nil {
@ -178,6 +195,36 @@ func encodeWithOpt(v interface{}, opt EncodeOption) ([]byte, error) {
return buf, nil return buf, nil
} }
func encodeNoEscapeWithOpt(v interface{}, opt EncodeOption) ([]byte, error) {
ctx := takeEncodeRuntimeContext()
b := ctx.buf[:0]
if v == nil {
b = encodeNull(b)
b = encodeComma(b)
return b, nil
}
header := (*interfaceHeader)(unsafe.Pointer(&v))
typ := header.typ
typeptr := uintptr(unsafe.Pointer(typ))
codeSet, err := encodeCompileToGetCodeSet(typeptr)
if err != nil {
return nil, err
}
p := uintptr(header.ptr)
ctx.init(p, codeSet.codeLength)
buf, err := encodeRunCode(ctx, b, codeSet, opt)
if err != nil {
releaseEncodeRuntimeContext(ctx)
return nil, err
}
ctx.buf = buf
releaseEncodeRuntimeContext(ctx)
return buf, nil
}
func encodeIndentWithOpt(v interface{}, prefix, indent string, opt EncodeOption) ([]byte, error) { func encodeIndentWithOpt(v interface{}, prefix, indent string, opt EncodeOption) ([]byte, error) {
ctx := takeEncodeRuntimeContext() ctx := takeEncodeRuntimeContext()
b := ctx.buf[:0] b := ctx.buf[:0]

View File

@ -159,7 +159,7 @@ func Marshal(v interface{}) ([]byte, error) {
// MarshalNoEscape // MarshalNoEscape
func MarshalNoEscape(v interface{}) ([]byte, error) { func MarshalNoEscape(v interface{}) ([]byte, error) {
return marshal(v, EncodeOptionHTMLEscape) return marshalNoEscape(v, EncodeOptionHTMLEscape)
} }
// MarshalWithOption returns the JSON encoding of v with EncodeOption. // MarshalWithOption returns the JSON encoding of v with EncodeOption.