Class: Mmdb::Decoder

Inherits:
Object
  • Object
show all
Defined in:
lib/mmdb/decoder.rb

Defined Under Namespace

Classes: Node

Instance Method Summary collapse

Constructor Details

#initialize(data) ⇒ Decoder

Returns a new instance of Decoder.



5
6
7
# File 'lib/mmdb/decoder.rb', line 5

def initialize(data)
  @data = data
end

Instance Method Details

#decode(position:, base:) ⇒ Object



56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
# File 'lib/mmdb/decoder.rb', line 56

def decode(position:, base:)
  ctrl = data[position + base].ord
  type = ctrl >> 5
  position += 1

  if type == POINTER
    decode_pointer(position, base, ctrl)
  else
    if type == EXTENDED_TYPE
      type = 7 + data[position + base].ord
      position += 1
    end

    size = ctrl & 0x1f
    if size >= 29
      byte_size = size - 29 + 1
      val = fetch(position, base, byte_size)
      position += byte_size
      size = val + SIZE_BASE_VALUES[byte_size]
    end

    case type
    when UTF8
      val = data[position + base, size].encode('utf-8', 'utf-8')
      Node.new(position + size, val)
    when DOUBLE
      val = data[position + base, size].unpack('G')[0]
      Node.new(position + size, val)
    when BYTE
      val = data[position + base, size]
      Node.new(position + size, val)
    when UINT16, UINT32, UINT64, UINT128
      val = fetch(position, base, size)
      Node.new(position + size, val)
    when MAP
      val = size.times.each_with_object({}) do |_, map|
        key_node = decode(position: position, base: base)
        val_node = decode(position: key_node.position, base: base)
        position = val_node.position
        map[key_node.value] = val_node.value
      end
      Node.new(position, val)
    when INT32
      v1 = data[position + base, size].unpack('N')[0]
      bits = size * 8
      val = (v1 & ~(1 << bits)) - (v1 & (1 << bits))
      Node.new(position + size, val)
    when ARRAY
      val = Array.new(size) do
        node = decode(position: position, base: base)
        position = node.position
        node.value
      end
      Node.new(position, val)
    when DATA_CACHE_CONTAINER
      raise 'TODO:'
    when END_MARKER
      Node.new(position, nil)
    when BOOLEAN
      Node.new(position, !size.zero?)
    when FLOAT
      val = data[position + base, size].unpack('g')[0]
      Node.new(position + size, val)
    end
  end
end

#ip_versionObject



23
24
25
# File 'lib/mmdb/decoder.rb', line 23

def ip_version
  ['ip_version']
end

#metadataObject



9
10
11
12
13
14
15
16
17
# File 'lib/mmdb/decoder.rb', line 9

def 
  @metadata ||=
    begin
      index = data.rindex(METADATA_BEGIN)
      raise InvalidFileFormat if index.nil?

      decode(position: index + METADATA_BEGIN.size, base: 0).value
    end
end

#node_byte_sizeObject



31
32
33
# File 'lib/mmdb/decoder.rb', line 31

def node_byte_size
  @node_byte_size ||= ['record_size'] * 2 / 8
end

#node_countObject



27
28
29
# File 'lib/mmdb/decoder.rb', line 27

def node_count
  ['node_count']
end

#read(node:, flag:) ⇒ Object



43
44
45
46
47
48
49
50
51
52
53
54
# File 'lib/mmdb/decoder.rb', line 43

def read(node:, flag:)
  position = node_byte_size * node
  middle = data[position + record_byte_size].ord if node_byte_size.odd?
  if flag.zero? # LEFT node
    val = fetch(position, 0)
    val += ((middle & 0xf0) << 20) if middle
  else # RIGHT node
    val = fetch(position + node_byte_size - record_byte_size, 0)
    val += ((middle & 0xf) << 24) if middle
  end
  val
end

#record_byte_sizeObject



39
40
41
# File 'lib/mmdb/decoder.rb', line 39

def record_byte_size
  @record_byte_size ||= node_byte_size / 2
end

#search_tree_sizeObject



35
36
37
# File 'lib/mmdb/decoder.rb', line 35

def search_tree_size
  @search_tree_size ||= node_count * node_byte_size
end

#start_indexObject



19
20
21
# File 'lib/mmdb/decoder.rb', line 19

def start_index
  @start_index ||= ip_version == 4 ? 96 : 0
end