| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103 | package berimport (	"errors"	"fmt"	"io"	"math")func readIdentifier(reader io.Reader) (Identifier, int, error) {	identifier := Identifier{}	read := 0	// identifier byte	b, err := readByte(reader)	if err != nil {		if Debug {			fmt.Printf("error reading identifier byte: %v\n", err)		}		return Identifier{}, read, err	}	read++	identifier.ClassType = Class(b) & ClassBitmask	identifier.TagType = Type(b) & TypeBitmask	if tag := Tag(b) & TagBitmask; tag != HighTag {		// short-form tag		identifier.Tag = tag		return identifier, read, nil	}	// high-tag-number tag	tagBytes := 0	for {		b, err := readByte(reader)		if err != nil {			if Debug {				fmt.Printf("error reading high-tag-number tag byte %d: %v\n", tagBytes, err)			}			return Identifier{}, read, err		}		tagBytes++		read++		// Lowest 7 bits get appended to the tag value (x.690, 8.1.2.4.2.b)		identifier.Tag <<= 7		identifier.Tag |= Tag(b) & HighTagValueBitmask		// First byte may not be all zeros (x.690, 8.1.2.4.2.c)		if tagBytes == 1 && identifier.Tag == 0 {			return Identifier{}, read, errors.New("invalid first high-tag-number tag byte")		}		// Overflow of int64		// TODO: support big int tags?		if tagBytes > 9 {			return Identifier{}, read, errors.New("high-tag-number tag overflow")		}		// Top bit of 0 means this is the last byte in the high-tag-number tag (x.690, 8.1.2.4.2.a)		if Tag(b)&HighTagContinueBitmask == 0 {			break		}	}	return identifier, read, nil}func encodeIdentifier(identifier Identifier) []byte {	b := []byte{0x0}	b[0] |= byte(identifier.ClassType)	b[0] |= byte(identifier.TagType)	if identifier.Tag < HighTag {		// Short-form		b[0] |= byte(identifier.Tag)	} else {		// high-tag-number		b[0] |= byte(HighTag)		tag := identifier.Tag		highBit := uint(63)		for {			if tag&(1<<highBit) != 0 {				break			}			highBit--		}		tagBytes := int(math.Ceil(float64(highBit) / 7.0))		for i := tagBytes - 1; i >= 0; i-- {			offset := uint(i) * 7			mask := Tag(0x7f) << offset			tagByte := (tag & mask) >> offset			if i != 0 {				tagByte |= 0x80			}			b = append(b, byte(tagByte))		}	}	return b}
 |