github.com/sagernet/sing@v0.4.0-beta.19.0.20240518125136-f67a0988a636/common/rw/varint.go (about) 1 package rw 2 3 import ( 4 "encoding/binary" 5 "io" 6 7 "github.com/sagernet/sing/common" 8 ) 9 10 type stubByteReader struct { 11 io.Reader 12 } 13 14 func (r stubByteReader) ReadByte() (byte, error) { 15 return ReadByte(r.Reader) 16 } 17 18 func ToByteReader(reader io.Reader) io.ByteReader { 19 if byteReader, ok := reader.(io.ByteReader); ok { 20 return byteReader 21 } 22 return &stubByteReader{reader} 23 } 24 25 func ReadUVariant(reader io.Reader) (uint64, error) { 26 return binary.ReadUvarint(ToByteReader(reader)) 27 } 28 29 func UVariantLen(x uint64) int { 30 switch { 31 case x < 1<<(7*1): 32 return 1 33 case x < 1<<(7*2): 34 return 2 35 case x < 1<<(7*3): 36 return 3 37 case x < 1<<(7*4): 38 return 4 39 case x < 1<<(7*5): 40 return 5 41 case x < 1<<(7*6): 42 return 6 43 case x < 1<<(7*7): 44 return 7 45 case x < 1<<(7*8): 46 return 8 47 case x < 1<<(7*9): 48 return 9 49 default: 50 return 10 51 } 52 } 53 54 func WriteUVariant(writer io.Writer, value uint64) error { 55 var b [8]byte 56 return common.Error(writer.Write(b[:binary.PutUvarint(b[:], value)])) 57 } 58 59 func WriteVString(writer io.Writer, value string) error { 60 err := WriteUVariant(writer, uint64(len(value))) 61 if err != nil { 62 return err 63 } 64 return WriteString(writer, value) 65 } 66 67 func ReadVString(reader io.Reader) (string, error) { 68 length, err := binary.ReadUvarint(ToByteReader(reader)) 69 if err != nil { 70 return "", err 71 } 72 value, err := ReadBytes(reader, int(length)) 73 if err != nil { 74 return "", err 75 } 76 return string(value), nil 77 }