diff --git a/encode_compile.go b/encode_compile.go index 9cab925..9dc7ec2 100644 --- a/encode_compile.go +++ b/encode_compile.go @@ -435,6 +435,26 @@ func (e *Encoder) typeToHeaderType(op opType) opType { return opStructFieldHeadString case opBool: return opStructFieldHeadBool + case opMapHead: + return opStructFieldHeadMap + case opMapHeadLoad: + return opStructFieldHeadMapLoad + case opMapHeadIndent: + return opStructFieldHeadMapIndent + case opMapHeadLoadIndent: + return opStructFieldHeadMapLoadIndent + case opArrayHead: + return opStructFieldHeadArray + case opArrayHeadIndent: + return opStructFieldHeadArrayIndent + case opSliceHead: + return opStructFieldHeadSlice + case opSliceHeadIndent: + return opStructFieldHeadSliceIndent + case opStructFieldHead: + return opStructFieldHeadStruct + case opStructFieldHeadIndent: + return opStructFieldHeadStructIndent case opMarshalJSON: return opStructFieldHeadMarshalJSON case opMarshalText: @@ -473,6 +493,26 @@ func (e *Encoder) typeToFieldType(op opType) opType { return opStructFieldString case opBool: return opStructFieldBool + case opMapHead: + return opStructFieldMap + case opMapHeadLoad: + return opStructFieldMapLoad + case opMapHeadIndent: + return opStructFieldMapIndent + case opMapHeadLoadIndent: + return opStructFieldMapLoadIndent + case opArrayHead: + return opStructFieldArray + case opArrayHeadIndent: + return opStructFieldArrayIndent + case opSliceHead: + return opStructFieldSlice + case opSliceHeadIndent: + return opStructFieldSliceIndent + case opStructFieldHead: + return opStructFieldStruct + case opStructFieldHeadIndent: + return opStructFieldStructIndent case opMarshalJSON: return opStructFieldMarshalJSON case opMarshalText: @@ -541,10 +581,30 @@ func (e *Encoder) structHeader(fieldCode *structFieldCode, valueCode *opcode, ta fieldCode.op = op switch op { case opStructFieldHead, + opStructFieldHeadSlice, + opStructFieldHeadArray, + opStructFieldHeadMap, + opStructFieldHeadMapLoad, + opStructFieldHeadStruct, opStructFieldHeadOmitEmpty, + opStructFieldHeadOmitEmptySlice, + opStructFieldHeadOmitEmptyArray, + opStructFieldHeadOmitEmptyMap, + opStructFieldHeadOmitEmptyMapLoad, + opStructFieldHeadOmitEmptyStruct, opStructFieldHeadStringTag, opStructFieldHeadIndent, + opStructFieldHeadSliceIndent, + opStructFieldHeadArrayIndent, + opStructFieldHeadMapIndent, + opStructFieldHeadMapLoadIndent, + opStructFieldHeadStructIndent, opStructFieldHeadOmitEmptyIndent, + opStructFieldHeadOmitEmptySliceIndent, + opStructFieldHeadOmitEmptyArrayIndent, + opStructFieldHeadOmitEmptyMapIndent, + opStructFieldHeadOmitEmptyMapLoadIndent, + opStructFieldHeadOmitEmptyStructIndent, opStructFieldHeadStringTagIndent: return valueCode.beforeLastCode() } @@ -557,10 +617,30 @@ func (e *Encoder) structField(fieldCode *structFieldCode, valueCode *opcode, tag fieldCode.op = op switch op { case opStructField, + opStructFieldSlice, + opStructFieldArray, + opStructFieldMap, + opStructFieldMapLoad, + opStructFieldStruct, opStructFieldOmitEmpty, + opStructFieldOmitEmptySlice, + opStructFieldOmitEmptyArray, + opStructFieldOmitEmptyMap, + opStructFieldOmitEmptyMapLoad, + opStructFieldOmitEmptyStruct, opStructFieldStringTag, opStructFieldIndent, + opStructFieldSliceIndent, + opStructFieldArrayIndent, + opStructFieldMapIndent, + opStructFieldMapLoadIndent, + opStructFieldStructIndent, opStructFieldOmitEmptyIndent, + opStructFieldOmitEmptySliceIndent, + opStructFieldOmitEmptyArrayIndent, + opStructFieldOmitEmptyMapIndent, + opStructFieldOmitEmptyMapLoadIndent, + opStructFieldOmitEmptyStructIndent, opStructFieldStringTagIndent: return valueCode.beforeLastCode() } diff --git a/encode_vm.go b/encode_vm.go index d38ceb6..b9f4eaf 100644 --- a/encode_vm.go +++ b/encode_vm.go @@ -1093,6 +1093,78 @@ func (e *Encoder) run(code *opcode) error { field.nextField.ptr = ptr code = field.next } + case opStructFieldPtrHeadArray: + code.ptr = e.ptrToPtr(code.ptr) + fallthrough + case opStructFieldHeadArray: + c := code.toStructFieldCode() + ptr := c.ptr + c.offset + if ptr == 0 { + if code.op == opStructFieldPtrHeadArray { + e.encodeNull() + } else { + e.encodeBytes([]byte{'[', ']'}) + } + code = c.end + } else { + e.encodeByte('{') + if !c.anonymousKey { + e.encodeBytes(c.key) + } + code = c.next + code.ptr = ptr + c.nextField.ptr = ptr + } + case opStructFieldPtrAnonymousHeadArray: + code.ptr = e.ptrToPtr(code.ptr) + fallthrough + case opStructFieldAnonymousHeadArray: + c := code.toStructFieldCode() + ptr := c.ptr + c.offset + if ptr == 0 { + code = c.end + } else { + e.encodeBytes(c.key) + code.ptr = ptr + c.nextField.ptr = ptr + code = c.next + } + case opStructFieldPtrHeadSlice: + code.ptr = e.ptrToPtr(code.ptr) + fallthrough + case opStructFieldHeadSlice: + c := code.toStructFieldCode() + ptr := c.ptr + c.offset + if ptr == 0 { + if code.op == opStructFieldPtrHeadSlice { + e.encodeNull() + } else { + e.encodeBytes([]byte{'[', ']'}) + } + code = c.end + } else { + e.encodeByte('{') + if !c.anonymousKey { + e.encodeBytes(c.key) + } + code = c.next + code.ptr = ptr + c.nextField.ptr = ptr + } + case opStructFieldPtrAnonymousHeadSlice: + code.ptr = e.ptrToPtr(code.ptr) + fallthrough + case opStructFieldAnonymousHeadSlice: + c := code.toStructFieldCode() + ptr := c.ptr + c.offset + if ptr == 0 { + code = c.end + } else { + e.encodeBytes(c.key) + code.ptr = ptr + c.nextField.ptr = ptr + code = c.next + } case opStructFieldPtrHeadMarshalJSON: code.ptr = e.ptrToPtr(code.ptr) fallthrough @@ -4150,6 +4222,51 @@ func (e *Encoder) run(code *opcode) error { } e.encodeString(*(*string)(unsafe.Pointer(&bytes))) code = code.next + case opStructFieldArray: + if e.buf[len(e.buf)-1] != '{' { + e.encodeByte(',') + } + c := code.toStructFieldCode() + c.nextField.ptr = c.ptr + code = code.next + code.ptr = c.ptr + c.offset + e.encodeBytes(c.key) + case opStructFieldSlice: + if e.buf[len(e.buf)-1] != '{' { + e.encodeByte(',') + } + c := code.toStructFieldCode() + c.nextField.ptr = c.ptr + code = code.next + code.ptr = c.ptr + c.offset + e.encodeBytes(c.key) + case opStructFieldMap: + if e.buf[len(e.buf)-1] != '{' { + e.encodeByte(',') + } + c := code.toStructFieldCode() + e.encodeBytes(c.key) + code = code.next + code.ptr = c.ptr + c.offset + c.nextField.ptr = c.ptr + case opStructFieldMapLoad: + if e.buf[len(e.buf)-1] != '{' { + e.encodeByte(',') + } + c := code.toStructFieldCode() + e.encodeBytes(c.key) + code = code.next + code.ptr = c.ptr + c.offset + c.nextField.ptr = c.ptr + case opStructFieldStruct: + if e.buf[len(e.buf)-1] != '{' { + e.encodeByte(',') + } + c := code.toStructFieldCode() + e.encodeBytes(c.key) + code = code.next + code.ptr = c.ptr + c.offset + c.nextField.ptr = c.ptr case opStructFieldIndent: c := code.toStructFieldCode() if e.buf[len(e.buf)-2] != '{' || e.buf[len(e.buf)-1] == '}' { @@ -4363,6 +4480,111 @@ func (e *Encoder) run(code *opcode) error { e.encodeBytes(buf.Bytes()) code = code.next c.nextField.ptr = c.ptr + case opStructFieldArrayIndent: + if e.buf[len(e.buf)-2] != '{' || e.buf[len(e.buf)-1] == '}' { + e.encodeBytes([]byte{',', '\n'}) + } + c := code.toStructFieldCode() + e.encodeIndent(c.indent) + e.encodeBytes(c.key) + e.encodeByte(' ') + p := c.ptr + c.offset + header := (*reflect.SliceHeader)(unsafe.Pointer(p)) + if p == 0 || header.Data == 0 { + e.encodeNull() + code = c.nextField + } else { + code = code.next + } + c.nextField.ptr = c.ptr + case opStructFieldSliceIndent: + if e.buf[len(e.buf)-2] != '{' || e.buf[len(e.buf)-1] == '}' { + e.encodeBytes([]byte{',', '\n'}) + } + c := code.toStructFieldCode() + e.encodeIndent(c.indent) + e.encodeBytes(c.key) + e.encodeByte(' ') + p := c.ptr + c.offset + header := (*reflect.SliceHeader)(unsafe.Pointer(p)) + if p == 0 || header.Data == 0 { + e.encodeNull() + code = c.nextField + } else { + code = code.next + } + c.nextField.ptr = c.ptr + case opStructFieldMapIndent: + if e.buf[len(e.buf)-2] != '{' || e.buf[len(e.buf)-1] == '}' { + e.encodeBytes([]byte{',', '\n'}) + } + c := code.toStructFieldCode() + e.encodeIndent(c.indent) + e.encodeBytes(c.key) + e.encodeByte(' ') + p := c.ptr + c.offset + if p == 0 { + e.encodeNull() + code = c.nextField + } else { + mlen := maplen(unsafe.Pointer(p)) + if mlen == 0 { + e.encodeBytes([]byte{'{', '}'}) + mapCode := code.next + mapHeadCode := mapCode.toMapHeadCode() + code = mapHeadCode.end.next + } else { + code = code.next + } + } + c.nextField.ptr = c.ptr + case opStructFieldMapLoadIndent: + if e.buf[len(e.buf)-2] != '{' || e.buf[len(e.buf)-1] == '}' { + e.encodeBytes([]byte{',', '\n'}) + } + c := code.toStructFieldCode() + e.encodeIndent(c.indent) + e.encodeBytes(c.key) + e.encodeByte(' ') + p := c.ptr + c.offset + if p == 0 { + e.encodeNull() + code = c.nextField + } else { + p = uintptr(*(*unsafe.Pointer)(unsafe.Pointer(p))) + mlen := maplen(unsafe.Pointer(p)) + if mlen == 0 { + e.encodeBytes([]byte{'{', '}'}) + code = c.nextField + } else { + code = code.next + } + } + c.nextField.ptr = c.ptr + case opStructFieldStructIndent: + if e.buf[len(e.buf)-2] != '{' || e.buf[len(e.buf)-1] == '}' { + e.encodeBytes([]byte{',', '\n'}) + } + c := code.toStructFieldCode() + p := c.ptr + c.offset + e.encodeIndent(c.indent) + e.encodeBytes(c.key) + e.encodeByte(' ') + if p == 0 { + e.encodeBytes([]byte{'{', '}'}) + code = c.nextField + } else { + headCode := c.next.toStructFieldCode() + if headCode.next == headCode.end { + // not exists fields + e.encodeBytes([]byte{'{', '}'}) + code = c.nextField + } else { + code = code.next + code.ptr = p + } + } + c.nextField.ptr = c.ptr case opStructFieldOmitEmpty: c := code.toStructFieldCode() p := c.ptr + c.offset @@ -4612,6 +4834,67 @@ func (e *Encoder) run(code *opcode) error { } code = code.next code.ptr = c.ptr + case opStructFieldOmitEmptyArray: + c := code.toStructFieldCode() + p := c.ptr + c.offset + header := (*reflect.SliceHeader)(unsafe.Pointer(p)) + if p == 0 || header.Data == 0 { + code = c.nextField + } else { + if e.buf[len(e.buf)-1] != '{' { + e.encodeByte(',') + } + code = code.next + } + c.nextField.ptr = c.ptr + case opStructFieldOmitEmptySlice: + c := code.toStructFieldCode() + p := c.ptr + c.offset + header := (*reflect.SliceHeader)(unsafe.Pointer(p)) + if p == 0 || header.Data == 0 { + code = c.nextField + } else { + if e.buf[len(e.buf)-1] != '{' { + e.encodeByte(',') + } + code = code.next + } + c.nextField.ptr = c.ptr + case opStructFieldOmitEmptyMap: + c := code.toStructFieldCode() + p := c.ptr + c.offset + if p == 0 { + code = c.nextField + } else { + mlen := maplen(unsafe.Pointer(p)) + if mlen == 0 { + code = c.nextField + } else { + if e.buf[len(e.buf)-1] != '{' { + e.encodeByte(',') + } + code = code.next + } + } + c.nextField.ptr = c.ptr + case opStructFieldOmitEmptyMapLoad: + c := code.toStructFieldCode() + p := c.ptr + c.offset + if p == 0 { + code = c.nextField + } else { + p = uintptr(*(*unsafe.Pointer)(unsafe.Pointer(p))) + mlen := maplen(unsafe.Pointer(p)) + if mlen == 0 { + code = c.nextField + } else { + if e.buf[len(e.buf)-1] != '{' { + e.encodeByte(',') + } + code = code.next + } + } + c.nextField.ptr = c.ptr case opStructFieldOmitEmptyIndent: c := code.toStructFieldCode() p := c.ptr + c.offset @@ -4847,6 +5130,102 @@ func (e *Encoder) run(code *opcode) error { } code = code.next code.ptr = c.ptr + case opStructFieldOmitEmptyArrayIndent: + c := code.toStructFieldCode() + p := c.ptr + c.offset + header := (*reflect.SliceHeader)(unsafe.Pointer(p)) + if p == 0 || header.Data == 0 { + code = c.nextField + } else { + if e.buf[len(e.buf)-2] != '{' || e.buf[len(e.buf)-1] == '}' { + e.encodeBytes([]byte{',', '\n'}) + } + e.encodeIndent(c.indent) + e.encodeBytes(c.key) + e.encodeByte(' ') + code = code.next + } + c.nextField.ptr = c.ptr + case opStructFieldOmitEmptySliceIndent: + c := code.toStructFieldCode() + p := c.ptr + c.offset + header := (*reflect.SliceHeader)(unsafe.Pointer(p)) + if p == 0 || header.Data == 0 { + code = c.nextField + } else { + if e.buf[len(e.buf)-2] != '{' || e.buf[len(e.buf)-1] == '}' { + e.encodeBytes([]byte{',', '\n'}) + } + e.encodeIndent(c.indent) + e.encodeBytes(c.key) + e.encodeByte(' ') + code = code.next + } + c.nextField.ptr = c.ptr + case opStructFieldOmitEmptyMapIndent: + c := code.toStructFieldCode() + p := c.ptr + c.offset + if p == 0 { + code = c.nextField + } else { + mlen := maplen(unsafe.Pointer(p)) + if mlen == 0 { + code = c.nextField + } else { + if e.buf[len(e.buf)-2] != '{' || e.buf[len(e.buf)-1] == '}' { + e.encodeBytes([]byte{',', '\n'}) + } + e.encodeIndent(c.indent) + e.encodeBytes(c.key) + e.encodeByte(' ') + code = code.next + } + } + c.nextField.ptr = c.ptr + case opStructFieldOmitEmptyMapLoadIndent: + c := code.toStructFieldCode() + p := c.ptr + c.offset + if p == 0 { + code = c.nextField + } else { + p = uintptr(*(*unsafe.Pointer)(unsafe.Pointer(p))) + mlen := maplen(unsafe.Pointer(p)) + if mlen == 0 { + code = c.nextField + } else { + if e.buf[len(e.buf)-2] != '{' || e.buf[len(e.buf)-1] == '}' { + e.encodeBytes([]byte{',', '\n'}) + } + e.encodeIndent(c.indent) + e.encodeBytes(c.key) + e.encodeByte(' ') + code = code.next + } + } + c.nextField.ptr = c.ptr + case opStructFieldOmitEmptyStructIndent: + c := code.toStructFieldCode() + p := c.ptr + c.offset + if p == 0 { + code = c.nextField + } else { + if e.buf[len(e.buf)-2] != '{' || e.buf[len(e.buf)-1] == '}' { + e.encodeBytes([]byte{',', '\n'}) + } + e.encodeIndent(c.indent) + e.encodeBytes(c.key) + e.encodeByte(' ') + headCode := c.next.toStructFieldCode() + if headCode.next == headCode.end { + // not exists fields + e.encodeBytes([]byte{'{', '}'}) + code = c.nextField + } else { + code = code.next + code.ptr = p + } + } + c.nextField.ptr = c.ptr case opStructFieldStringTag: c := code.toStructFieldCode() p := c.ptr + c.offset