Task: Variable-length quantity



C#: namespace Vlq
{
  using System;
  using System.Collections.Generic;
  using System.Linq;

  public static class VarLenQuantity
  {
    public static ulong ToVlq(ulong integer)
    {
      var array = new byte[8];
      var buffer = ToVlqCollection(integer)
        .SkipWhile(b => b == 0)
        .Reverse()
        .ToArray();
      Array.Copy(buffer, array, buffer.Length);
      return BitConverter.ToUInt64(array, 0);
    }

    public static ulong FromVlq(ulong integer)
    {
      var collection = BitConverter.GetBytes(integer).Reverse();
      return FromVlqCollection(collection);
    }

    public static IEnumerable<byte> ToVlqCollection(ulong integer)
    {
      if (integer > Math.Pow(2, 56))
        throw new OverflowException("Integer exceeds max value.");

      var index = 7;
      var significantBitReached = false;
      var mask = 0x7fUL << (index * 7);
      while (index >= 0)
      {
        var buffer = (mask & integer);
        if (buffer > 0 || significantBitReached)
        {
          significantBitReached = true;
          buffer >>= index * 7;
          if (index > 0)
            buffer |= 0x80;
          yield return (byte)buffer;
        }
        mask >>= 7;
        index--;
      }
    }


    public static ulong FromVlqCollection(IEnumerable<byte> vlq)
    {
      ulong integer = 0;
      var significantBitReached = false;

      using (var enumerator = vlq.GetEnumerator())
      {
        int index = 0;
        while (enumerator.MoveNext())
        {
          var buffer = enumerator.Current;
          if (buffer > 0 || significantBitReached)
          {
            significantBitReached = true;
            integer <<= 7;
            integer |= (buffer & 0x7fUL);
          }

          if (++index == 8 || (significantBitReached && (buffer & 0x80) != 0x80))
            break;
        }
      }
      return integer;
    }

    public static void Main()
    {
      var integers = new ulong[] { 0x7fUL << 7 * 7, 0x80, 0x2000, 0x3FFF, 0x4000, 0x200000, 0x1fffff };

      foreach (var original in integers)
      {
        Console.WriteLine("Original: 0x{0:X}", original);

        
        var seq = ToVlqCollection(original);
        Console.WriteLine("Sequence: 0x{0}", seq.Select(b => b.ToString("X2")).Aggregate(string.Concat));

        var decoded = FromVlqCollection(seq);
        Console.WriteLine("Decoded: 0x{0:X}", decoded);

        
        var encoded = ToVlq(original);
        Console.WriteLine("Encoded: 0x{0:X}", encoded);

        decoded = FromVlq(encoded);
        Console.WriteLine("Decoded: 0x{0:X}", decoded);

        Console.WriteLine();
      }
      Console.WriteLine("Press any key to continue...");
      Console.ReadKey();
    }
  }
}





Python: def tobits(n, _group=8, _sep='_', _pad=False):
    'Express n as binary bits with separator'
    bits = '{0:b}'.format(n)[::-1]
    if _pad:
        bits = '{0:0{1}b}'.format(n,
                                  ((_group+len(bits)-1)//_group)*_group)[::-1]
        answer = _sep.join(bits[i:i+_group]
                                 for i in range(0, len(bits), _group))[::-1]
        answer = '0'*(len(_sep)-1) + answer
    else:
        answer = _sep.join(bits[i:i+_group]
                           for i in range(0, len(bits), _group))[::-1]
    return answer

def tovlq(n):
    return tobits(n, _group=7, _sep='1_', _pad=True)

def toint(vlq):
    return int(''.join(vlq.split('_1')), 2)    

def vlqsend(vlq):
    for i, byte in enumerate(vlq.split('_')[::-1]):
        print('Sent byte {0:3}: {1: