-
Notifications
You must be signed in to change notification settings - Fork 386
/
Copy pathmetastruct.rb
64 lines (54 loc) · 1.6 KB
/
metastruct.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
# frozen_string_literal: true
require 'forwardable'
module Datadog
module Tracing
module Metadata
# Adds complex structures tagging behavior through metastruct
class Metastruct
extend Forwardable
MERGER = proc do |_, v1, v2|
if v1.is_a?(Hash) && v2.is_a?(Hash)
v1.merge(v2, &MERGER)
elsif v1.is_a?(Array) && v2.is_a?(Array)
v1.concat(v2)
elsif v2.nil?
v1
else
v2
end
end
def self.empty
new({})
end
def initialize(metastruct)
@metastruct = metastruct
end
# Deep merge two metastructs
# If the types are not both Arrays or Hashes, the second one will overwrite the first one
#
# Example with same types:
# metastruct = { a: { b: [1, 2] } }
# second = { a: { b: [3, 4], c: 5 } }
# result = { a: { b: [1, 2, 3, 4], c: 5 } }
#
# Example with different types:
# metastruct = { a: { b: 1 } }
# second = { a: { b: [2, 3] } }
# result = { a: { b: [2, 3] } }
def deep_merge!(second)
@metastruct.merge!(second.to_h, &MERGER)
end
def_delegators :@metastruct, :[], :[]=, :dig, :to_h
def pretty_print(q)
q.seplist @metastruct.each do |key, value|
q.text "#{key} => #{value}\n"
end
end
def to_msgpack(packer = nil)
packer ||= MessagePack::Packer.new
packer.write(@metastruct.transform_values(&:to_msgpack))
end
end
end
end
end