forked from quic-go/quic-go
implement a function to encode a varint using a fixed length
This commit is contained in:
@@ -83,6 +83,34 @@ func WriteVarInt(b *bytes.Buffer, i uint64) {
|
||||
}
|
||||
}
|
||||
|
||||
// WriteVarIntWithLen writes a number in the QUIC varint format, with the desired length.
|
||||
func WriteVarIntWithLen(b *bytes.Buffer, i uint64, length protocol.ByteCount) {
|
||||
if length != 1 && length != 2 && length != 4 && length != 8 {
|
||||
panic("invalid varint length")
|
||||
}
|
||||
l := VarIntLen(i)
|
||||
if l == length {
|
||||
WriteVarInt(b, i)
|
||||
return
|
||||
}
|
||||
if l > length {
|
||||
panic(fmt.Sprintf("cannot encode %d in %d bytes", i, length))
|
||||
}
|
||||
if length == 2 {
|
||||
b.WriteByte(0b01000000)
|
||||
} else if length == 4 {
|
||||
b.WriteByte(0b10000000)
|
||||
} else if length == 8 {
|
||||
b.WriteByte(0b11000000)
|
||||
}
|
||||
for j := protocol.ByteCount(1); j < length-l; j++ {
|
||||
b.WriteByte(0)
|
||||
}
|
||||
for j := protocol.ByteCount(0); j < l; j++ {
|
||||
b.WriteByte(uint8(i >> (8 * (l - 1 - j))))
|
||||
}
|
||||
}
|
||||
|
||||
// VarIntLen determines the number of bytes that will be needed to write a number
|
||||
func VarIntLen(i uint64) protocol.ByteCount {
|
||||
if i <= maxVarInt1 {
|
||||
|
||||
@@ -10,7 +10,7 @@ import (
|
||||
var _ = Describe("Varint encoding / decoding", func() {
|
||||
Context("decoding", func() {
|
||||
It("reads a 1 byte number", func() {
|
||||
b := bytes.NewReader([]byte{25}) // 00011001
|
||||
b := bytes.NewReader([]byte{0b00011001})
|
||||
val, err := ReadVarInt(b)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(val).To(Equal(uint64(25)))
|
||||
@@ -18,7 +18,7 @@ var _ = Describe("Varint encoding / decoding", func() {
|
||||
})
|
||||
|
||||
It("reads a number that is encoded too long", func() {
|
||||
b := bytes.NewReader([]byte{0x40, 0x25}) // first byte: 01000000
|
||||
b := bytes.NewReader([]byte{0b01000000, 0x25})
|
||||
val, err := ReadVarInt(b)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(val).To(Equal(uint64(37)))
|
||||
@@ -26,7 +26,7 @@ var _ = Describe("Varint encoding / decoding", func() {
|
||||
})
|
||||
|
||||
It("reads a 2 byte number", func() {
|
||||
b := bytes.NewReader([]byte{0x7b, 0xbd}) // first byte: 01111011
|
||||
b := bytes.NewReader([]byte{0b01111011, 0xbd})
|
||||
val, err := ReadVarInt(b)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(val).To(Equal(uint64(15293)))
|
||||
@@ -34,7 +34,7 @@ var _ = Describe("Varint encoding / decoding", func() {
|
||||
})
|
||||
|
||||
It("reads a 4 byte number", func() {
|
||||
b := bytes.NewReader([]byte{0x9d, 0x7f, 0x3e, 0x7d}) // first byte: 10011011
|
||||
b := bytes.NewReader([]byte{0b10011101, 0x7f, 0x3e, 0x7d})
|
||||
val, err := ReadVarInt(b)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(val).To(Equal(uint64(494878333)))
|
||||
@@ -42,7 +42,7 @@ var _ = Describe("Varint encoding / decoding", func() {
|
||||
})
|
||||
|
||||
It("reads an 8 byte number", func() {
|
||||
b := bytes.NewReader([]byte{0xc2, 0x19, 0x7c, 0x5e, 0xff, 0x14, 0xe8, 0x8c}) // first byte: 10000010
|
||||
b := bytes.NewReader([]byte{0b11000010, 0x19, 0x7c, 0x5e, 0xff, 0x14, 0xe8, 0x8c})
|
||||
val, err := ReadVarInt(b)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(val).To(Equal(uint64(151288809941952652)))
|
||||
@@ -51,81 +51,135 @@ var _ = Describe("Varint encoding / decoding", func() {
|
||||
})
|
||||
|
||||
Context("encoding", func() {
|
||||
It("writes a 1 byte number", func() {
|
||||
b := &bytes.Buffer{}
|
||||
WriteVarInt(b, 37)
|
||||
Expect(b.Bytes()).To(Equal([]byte{0x25}))
|
||||
Context("with minimal length", func() {
|
||||
It("writes a 1 byte number", func() {
|
||||
b := &bytes.Buffer{}
|
||||
WriteVarInt(b, 37)
|
||||
Expect(b.Bytes()).To(Equal([]byte{0x25}))
|
||||
})
|
||||
|
||||
It("writes the maximum 1 byte number in 1 byte", func() {
|
||||
b := &bytes.Buffer{}
|
||||
WriteVarInt(b, maxVarInt1)
|
||||
Expect(b.Bytes()).To(Equal([]byte{0b00111111}))
|
||||
})
|
||||
|
||||
It("writes the minimum 2 byte number in 2 bytes", func() {
|
||||
b := &bytes.Buffer{}
|
||||
WriteVarInt(b, maxVarInt1+1)
|
||||
Expect(b.Bytes()).To(Equal([]byte{0x40, maxVarInt1 + 1}))
|
||||
})
|
||||
|
||||
It("writes a 2 byte number", func() {
|
||||
b := &bytes.Buffer{}
|
||||
WriteVarInt(b, 15293)
|
||||
Expect(b.Bytes()).To(Equal([]byte{0b01000000 ^ 0x3b, 0xbd}))
|
||||
})
|
||||
|
||||
It("writes the maximum 2 byte number in 2 bytes", func() {
|
||||
b := &bytes.Buffer{}
|
||||
WriteVarInt(b, maxVarInt2)
|
||||
Expect(b.Bytes()).To(Equal([]byte{0b01111111, 0xff}))
|
||||
})
|
||||
|
||||
It("writes the minimum 4 byte number in 4 bytes", func() {
|
||||
b := &bytes.Buffer{}
|
||||
WriteVarInt(b, maxVarInt2+1)
|
||||
Expect(b.Len()).To(Equal(4))
|
||||
num, err := ReadVarInt(b)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(num).To(Equal(uint64(maxVarInt2 + 1)))
|
||||
})
|
||||
|
||||
It("writes a 4 byte number", func() {
|
||||
b := &bytes.Buffer{}
|
||||
WriteVarInt(b, 494878333)
|
||||
Expect(b.Bytes()).To(Equal([]byte{0b10000000 ^ 0x1d, 0x7f, 0x3e, 0x7d}))
|
||||
})
|
||||
|
||||
It("writes the maximum 4 byte number in 4 bytes", func() {
|
||||
b := &bytes.Buffer{}
|
||||
WriteVarInt(b, maxVarInt4)
|
||||
Expect(b.Bytes()).To(Equal([]byte{0b10111111, 0xff, 0xff, 0xff}))
|
||||
})
|
||||
|
||||
It("writes the minimum 8 byte number in 8 bytes", func() {
|
||||
b := &bytes.Buffer{}
|
||||
WriteVarInt(b, maxVarInt4+1)
|
||||
Expect(b.Len()).To(Equal(8))
|
||||
num, err := ReadVarInt(b)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(num).To(Equal(uint64(maxVarInt4 + 1)))
|
||||
})
|
||||
|
||||
It("writes an 8 byte number", func() {
|
||||
b := &bytes.Buffer{}
|
||||
WriteVarInt(b, 151288809941952652)
|
||||
Expect(b.Bytes()).To(Equal([]byte{0xc2, 0x19, 0x7c, 0x5e, 0xff, 0x14, 0xe8, 0x8c}))
|
||||
})
|
||||
|
||||
It("writes the maximum 8 byte number in 8 bytes", func() {
|
||||
b := &bytes.Buffer{}
|
||||
WriteVarInt(b, maxVarInt8)
|
||||
Expect(b.Bytes()).To(Equal([]byte{0xff /* 11111111 */, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}))
|
||||
})
|
||||
|
||||
It("panics when given a too large number (> 62 bit)", func() {
|
||||
Expect(func() { WriteVarInt(&bytes.Buffer{}, maxVarInt8+1) }).Should(Panic())
|
||||
})
|
||||
})
|
||||
|
||||
It("writes the maximum 1 byte number in 1 byte", func() {
|
||||
b := &bytes.Buffer{}
|
||||
WriteVarInt(b, maxVarInt1)
|
||||
Expect(b.Bytes()).To(Equal([]byte{0x3f /* 00111111 */}))
|
||||
})
|
||||
Context("with fixed length", func() {
|
||||
It("panics when given an invalid length", func() {
|
||||
Expect(func() { WriteVarIntWithLen(&bytes.Buffer{}, 25, 3) }).Should(Panic())
|
||||
})
|
||||
|
||||
It("writes the minimum 2 byte number in 2 bytes", func() {
|
||||
b := &bytes.Buffer{}
|
||||
WriteVarInt(b, maxVarInt1+1)
|
||||
Expect(b.Bytes()).To(Equal([]byte{0x40, maxVarInt1 + 1}))
|
||||
})
|
||||
It("panics when given a too short length", func() {
|
||||
Expect(func() { WriteVarIntWithLen(&bytes.Buffer{}, maxVarInt1+1, 1) }).Should(Panic())
|
||||
Expect(func() { WriteVarIntWithLen(&bytes.Buffer{}, maxVarInt2+1, 2) }).Should(Panic())
|
||||
Expect(func() { WriteVarIntWithLen(&bytes.Buffer{}, maxVarInt4+1, 4) }).Should(Panic())
|
||||
})
|
||||
|
||||
It("writes a 2 byte number", func() {
|
||||
b := &bytes.Buffer{}
|
||||
WriteVarInt(b, 15293)
|
||||
Expect(b.Bytes()).To(Equal([]byte{0x7b, 0xbd}))
|
||||
})
|
||||
It("writes a 1-byte number in minimal encoding", func() {
|
||||
b := &bytes.Buffer{}
|
||||
WriteVarIntWithLen(b, 37, 1)
|
||||
Expect(b.Bytes()).To(Equal([]byte{0x25}))
|
||||
})
|
||||
|
||||
It("writes the maximum 2 byte number in 2 bytes", func() {
|
||||
b := &bytes.Buffer{}
|
||||
WriteVarInt(b, maxVarInt2)
|
||||
Expect(b.Bytes()).To(Equal([]byte{0x7f /* 01111111 */, 0xff}))
|
||||
})
|
||||
It("writes a 1-byte number in 2 bytes", func() {
|
||||
b := &bytes.Buffer{}
|
||||
WriteVarIntWithLen(b, 37, 2)
|
||||
Expect(b.Bytes()).To(Equal([]byte{0b01000000, 0x25}))
|
||||
Expect(ReadVarInt(b)).To(BeEquivalentTo(37))
|
||||
})
|
||||
|
||||
It("writes the minimum 4 byte number in 4 bytes", func() {
|
||||
b := &bytes.Buffer{}
|
||||
WriteVarInt(b, maxVarInt2+1)
|
||||
Expect(b.Len()).To(Equal(4))
|
||||
num, err := ReadVarInt(b)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(num).To(Equal(uint64(maxVarInt2 + 1)))
|
||||
})
|
||||
It("writes a 1-byte number in 4 bytes", func() {
|
||||
b := &bytes.Buffer{}
|
||||
WriteVarIntWithLen(b, 37, 4)
|
||||
Expect(b.Bytes()).To(Equal([]byte{0b10000000, 0, 0, 0x25}))
|
||||
Expect(ReadVarInt(b)).To(BeEquivalentTo(37))
|
||||
})
|
||||
|
||||
It("writes a 4 byte number", func() {
|
||||
b := &bytes.Buffer{}
|
||||
WriteVarInt(b, 494878333)
|
||||
Expect(b.Bytes()).To(Equal([]byte{0x9d, 0x7f, 0x3e, 0x7d}))
|
||||
})
|
||||
It("writes a 1-byte number in 8 bytes", func() {
|
||||
b := &bytes.Buffer{}
|
||||
WriteVarIntWithLen(b, 37, 8)
|
||||
Expect(b.Bytes()).To(Equal([]byte{0b11000000, 0, 0, 0, 0, 0, 0, 0x25}))
|
||||
Expect(ReadVarInt(b)).To(BeEquivalentTo(37))
|
||||
})
|
||||
|
||||
It("writes the maximum 4 byte number in 4 bytes", func() {
|
||||
b := &bytes.Buffer{}
|
||||
WriteVarInt(b, maxVarInt4)
|
||||
Expect(b.Bytes()).To(Equal([]byte{0xbf /* 10111111 */, 0xff, 0xff, 0xff}))
|
||||
})
|
||||
It("writes a 2-byte number in 4 bytes", func() {
|
||||
b := &bytes.Buffer{}
|
||||
WriteVarIntWithLen(b, 15293, 4)
|
||||
Expect(b.Bytes()).To(Equal([]byte{0b10000000, 0, 0x3b, 0xbd}))
|
||||
Expect(ReadVarInt(b)).To(BeEquivalentTo(15293))
|
||||
})
|
||||
|
||||
It("writes the minimum 8 byte number in 8 bytes", func() {
|
||||
b := &bytes.Buffer{}
|
||||
WriteVarInt(b, maxVarInt4+1)
|
||||
Expect(b.Len()).To(Equal(8))
|
||||
num, err := ReadVarInt(b)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(num).To(Equal(uint64(maxVarInt4 + 1)))
|
||||
})
|
||||
|
||||
It("writes an 8 byte number", func() {
|
||||
b := &bytes.Buffer{}
|
||||
WriteVarInt(b, 151288809941952652)
|
||||
Expect(b.Bytes()).To(Equal([]byte{0xc2, 0x19, 0x7c, 0x5e, 0xff, 0x14, 0xe8, 0x8c}))
|
||||
})
|
||||
|
||||
It("writes the maximum 8 byte number in 8 bytes", func() {
|
||||
b := &bytes.Buffer{}
|
||||
WriteVarInt(b, maxVarInt8)
|
||||
Expect(b.Bytes()).To(Equal([]byte{0xff /* 11111111 */, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}))
|
||||
})
|
||||
|
||||
It("panics when given a too large number (> 62 bit)", func() {
|
||||
b := &bytes.Buffer{}
|
||||
Expect(func() { WriteVarInt(b, maxVarInt8+1) }).Should(Panic())
|
||||
It("write a 4-byte number in 8 bytes", func() {
|
||||
b := &bytes.Buffer{}
|
||||
WriteVarIntWithLen(b, 494878333, 8)
|
||||
Expect(b.Bytes()).To(Equal([]byte{0b11000000, 0, 0, 0, 0x1d, 0x7f, 0x3e, 0x7d}))
|
||||
Expect(ReadVarInt(b)).To(BeEquivalentTo(494878333))
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
Reference in New Issue
Block a user