Refactor CBOR head funcs to remove magic numbers
This commit is contained in:
parent
03575b4950
commit
b75278bc2e
3
cache.go
3
cache.go
@ -276,7 +276,8 @@ func getEncodingStructType(t reflect.Type) (*encodingStructType, error) {
|
||||
copy(flds[i].cborNameByteString, flds[i].cborName)
|
||||
// Reset encoded CBOR type to byte string, preserving the "additional
|
||||
// information" bits:
|
||||
flds[i].cborNameByteString[0] = byte(cborTypeByteString) | (flds[i].cborNameByteString[0] & 0x1f)
|
||||
flds[i].cborNameByteString[0] = byte(cborTypeByteString) |
|
||||
getAdditionalInformation(flds[i].cborNameByteString[0])
|
||||
|
||||
hasKeyAsStr = true
|
||||
}
|
||||
|
||||
69
decode.go
69
decode.go
@ -1311,6 +1311,39 @@ func (t cborType) String() string {
|
||||
}
|
||||
}
|
||||
|
||||
const (
|
||||
// From RFC 8949.3:
|
||||
// The initial byte of each encoded data item contains both information about the major type
|
||||
// (the high-order 3 bits, described in Section 3.1) and additional information
|
||||
// (the low-order 5 bits).
|
||||
|
||||
// typeMask is used to extract major type in initial byte of encoded data item.
|
||||
typeMask = 0xe0
|
||||
|
||||
// additionalInformationMask is used to extract additional information in initial byte of encoded data item.
|
||||
additionalInformationMask = 0x1f
|
||||
)
|
||||
|
||||
func getType(b byte) cborType {
|
||||
return cborType(b & typeMask)
|
||||
}
|
||||
|
||||
func getAdditionalInformation(b byte) byte {
|
||||
return b & additionalInformationMask
|
||||
}
|
||||
|
||||
func parseInitialByte(b byte) (t cborType, ai byte) {
|
||||
return getType(b), getAdditionalInformation(b)
|
||||
}
|
||||
|
||||
const (
|
||||
maxAdditionalInformationWithoutArgument = 23
|
||||
additionalInformationWith1ByteArgument = 24
|
||||
additionalInformationWith2ByteArgument = 25
|
||||
additionalInformationWith4ByteArgument = 26
|
||||
additionalInformationWith8ByteArgument = 27
|
||||
)
|
||||
|
||||
const (
|
||||
selfDescribedCBORTagNum = 55799
|
||||
expectedLaterEncodingBase64URLTagNum = 21
|
||||
@ -2791,32 +2824,38 @@ func (d *decoder) skip() {
|
||||
|
||||
// getHead assumes data is well-formed, and does not perform bounds checking.
|
||||
func (d *decoder) getHead() (t cborType, ai byte, val uint64) {
|
||||
t = cborType(d.data[d.off] & 0xe0)
|
||||
ai = d.data[d.off] & 0x1f
|
||||
t, ai = parseInitialByte(d.data[d.off])
|
||||
val = uint64(ai)
|
||||
d.off++
|
||||
|
||||
if ai < 24 {
|
||||
if ai <= maxAdditionalInformationWithoutArgument {
|
||||
return
|
||||
}
|
||||
if ai == 24 {
|
||||
|
||||
if ai == additionalInformationWith1ByteArgument {
|
||||
val = uint64(d.data[d.off])
|
||||
d.off++
|
||||
return
|
||||
}
|
||||
if ai == 25 {
|
||||
val = uint64(binary.BigEndian.Uint16(d.data[d.off : d.off+2]))
|
||||
d.off += 2
|
||||
|
||||
if ai == additionalInformationWith2ByteArgument {
|
||||
const argumentSize = 2
|
||||
val = uint64(binary.BigEndian.Uint16(d.data[d.off : d.off+argumentSize]))
|
||||
d.off += argumentSize
|
||||
return
|
||||
}
|
||||
if ai == 26 {
|
||||
val = uint64(binary.BigEndian.Uint32(d.data[d.off : d.off+4]))
|
||||
d.off += 4
|
||||
|
||||
if ai == additionalInformationWith4ByteArgument {
|
||||
const argumentSize = 4
|
||||
val = uint64(binary.BigEndian.Uint32(d.data[d.off : d.off+argumentSize]))
|
||||
d.off += argumentSize
|
||||
return
|
||||
}
|
||||
if ai == 27 {
|
||||
val = binary.BigEndian.Uint64(d.data[d.off : d.off+8])
|
||||
d.off += 8
|
||||
|
||||
if ai == additionalInformationWith8ByteArgument {
|
||||
const argumentSize = 8
|
||||
val = binary.BigEndian.Uint64(d.data[d.off : d.off+argumentSize])
|
||||
d.off += argumentSize
|
||||
return
|
||||
}
|
||||
return
|
||||
@ -2849,7 +2888,7 @@ func (d *decoder) reset(data []byte) {
|
||||
}
|
||||
|
||||
func (d *decoder) nextCBORType() cborType {
|
||||
return cborType(d.data[d.off] & 0xe0)
|
||||
return getType(d.data[d.off])
|
||||
}
|
||||
|
||||
func (d *decoder) nextCBORNil() bool {
|
||||
@ -3069,7 +3108,7 @@ func convertByteSliceToByteString(v interface{}) (interface{}, bool) {
|
||||
|
||||
// validBuiltinTag checks that supported built-in tag numbers are followed by expected content types.
|
||||
func validBuiltinTag(tagNum uint64, contentHead byte) error {
|
||||
t := cborType(contentHead & 0xe0)
|
||||
t := getType(contentHead)
|
||||
switch tagNum {
|
||||
case 0:
|
||||
// Tag content (date/time text string in RFC 3339 format) must be string type.
|
||||
|
||||
46
encode.go
46
encode.go
@ -1642,34 +1642,46 @@ func encodeTag(e *bytes.Buffer, em *encMode, v reflect.Value) error {
|
||||
|
||||
// encodeHead writes CBOR head of specified type t and returns number of bytes written.
|
||||
func encodeHead(e *bytes.Buffer, t byte, n uint64) int {
|
||||
if n <= 23 {
|
||||
if n <= maxAdditionalInformationWithoutArgument {
|
||||
const headSize = 1
|
||||
e.WriteByte(t | byte(n))
|
||||
return 1
|
||||
return headSize
|
||||
}
|
||||
|
||||
if n <= math.MaxUint8 {
|
||||
scratch := [2]byte{t | byte(24), byte(n)}
|
||||
e.Write(scratch[:2])
|
||||
return 2
|
||||
const headSize = 2
|
||||
scratch := [headSize]byte{
|
||||
t | byte(additionalInformationWith1ByteArgument),
|
||||
byte(n),
|
||||
}
|
||||
e.Write(scratch[:])
|
||||
return headSize
|
||||
}
|
||||
|
||||
if n <= math.MaxUint16 {
|
||||
var scratch [3]byte
|
||||
scratch[0] = t | byte(25)
|
||||
const headSize = 3
|
||||
var scratch [headSize]byte
|
||||
scratch[0] = t | byte(additionalInformationWith2ByteArgument)
|
||||
binary.BigEndian.PutUint16(scratch[1:], uint16(n))
|
||||
e.Write(scratch[:3])
|
||||
return 3
|
||||
e.Write(scratch[:])
|
||||
return headSize
|
||||
}
|
||||
|
||||
if n <= math.MaxUint32 {
|
||||
var scratch [5]byte
|
||||
scratch[0] = t | byte(26)
|
||||
const headSize = 5
|
||||
var scratch [headSize]byte
|
||||
scratch[0] = t | byte(additionalInformationWith4ByteArgument)
|
||||
binary.BigEndian.PutUint32(scratch[1:], uint32(n))
|
||||
e.Write(scratch[:5])
|
||||
return 5
|
||||
e.Write(scratch[:])
|
||||
return headSize
|
||||
}
|
||||
var scratch [9]byte
|
||||
scratch[0] = t | byte(27)
|
||||
|
||||
const headSize = 9
|
||||
var scratch [headSize]byte
|
||||
scratch[0] = t | byte(additionalInformationWith8ByteArgument)
|
||||
binary.BigEndian.PutUint64(scratch[1:], n)
|
||||
e.Write(scratch[:9])
|
||||
return 9
|
||||
e.Write(scratch[:])
|
||||
return headSize
|
||||
}
|
||||
|
||||
var (
|
||||
|
||||
@ -1388,7 +1388,7 @@ func (n *number3) UnmarshalCBOR(data []byte) (err error) {
|
||||
return fmt.Errorf("wrong tag number %d, want %d", rawTag.Number, 100)
|
||||
}
|
||||
|
||||
if rawTag.Content[0]&0xe0 != 0xa0 {
|
||||
if getType(rawTag.Content[0]) != cborTypeMap {
|
||||
return fmt.Errorf("wrong tag content type, want map")
|
||||
}
|
||||
|
||||
|
||||
52
valid.go
52
valid.go
@ -99,7 +99,7 @@ func (d *decoder) wellformed(allowExtraData bool, checkBuiltinTags bool) error {
|
||||
}
|
||||
|
||||
// wellformedInternal checks data's well-formedness and returns max depth and error.
|
||||
func (d *decoder) wellformedInternal(depth int, checkBuiltinTags bool) (int, error) { // nolint:gocyclo
|
||||
func (d *decoder) wellformedInternal(depth int, checkBuiltinTags bool) (int, error) { //nolint:gocyclo
|
||||
t, ai, val, err := d.wellformedHead()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
@ -194,7 +194,7 @@ func (d *decoder) wellformedInternal(depth int, checkBuiltinTags bool) (int, err
|
||||
Message: "bignum",
|
||||
}
|
||||
}
|
||||
if cborType(d.data[d.off]&0xe0) != cborTypeTag {
|
||||
if getType(d.data[d.off]) != cborTypeTag {
|
||||
break
|
||||
}
|
||||
if _, _, tagNum, err = d.wellformedHead(); err != nil {
|
||||
@ -224,11 +224,11 @@ func (d *decoder) wellformedIndefiniteString(t cborType, depth int, checkBuiltin
|
||||
break
|
||||
}
|
||||
// Peek ahead to get next type and indefinite length status.
|
||||
nt := cborType(d.data[d.off] & 0xe0)
|
||||
nt, ai := parseInitialByte(d.data[d.off])
|
||||
if t != nt {
|
||||
return 0, &SyntaxError{"cbor: wrong element type " + nt.String() + " for indefinite-length " + t.String()}
|
||||
}
|
||||
if (d.data[d.off] & 0x1f) == 31 {
|
||||
if ai == 31 {
|
||||
return 0, &SyntaxError{"cbor: indefinite-length " + t.String() + " chunk is not definite-length"}
|
||||
}
|
||||
if depth, err = d.wellformedInternal(depth, checkBuiltinTags); err != nil {
|
||||
@ -281,16 +281,18 @@ func (d *decoder) wellformedHead() (t cborType, ai byte, val uint64, err error)
|
||||
return 0, 0, 0, io.ErrUnexpectedEOF
|
||||
}
|
||||
|
||||
t = cborType(d.data[d.off] & 0xe0)
|
||||
ai = d.data[d.off] & 0x1f
|
||||
t, ai = parseInitialByte(d.data[d.off])
|
||||
val = uint64(ai)
|
||||
d.off++
|
||||
dataLen--
|
||||
|
||||
if ai < 24 {
|
||||
if ai <= maxAdditionalInformationWithoutArgument {
|
||||
return t, ai, val, nil
|
||||
}
|
||||
if ai == 24 {
|
||||
if dataLen < 2 {
|
||||
|
||||
if ai == additionalInformationWith1ByteArgument {
|
||||
const argumentSize = 1
|
||||
if dataLen < argumentSize {
|
||||
return 0, 0, 0, io.ErrUnexpectedEOF
|
||||
}
|
||||
val = uint64(d.data[d.off])
|
||||
@ -300,12 +302,14 @@ func (d *decoder) wellformedHead() (t cborType, ai byte, val uint64, err error)
|
||||
}
|
||||
return t, ai, val, nil
|
||||
}
|
||||
if ai == 25 {
|
||||
if dataLen < 3 {
|
||||
|
||||
if ai == additionalInformationWith2ByteArgument {
|
||||
const argumentSize = 2
|
||||
if dataLen < argumentSize {
|
||||
return 0, 0, 0, io.ErrUnexpectedEOF
|
||||
}
|
||||
val = uint64(binary.BigEndian.Uint16(d.data[d.off : d.off+2]))
|
||||
d.off += 2
|
||||
val = uint64(binary.BigEndian.Uint16(d.data[d.off : d.off+argumentSize]))
|
||||
d.off += argumentSize
|
||||
if t == cborTypePrimitives {
|
||||
if err := d.acceptableFloat(float64(float16.Frombits(uint16(val)).Float32())); err != nil {
|
||||
return 0, 0, 0, err
|
||||
@ -313,12 +317,14 @@ func (d *decoder) wellformedHead() (t cborType, ai byte, val uint64, err error)
|
||||
}
|
||||
return t, ai, val, nil
|
||||
}
|
||||
if ai == 26 {
|
||||
if dataLen < 5 {
|
||||
|
||||
if ai == additionalInformationWith4ByteArgument {
|
||||
const argumentSize = 4
|
||||
if dataLen < argumentSize {
|
||||
return 0, 0, 0, io.ErrUnexpectedEOF
|
||||
}
|
||||
val = uint64(binary.BigEndian.Uint32(d.data[d.off : d.off+4]))
|
||||
d.off += 4
|
||||
val = uint64(binary.BigEndian.Uint32(d.data[d.off : d.off+argumentSize]))
|
||||
d.off += argumentSize
|
||||
if t == cborTypePrimitives {
|
||||
if err := d.acceptableFloat(float64(math.Float32frombits(uint32(val)))); err != nil {
|
||||
return 0, 0, 0, err
|
||||
@ -326,12 +332,14 @@ func (d *decoder) wellformedHead() (t cborType, ai byte, val uint64, err error)
|
||||
}
|
||||
return t, ai, val, nil
|
||||
}
|
||||
if ai == 27 {
|
||||
if dataLen < 9 {
|
||||
|
||||
if ai == additionalInformationWith8ByteArgument {
|
||||
const argumentSize = 8
|
||||
if dataLen < argumentSize {
|
||||
return 0, 0, 0, io.ErrUnexpectedEOF
|
||||
}
|
||||
val = binary.BigEndian.Uint64(d.data[d.off : d.off+8])
|
||||
d.off += 8
|
||||
val = binary.BigEndian.Uint64(d.data[d.off : d.off+argumentSize])
|
||||
d.off += argumentSize
|
||||
if t == cborTypePrimitives {
|
||||
if err := d.acceptableFloat(math.Float64frombits(val)); err != nil {
|
||||
return 0, 0, 0, err
|
||||
@ -339,6 +347,7 @@ func (d *decoder) wellformedHead() (t cborType, ai byte, val uint64, err error)
|
||||
}
|
||||
return t, ai, val, nil
|
||||
}
|
||||
|
||||
if ai == 31 {
|
||||
switch t {
|
||||
case cborTypePositiveInt, cborTypeNegativeInt, cborTypeTag:
|
||||
@ -348,6 +357,7 @@ func (d *decoder) wellformedHead() (t cborType, ai byte, val uint64, err error)
|
||||
}
|
||||
return t, ai, val, nil
|
||||
}
|
||||
|
||||
// ai == 28, 29, 30
|
||||
return 0, 0, 0, &SyntaxError{"cbor: invalid additional information " + strconv.Itoa(int(ai)) + " for type " + t.String()}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user