| // Copyright 2026 The Go Authors. All rights reserved. | |
| // Use of this source code is governed by a BSD-style | |
| // license that can be found in the LICENSE file. | |
| // The functions in this file are copied from golang.org/x/net/internal/quic/quicwire. | |
| package http3 | |
| // consumeVarint parses a variable-length integer, reporting its length. | |
| // It returns a negative length upon an error. | |
| // | |
| // https://www.rfc-editor.org/rfc/rfc9000.html#section-16 | |
| func consumeVarint(b []byte) (v uint64, n int) { | |
| if len(b) < 1 { | |
| return 0, -1 | |
| } | |
| b0 := b[0] & 0x3f | |
| switch b[0] >> 6 { | |
| case 0: | |
| return uint64(b0), 1 | |
| case 1: | |
| if len(b) < 2 { | |
| return 0, -1 | |
| } | |
| return uint64(b0)<<8 | uint64(b[1]), 2 | |
| case 2: | |
| if len(b) < 4 { | |
| return 0, -1 | |
| } | |
| return uint64(b0)<<24 | uint64(b[1])<<16 | uint64(b[2])<<8 | uint64(b[3]), 4 | |
| case 3: | |
| if len(b) < 8 { | |
| return 0, -1 | |
| } | |
| return uint64(b0)<<56 | uint64(b[1])<<48 | uint64(b[2])<<40 | uint64(b[3])<<32 | uint64(b[4])<<24 | uint64(b[5])<<16 | uint64(b[6])<<8 | uint64(b[7]), 8 | |
| } | |
| return 0, -1 | |
| } | |
| // consumeVarintInt64 parses a variable-length integer as an int64. | |
| func consumeVarintInt64(b []byte) (v int64, n int) { | |
| u, n := consumeVarint(b) | |
| // QUIC varints are 62-bits large, so this conversion can never overflow. | |
| return int64(u), n | |
| } | |
| // appendVarint appends a variable-length integer to b. | |
| // | |
| // https://www.rfc-editor.org/rfc/rfc9000.html#section-16 | |
| func appendVarint(b []byte, v uint64) []byte { | |
| switch { | |
| case v <= 63: | |
| return append(b, byte(v)) | |
| case v <= 16383: | |
| return append(b, (1<<6)|byte(v>>8), byte(v)) | |
| case v <= 1073741823: | |
| return append(b, (2<<6)|byte(v>>24), byte(v>>16), byte(v>>8), byte(v)) | |
| case v <= 4611686018427387903: | |
| return append(b, (3<<6)|byte(v>>56), byte(v>>48), byte(v>>40), byte(v>>32), byte(v>>24), byte(v>>16), byte(v>>8), byte(v)) | |
| default: | |
| panic("varint too large") | |
| } | |
| } | |
| // sizeVarint returns the size of the variable-length integer encoding of f. | |
| func sizeVarint(v uint64) int { | |
| switch { | |
| case v <= 63: | |
| return 1 | |
| case v <= 16383: | |
| return 2 | |
| case v <= 1073741823: | |
| return 4 | |
| case v <= 4611686018427387903: | |
| return 8 | |
| default: | |
| panic("varint too large") | |
| } | |
| } |