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.



3
4
5
# File 'lib/mmdb/decoder.rb', line 3

def initialize(data)
  @data = data
end

Instance Method Details

#decode(position:, base:) ⇒ Object



53
54
55
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
# File 'lib/mmdb/decoder.rb', line 53

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



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

def ip_version
  ["ip_version"]
end

#metadataObject



7
8
9
10
11
12
13
14
# File 'lib/mmdb/decoder.rb', line 7

def 
   ||=
    begin
      index = data.rindex()
      raise InvalidFileFormat if index.nil?
      decode(position: index + .size, base: 0).value
    end
end

#node_byte_sizeObject



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

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

#node_countObject



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

def node_count
  ["node_count"]
end

#read(node:, flag:) ⇒ Object



40
41
42
43
44
45
46
47
48
49
50
51
# File 'lib/mmdb/decoder.rb', line 40

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



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

def record_byte_size
  @record_byte_size ||= node_byte_size / 2
end

#search_tree_sizeObject



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

def search_tree_size
  @search_tree_size ||= node_count * node_byte_size
end

#start_indexObject



16
17
18
# File 'lib/mmdb/decoder.rb', line 16

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