package leb128import ()const ( maxVarintLen32 = 5 maxVarintLen33 = maxVarintLen32 maxVarintLen64 = 10 int33Mask int64 = 1 << 7 int33Mask2 = ^int33Mask int33Mask3 = 1 << 6 int33Mask4 = 8589934591// 2^33-1 int33Mask5 = 1 << 32 int33Mask6 = int33Mask4 + 1// 2^33 int64Mask3 = 1 << 6 int64Mask4 = ^0)var ( errOverflow32 = errors.New("overflows a 32-bit integer") errOverflow33 = errors.New("overflows a 33-bit integer") errOverflow64 = errors.New("overflows a 64-bit integer"))// EncodeInt32 encodes the signed value into a buffer in LEB128 format//// See https://en.wikipedia.org/wiki/LEB128#Encode_signed_integerfunc ( int32) []byte {returnEncodeInt64(int64())}// EncodeInt64 encodes the signed value into a buffer in LEB128 format//// See https://en.wikipedia.org/wiki/LEB128#Encode_signed_integerfunc ( int64) ( []byte) {for {// Take 7 remaining low-order bits from the value into b. := uint8( & 0x7f)// Extract the sign bit. := uint8( & 0x40) >>= 7// The encoding unsigned numbers is simpler as it only needs to check if the value is non-zero to tell if there // are more bits to encode. Signed is a little more complicated as you have to double-check the sign bit. // If either case, set the high-order bit to tell the reader there are more bytes in this int.if ( != -1 || == 0) && ( != 0 || != 0) { |= 0x80 }// Append b into the buffer = append(, )if &0x80 == 0 {break } }return}// EncodeUint32 encodes the value into a buffer in LEB128 format//// See https://en.wikipedia.org/wiki/LEB128#Encode_unsigned_integerfunc ( uint32) []byte {returnEncodeUint64(uint64())}// EncodeUint64 encodes the value into a buffer in LEB128 format//// See https://en.wikipedia.org/wiki/LEB128#Encode_unsigned_integerfunc ( uint64) ( []byte) {// This is effectively a do/while loop where we take 7 bits of the value and encode them until it is zero.for {// Take 7 remaining low-order bits from the value into b. := uint8( & 0x7f) = >> 7// If there are remaining bits, the value won't be zero: Set the high- // order bit to tell the reader there are more bytes in this uint.if != 0 { |= 0x80 }// Append b into the buffer = append(, )if &0x80 == 0 {return } }}type nextByte func(i int) (byte, error)func ( io.ByteReader) ( uint32, uint64, error) {returndecodeUint32(func( int) (byte, error) { return .ReadByte() })}func ( []byte) ( uint32, uint64, error) {returndecodeUint32(func( int) (byte, error) {if >= len() {return0, io.EOF }return [], nil })}func decodeUint32( nextByte) ( uint32, uint64, error) {// Derived from https://github.com/golang/go/blob/go1.24.0/src/encoding/binary/varint.go // with the modification on the overflow handling tailored for 32-bits.varuint32for := 0; < maxVarintLen32; ++ { , := ()if != nil {return0, 0, }if < 0x80 {// Unused bits must be all zero.if == maxVarintLen32-1 && (&0xf0) > 0 {return0, 0, errOverflow32 }return | uint32()<<, uint64() + 1, nil } |= uint32(&0x7f) << += 7 }return0, 0, errOverflow32}func ( []byte) ( uint64, uint64, error) { := len()if == 0 {return0, 0, io.EOF }// Derived from https://github.com/golang/go/blob/go1.24.0/src/encoding/binary/varint.govaruint64for := 0; < maxVarintLen64; ++ {if >= {return0, 0, io.EOF } := []if < 0x80 {// Unused bits (non first bit) must all be zero.if == maxVarintLen64-1 && > 1 {return0, 0, errOverflow64 }return | uint64()<<, uint64() + 1, nil } |= uint64(&0x7f) << += 7 }return0, 0, errOverflow64}func ( io.ByteReader) ( int32, uint64, error) {returndecodeInt32(func( int) (byte, error) { return .ReadByte() })}func ( []byte) ( int32, uint64, error) {returndecodeInt32(func( int) (byte, error) {if >= len() {return0, io.EOF }return [], nil })}func decodeInt32( nextByte) ( int32, uint64, error) {varintvarbytefor { , = (int())if != nil {return0, 0, fmt.Errorf("readByte failed: %w", ) } |= (int32() & 0x7f) << += 7 ++if &0x80 == 0 {if < 32 && (&0x40) != 0 { |= ^0 << }// Over flow checks. // fixme: can be optimized.if > maxVarintLen32 {return0, 0, errOverflow32 } elseif := & 0b00110000; == maxVarintLen32 && < 0 && != 0b00110000 {return0, 0, errOverflow32 } elseif == maxVarintLen32 && >= 0 && != 0x00 {return0, 0, errOverflow32 }return } }}// DecodeInt33AsInt64 is a special cased decoder for wasm.BlockType which is encoded as a positive signed integer, yet// still needs to fit the 32-bit range of allowed indices. Hence, this is 33, not 32-bit!//// See https://webassembly.github.io/spec/core/binary/instructions.html#control-instructionsfunc ( io.ByteReader) ( int64, uint64, error) {varintvarint64varbytefor < 35 { , = .ReadByte()if != nil {return0, 0, fmt.Errorf("readByte failed: %w", ) } = int64() |= ( & int33Mask2) << += 7 ++if &int33Mask == 0 {break } }// fixme: can be optimizedif < 33 && (&int33Mask3) == int33Mask3 { |= int33Mask4 << } = & int33Mask4// if 33rd bit == 1, we translate it as a corresponding signed-33bit minus valueif &int33Mask5 > 0 { = - int33Mask6 }// Over flow checks. // fixme: can be optimized.if > maxVarintLen33 {return0, 0, errOverflow33 } elseif := & 0b00100000; == maxVarintLen33 && < 0 && != 0b00100000 {return0, 0, errOverflow33 } elseif == maxVarintLen33 && >= 0 && != 0x00 {return0, 0, errOverflow33 }return , , nil}func ( io.ByteReader) ( int64, uint64, error) {returndecodeInt64(func( int) (byte, error) { return .ReadByte() })}func ( []byte) ( int64, uint64, error) {returndecodeInt64(func( int) (byte, error) {if >= len() {return0, io.EOF }return [], nil })}func decodeInt64( nextByte) ( int64, uint64, error) {varintvarbytefor { , = (int())if != nil {return0, 0, fmt.Errorf("readByte failed: %w", ) } |= (int64() & 0x7f) << += 7 ++if &0x80 == 0 {if < 64 && (&int64Mask3) == int64Mask3 { |= int64Mask4 << }// Over flow checks. // fixme: can be optimized.if > maxVarintLen64 {return0, 0, errOverflow64 } elseif := & 0b00111110; == maxVarintLen64 && < 0 && != 0b00111110 {return0, 0, errOverflow64 } elseif == maxVarintLen64 && >= 0 && != 0x00 {return0, 0, errOverflow64 }return } }}
The pages are generated with Goldsv0.8.2. (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu.
PR and bug reports are welcome and can be submitted to the issue list.
Please follow @zigo_101 (reachable from the left QR code) to get the latest news of Golds.