blob: a30af8dafc9952d62efc6f275a5c28987e8f9ac4 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package hessian
import (
"io"
)
import (
gxbytes "github.com/dubbogo/gost/bytes"
perrors "github.com/pkg/errors"
)
// binaryTag check whether the given tag is a binary tag
func binaryTag(tag byte) bool {
return (tag >= BC_BINARY_DIRECT && tag <= INT_DIRECT_MAX) ||
(tag >= BC_BINARY_SHORT && tag <= byte(0x37)) ||
tag == BC_BINARY_CHUNK ||
tag == BC_BINARY
}
/////////////////////////////////////////
// Binary, []byte
/////////////////////////////////////////
// # 8-bit binary data split into 64k chunks
// ::= x41(A) b1 b0 <binary-data> binary # non-final chunk
// ::= x42(B) b1 b0 <binary-data> # final chunk
// ::= [x20-x2f] <binary-data> # binary data of length 0-15
// ::= [x34-x37] <binary-data> # binary data of length 0-1023
func encBinary(b []byte, v []byte) []byte {
var (
length uint16
vLength int
)
if v == nil {
return encByte(b, BC_NULL)
}
vLength = len(v)
for {
if vLength > CHUNK_SIZE {
length = CHUNK_SIZE
b = encByte(b, BC_BINARY_CHUNK, byte(length>>8), byte(length))
} else {
length = uint16(vLength)
if vLength <= int(BINARY_DIRECT_MAX) {
b = encByte(b, byte(int(BC_BINARY_DIRECT)+vLength))
} else if vLength <= int(BINARY_SHORT_MAX) {
b = encByte(b, byte(int(BC_BINARY_SHORT)+vLength>>8), byte(vLength))
} else {
b = encByte(b, BC_BINARY, byte(vLength>>8), byte(vLength))
}
}
b = append(b, v[:length]...)
v = v[length:]
vLength = len(v)
if vLength == 0 {
break
}
}
return b
}
/////////////////////////////////////////
// Binary, []byte
/////////////////////////////////////////
// # 8-bit binary data split into 64k chunks
// ::= x41('A') b1 b0 <binary-data> binary # non-final chunk
// ::= x42('B') b1 b0 <binary-data> # final chunk
// ::= [x20-x2f] <binary-data> # binary data of length 0-15
// ::= [x34-x37] <binary-data> # binary data of length 0-1023
func (d *Decoder) getBinaryLength(tag byte) (int, error) {
var (
err error
buf [2]byte
)
if tag >= BC_BINARY_DIRECT && tag <= INT_DIRECT_MAX { // [0x20, 0x2f]
return int(tag - BC_BINARY_DIRECT), nil
}
if tag >= BC_BINARY_SHORT && tag <= byte(0x37) { // [0x34, 0x37]
_, err = io.ReadFull(d.reader, buf[:1])
if err != nil {
return 0, perrors.WithStack(err)
}
return int(tag-BC_BINARY_SHORT)<<8 + int(buf[0]), nil
}
if tag != BC_BINARY_CHUNK && tag != BC_BINARY {
return 0, perrors.Errorf("illegal binary tag:%d", tag)
}
_, err = io.ReadFull(d.reader, buf[:2])
if err != nil {
return 0, perrors.WithStack(err)
}
return int(buf[0])<<8 + int(buf[1]), nil
}
func (d *Decoder) decBinary(flag int32) ([]byte, error) {
var (
err error
tag byte
length int
)
if flag != TAG_READ {
tag = byte(flag)
} else {
tag, err = d.readBufByte()
if err != nil {
return nil, perrors.WithStack(err)
}
}
if tag == BC_NULL {
return []byte(""), nil
}
data := make([]byte, 0, 128)
bufp := gxbytes.AcquireBytes(65536)
defer gxbytes.ReleaseBytes(bufp)
buf := *bufp
for {
length, err = d.getBinaryLength(tag)
if err != nil {
return nil, perrors.WithStack(err)
}
_, err = io.ReadFull(d.reader, buf[:length])
if err != nil {
return nil, perrors.WithStack(err)
}
data = append(data, buf[:length]...)
if tag != BC_BINARY_CHUNK {
break
}
tag, err = d.readBufByte()
if err != nil {
return nil, perrors.WithStack(err)
}
}
return data, nil
}