Class: Daybreak::Format

Inherits:
Object
  • Object
show all
Defined in:
lib/daybreak/format.rb

Overview

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

Constant Summary collapse

MAGIC =

Magic string of the file header

'DAYBREAK'
VERSION =

Database file format version

1
DELETE =

Special value size used for deleted records

(1 << 32) - 1

Instance Method Summary collapse

Instance Method Details

#crc32(s) ⇒ Fixnum (protected)

Compute crc32 of string

Parameters:

  • s (String)

    a string

Returns:

  • (Fixnum)


69
70
71
# File 'lib/daybreak/format.rb', line 69

def crc32(s)
  [Zlib.crc32(s, 0)].pack('N')
end

#dump(record) ⇒ String

Serialize record and return string

Parameters:

  • record (Array)

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

Returns:

  • (String)

    serialized record



25
26
27
28
29
30
31
32
33
# File 'lib/daybreak/format.rb', line 25

def dump(record)
  data =
    if record.size == 1
      [record[0].bytesize, DELETE].pack('NN') << record[0]
    else
      [record[0].bytesize, record[1].bytesize].pack('NN') << record[0] << record[1]
    end
  data << crc32(data)
end

#headerString

Return database header as string

Returns:

  • (String)

    database file header



18
19
20
# File 'lib/daybreak/format.rb', line 18

def header
  MAGIC + [VERSION].pack('n')
end

#parse(buf) {|Array| ... } ⇒ Fixnum

Deserialize records from buffer, and yield them.

Parameters:

  • buf (String)

    the buffer to read from

Yields:

  • (Array)

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

Returns:

  • (Fixnum)

    number of records



39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
# File 'lib/daybreak/format.rb', line 39

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
    raise 'CRC mismatch: your data might be corrupted!' unless buf[n, 4] == crc32(data)
    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) ⇒ Object

Read database header from input stream

Parameters:

  • input (#read)

    the input stream

Returns:

  • void



10
11
12
13
14
# File 'lib/daybreak/format.rb', line 10

def read_header(input)
  raise 'Not a Daybreak database' if input.read(MAGIC.bytesize) != MAGIC
  ver = input.read(2).unpack('n').first
  raise "Expected database version #{VERSION}, got #{ver}" if ver != VERSION
end