github.com/Psiphon-Labs/psiphon-tunnel-core@v2.0.28+incompatible/psiphon/common/quic/gquic-go/internal/utils/varint.go (about)

     1  package utils
     2  
     3  import (
     4  	"bytes"
     5  	"fmt"
     6  	"io"
     7  
     8  	"github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/quic/gquic-go/internal/protocol"
     9  )
    10  
    11  // taken from the QUIC draft
    12  const (
    13  	maxVarInt1 = 63
    14  	maxVarInt2 = 16383
    15  	maxVarInt4 = 1073741823
    16  	maxVarInt8 = 4611686018427387903
    17  )
    18  
    19  // ReadVarInt reads a number in the QUIC varint format
    20  func ReadVarInt(b io.ByteReader) (uint64, error) {
    21  	firstByte, err := b.ReadByte()
    22  	if err != nil {
    23  		return 0, err
    24  	}
    25  	// the first two bits of the first byte encode the length
    26  	len := 1 << ((firstByte & 0xc0) >> 6)
    27  	b1 := firstByte & (0xff - 0xc0)
    28  	if len == 1 {
    29  		return uint64(b1), nil
    30  	}
    31  	b2, err := b.ReadByte()
    32  	if err != nil {
    33  		return 0, err
    34  	}
    35  	if len == 2 {
    36  		return uint64(b2) + uint64(b1)<<8, nil
    37  	}
    38  	b3, err := b.ReadByte()
    39  	if err != nil {
    40  		return 0, err
    41  	}
    42  	b4, err := b.ReadByte()
    43  	if err != nil {
    44  		return 0, err
    45  	}
    46  	if len == 4 {
    47  		return uint64(b4) + uint64(b3)<<8 + uint64(b2)<<16 + uint64(b1)<<24, nil
    48  	}
    49  	b5, err := b.ReadByte()
    50  	if err != nil {
    51  		return 0, err
    52  	}
    53  	b6, err := b.ReadByte()
    54  	if err != nil {
    55  		return 0, err
    56  	}
    57  	b7, err := b.ReadByte()
    58  	if err != nil {
    59  		return 0, err
    60  	}
    61  	b8, err := b.ReadByte()
    62  	if err != nil {
    63  		return 0, err
    64  	}
    65  	return uint64(b8) + uint64(b7)<<8 + uint64(b6)<<16 + uint64(b5)<<24 + uint64(b4)<<32 + uint64(b3)<<40 + uint64(b2)<<48 + uint64(b1)<<56, nil
    66  }
    67  
    68  // WriteVarInt writes a number in the QUIC varint format
    69  func WriteVarInt(b *bytes.Buffer, i uint64) {
    70  	if i <= maxVarInt1 {
    71  		b.WriteByte(uint8(i))
    72  	} else if i <= maxVarInt2 {
    73  		b.Write([]byte{uint8(i>>8) | 0x40, uint8(i)})
    74  	} else if i <= maxVarInt4 {
    75  		b.Write([]byte{uint8(i>>24) | 0x80, uint8(i >> 16), uint8(i >> 8), uint8(i)})
    76  	} else if i <= maxVarInt8 {
    77  		b.Write([]byte{
    78  			uint8(i>>56) | 0xc0, uint8(i >> 48), uint8(i >> 40), uint8(i >> 32),
    79  			uint8(i >> 24), uint8(i >> 16), uint8(i >> 8), uint8(i),
    80  		})
    81  	} else {
    82  		panic(fmt.Sprintf("%#x doesn't fit into 62 bits", i))
    83  	}
    84  }
    85  
    86  // VarIntLen determines the number of bytes that will be needed to write a number
    87  func VarIntLen(i uint64) protocol.ByteCount {
    88  	if i <= maxVarInt1 {
    89  		return 1
    90  	}
    91  	if i <= maxVarInt2 {
    92  		return 2
    93  	}
    94  	if i <= maxVarInt4 {
    95  		return 4
    96  	}
    97  	if i <= maxVarInt8 {
    98  		return 8
    99  	}
   100  	panic(fmt.Sprintf("%#x doesn't fit into 62 bits", i))
   101  }