Module: SourceMap::VLQ

Defined in:
lib/source_map/vlq.rb

Overview

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

Constant Summary collapse

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
5
VLQ_BASE =

binary: 100000

1 << VLQ_BASE_SHIFT
VLQ_BASE_MASK =

binary: 011111

VLQ_BASE - 1
VLQ_CONTINUATION_BIT =

binary: 100000

VLQ_BASE
BASE64_DIGITS =
'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'.split('')
BASE64_VALUES =
(0..64).inject({}){ |h, i| h.update BASE64_DIGITS[i] => i }

Class Method Summary collapse

Class Method Details

.decode(str) ⇒ Object

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



56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
# 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) ⇒ Object

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



77
78
79
80
81
82
83
84
# 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) ⇒ Object

Returns the base 64 VLQ encoded value.



39
40
41
42
43
44
45
46
47
48
49
50
51
52
# 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