Here is a description of SCALE compact-encoding. As you mentioned in your question, there are basically 4 variants indicated by the flags from the 2 least-significant bits.
Effectively when decoding the first byte of SCALE compact, it would be in the form 0bxxxxxxyy
where yy
are the flags and the most-significant 6 xxxxxx
are the bits containing the value in the first byte.
Interpreting the lest-significant binary flags you can have lengths of 1, 2, 4 & 4+ bytes -
00
This is a single-byte version. To extract the value, you would do byte1 >> 2
. As an example 0b00000100
would be 4 >> 2 = 1
01
This is a double-byte version. To extract the value, you would do (byte1 + (byte2 << 8)) >> 2
. As an example 0b11111101 0b00000111
would be (253 + (7 << 8)) >> 2 = 511
10
This is the 4 byte version. For extracting the value, it ends up being (byte1 + (byte2 << 8) + (byte3 << 16) + (byte4 << 24)) >> 2
. An example would be 0b11111110 0b11111111 0b11111111 0b11111111
which would be (254 + (255 << 8) + (255 << 16) + (255 << 24)) >> 2 = 1073741823
11
This is the n-byte version. The first byte + 4 details the number of bytes following. So Assuming a first byte of 0b00000111
it would yield 5 bytes, i.e. (7 >> 2) + 4 = 5
. The next 5 bytes would therefore be the LE encoded value.
Depending on your toolset and language, be aware that some of these are very large numbers and could overflow the "normal" representation. So it is recommended to use big integer support for your environment especially when converting the very large values.
(And example of this is JS where the maximum integer is 2^53 - 1. So in this specific case you may want to use BigInt or alternatives when converting. Other languages would have other limits, bear those in mind.)