Module: FirefoxJson::JsFile

Defined in:
lib/firefox-json/js_file.rb

Overview

Saves and restores files

Defined Under Namespace

Classes: FileTooLarge

Constant Summary collapse

MOZ_ID =
"mozLz40\0"
MOZ_PREFIX =
MOZ_ID.size + 4
MAX_SIZE =
1 << 32 - 1
OFFSETS =
[1 << 24, 1 << 16, 1 << 8, 1]

Class Method Summary collapse

Class Method Details

.compress(string) ⇒ Object



50
51
52
53
54
55
56
57
58
59
60
61
# File 'lib/firefox-json/js_file.rb', line 50

def self.compress(string)
  size = string.bytesize
  if size > MAX_SIZE
    raise FileTooLarge, 'Content over 4GB!'
  end
  sstr = OFFSETS.map do |offset|
    part = size / offset
    size %= offset
    part
  end.reverse.pack('c*')
  MOZ_ID + sstr + LZ4.block_encode(string)
end

.decompress(string) ⇒ Object



38
39
40
41
42
43
44
45
46
47
48
# File 'lib/firefox-json/js_file.rb', line 38

def self.decompress(string)
  string.force_encoding(Encoding::BINARY)
  size = string[8, 4].bytes.zip(OFFSETS.reverse).map do |byte, offset|
    byte * offset
  end.sum
  string = LZ4.block_decode(string[MOZ_PREFIX..-1])
  if string.bytesize != size
    raise "Expected size #{size} != #{string.bytesize}"
  end
  string.force_encoding(Encoding::UTF_8)
end

.load(string) ⇒ Object



18
19
20
21
22
23
# File 'lib/firefox-json/js_file.rb', line 18

def self.load(string)
  if string[0, MOZ_ID.size] == MOZ_ID
    string = decompress(string)
  end
  Oj.load(string, mode: :strict)
end

.load_file(path) ⇒ Object



14
15
16
# File 'lib/firefox-json/js_file.rb', line 14

def self.load_file(path)
  load(IO.read(path))
end

.save(path, data) ⇒ Object



25
26
27
28
29
30
31
32
33
34
35
36
# File 'lib/firefox-json/js_file.rb', line 25

def self.save(path, data)
  string = Oj.dump(data, mode: :strict)
  if path.end_with?('jsonlz4')
    File.open(path, 'wb') do |file|
      file.write(compress(string))
    end
  else
    File.open(path, 'w') do |file|
      file.write(string)
    end
  end
end