class Garcon::Stash::Format

Database format serializer and deserializer. You can create your own implementation of this class and define your own database format!

@api public

Constants

DELETE

Special value size used for deleted records

VERSION

Database file format version (it is a hash after all).

Public Instance Methods

crc32(s) click to toggle source

Compute crc32 of string

@param [String] s a string

@return [Fixnum]

# File lib/garcon/stash/format.rb, line 109
def crc32(s)
  [Zlib.crc32(s, 0)].pack('N')
end
dump(rec) click to toggle source

Serialize record and return string.

@param [Array] rec

an array with [key, value] or [key] if the record is deleted

@return [String] serialized record

# File lib/garcon/stash/format.rb, line 55
def dump(rec)
  data = if rec.size == 1
    [rec[0].bytesize, DELETE].pack('NN') << rec[0]
  else
    [rec[0].bytesize, rec[1].bytesize].pack('NN') << rec[0] << rec[1]
  end
  data << crc32(data)
end
header() click to toggle source

Return database header as string

@return [String] database file header

# File lib/garcon/stash/format.rb, line 44
def header
  MAGIC + [VERSION].pack('n')
end
parse(buf) { |value_size == DELETE ? [data : [data, data| ... } click to toggle source

Deserialize records from buffer, and yield them.

@param [String] buf

the buffer to read from

@yield [Array] block

deserialized record [key, value] or [key] if the record is deleted

@return [Fixnum] number of records

# File lib/garcon/stash/format.rb, line 74
def parse(buf)
  n, count = 0, 0
  while n < buf.size
    key_size, value_size = buf[n, 8].unpack('NN')
    data_size = key_size + 8
    data_size += value_size if value_size != DELETE
    data = buf[n, data_size]
    n += data_size
    unless buf[n, 4] == crc32(data)
      raise 'CRC mismatch: your stash might be corrupted!'
    end
    n += 4
    yield(value_size == DELETE ? [data[8, key_size]] : [data[8, key_size], data[8 + key_size, value_size]])
    count += 1
  end
  count
end
read_header(input) click to toggle source

Read database header from input stream

@param [#read] input

the input stream

@return void

# File lib/garcon/stash/format.rb, line 34
def read_header(input)
  raise 'Not a stash' if input.read(MAGIC.bytesize) != MAGIC
  ver = input.read(2).unpack('n').first
  raise "Expected stash version #{VERSION}, got #{ver}" if ver != VERSION
end