module SourceMap::VLQ

Support for encoding/decoding the variable length quantity format described in the spec at:

docs.google.com/document/d/1U1RGAehQwRypUTovF1KRlpiOFze0b-_2gc6fAH0KY0k/edit

This implementation is heavily based on github.com/mozilla/source-map Copyright 2009-2011, Mozilla Foundation and contributors, BSD

Constants

BASE64_DIGITS
BASE64_VALUES
VLQ_BASE

binary: 100000

VLQ_BASE_MASK

binary: 011111

VLQ_BASE_SHIFT

A single base 64 digit can contain 6 bits of data. For the base 64 variable length quantities we use in the source map spec, the first bit is the sign, the next four bits are the actual value, and the 6th bit is the continuation bit. The continuation bit tells us whether there are more digits in this value following this digit.

Continuation
|    Sign
|    |
V    V
101011
VLQ_CONTINUATION_BIT

binary: 100000

Public Class Methods

decode(str) click to toggle source

Decodes the next base 64 VLQ value from the given string and returns the value and the rest of the string.

# File lib/source_map/vlq.rb, line 56
def self.decode(str)

  vlq = 0
  shift = 0
  continue = true
  chars = str.split('')

  while continue
    char = chars.shift or raise "Expected more digits in base 64 VLQ value."
    digit = base64_decode(char)
    continue = false if (digit & VLQ_CONTINUATION_BIT) == 0
    digit &= VLQ_BASE_MASK
    vlq += digit << shift
    shift += VLQ_BASE_SHIFT
  end

  [from_vlq_signed(vlq), chars.join('')]
end
decode_array(str) click to toggle source

Decode an array of variable length quantities from the given string and return them.

# File lib/source_map/vlq.rb, line 77
def self.decode_array(str)
  output = []
  while str != ''
    int, str = decode(str)
    output << int
  end
  output
end
encode(int) click to toggle source

Returns the base 64 VLQ encoded value.

# File lib/source_map/vlq.rb, line 39
def self.encode(int)

  vlq = to_vlq_signed(int)
  encoded = ""

  begin
    digit = vlq & VLQ_BASE_MASK
    vlq >>= VLQ_BASE_SHIFT
    digit |= VLQ_CONTINUATION_BIT if vlq > 0
    encoded << base64_encode(digit)
  end while vlq > 0

  encoded
end

Protected Class Methods

base64_decode(char) click to toggle source
# File lib/source_map/vlq.rb, line 92
def self.base64_decode(char)
  BASE64_VALUES[char] or raise ArgumentError, "#{char} is not a valid base64 digit"
end
base64_encode(int) click to toggle source
# File lib/source_map/vlq.rb, line 88
def self.base64_encode(int)
  BASE64_DIGITS[int] or raise ArgumentError, "#{int} is not a valid base64 digit"
end
from_vlq_signed(vlq) click to toggle source

Converts to a two's-complement value from a value where the sign bit is placed in the least significant bit. For example, as decimals:

2 (10 binary) becomes 1, 3 (11 binary) becomes -1
4 (100 binary) becomes 2, 5 (101 binary) becomes -2
# File lib/source_map/vlq.rb, line 113
def self.from_vlq_signed(vlq)
  if vlq & 1 == 1
    -(vlq >> 1)
  else
    vlq >> 1
  end
end
to_vlq_signed(int) click to toggle source

Converts from a two's-complement integer to an integer where the sign bit is placed in the least significant bit. For example, as decimals:

1 becomes 2 (10 binary), -1 becomes 3 (11 binary)
2 becomes 4 (100 binary), -2 becomes 5 (101 binary)
# File lib/source_map/vlq.rb, line 100
def self.to_vlq_signed(int)
  if int < 0
    ((-int) << 1) + 1
  else
    int << 1
  end
end