How to use the varint and zigzag encoder
- Choose Numbers to bytes or Bytes to numbers.
- Pick the format: unsigned varint, zigzag varint or signed LEB128.
- To encode, enter whole numbers, one per line or separated by spaces or commas. Hex numbers such as 0xFF are accepted.
- To decode, paste hex bytes such as AC 02. Read the numbers and bytes in the table.
Formula
split the number into groups of 7 bits, least significant group first
write each group as a byte, with the top bit set on every byte except the last
zigzag: n >= 0 gives 2n, n < 0 gives -2n - 1
signed LEB128: stop when the remaining bits all equal the sign bit of the last group
Unsigned varints from Protocol Buffers and unsigned LEB128 use the same bytes. The range is 0 to 18,446,744,073,709,551,615 for unsigned and -9,223,372,036,854,775,808 to 9,223,372,036,854,775,807 for signed values.
Small numbers use one or two bytes
The numbers 1, 127, 128, 300 and 16,384 encode as 01, 7F, 80 01, AC 02 and 80 80 01. Nine bytes carry five numbers. The number 300 is 100101100 in binary. Its low seven bits, 0101100, become AC after the continuation bit is added, and the remaining bits, 10, become 02.
In zigzag form, 0, -1, 1 and -2 become 0, 1, 2 and 3, so they take one byte each. The largest 32 bit values are longer: 2,147,483,647 maps to 4,294,967,294 and is written FE FF FF FF 0F, five bytes. Signed LEB128 writes -2 as 7E, 127 as FF 00 and -128 as 80 7F.
Why zigzag exists
A plain varint writes a negative number as a huge unsigned one, so in Protocol Buffers a negative int64 takes 10 bytes. Zigzag encoding interleaves positive and negative numbers so that small values of either sign give small codes. It is used for the sint32 and sint64 field types.
Signed LEB128 handles negative numbers a different way, by sign extension, and is used in formats such as DWARF and WebAssembly. The two are not interchangeable, so choose the one your format specifies.
Checking real data
Decode mode reads a stream of bytes as a series of varints, so you can paste a few bytes from a dump and see the numbers. Open a file as hex with the Hex Viewer to find them. For fixed width integers, see the Byte Order Swap Calculator, and for shifts and masks, try the Bitwise Calculator.
Assumptions and limits
- Values are whole numbers of at most 64 bits.
- A varint is at most 10 bytes long.
- Bytes are entered in hex, with or without spaces.
- At most 200 numbers are encoded at a time.
- The numbers shown when the page opens are examples.
Frequently asked questions
Is a varint the same as LEB128?
For unsigned numbers, yes. Protocol Buffers varints and unsigned LEB128 write the same bytes. Signed numbers differ between zigzag and signed LEB128.
Why does 128 need two bytes?
One byte carries only 7 bits of the number, so it holds 0 to 127. At 128 the number needs an eighth bit, so a second byte is added.
What happens with a cut-off byte stream?
If the last byte still has its top bit set, the number is incomplete. The page says the last value is cut off instead of guessing.
Can I decode bytes with a different format than I encoded?
You can, but the numbers will be different. The same bytes mean different values as unsigned, zigzag and signed LEB128, so use the format of your source.