Module: Bitfab::Serialize

Defined in:
lib/bitfab/serialize.rb

Class Method Summary collapse

Class Method Details

.deserialize_inputs(item) ⇒ Array(Array, Hash)

Deserialize replay inputs from a span’s data into [args, kwargs].

Prefers Marshal-serialized ‘inputSerialized` for type preservation, falls back to the raw `input` field.

Parameters:

  • item (Hash)

    with “inputSerialized” and/or “input” keys

Returns:

  • (Array(Array, Hash))

    positional args and keyword args



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
# File 'lib/bitfab/serialize.rb', line 76

def deserialize_inputs(item)
  input_serialized = item["inputSerialized"]
  raw_input = item["input"]

  if input_serialized.is_a?(String) && !input_serialized.empty?
    begin
      deserialized = unmarshal_value(input_serialized)
      if deserialized.is_a?(Hash) && (deserialized.key?(:args) || deserialized.key?(:kwargs))
        return [deserialized[:args] || [], deserialized[:kwargs] || {}]
      end
      return deserialized.nil? ? [[], {}] : [[deserialized], {}]
    rescue
      # Fall through to raw_input
    end
  end

  if raw_input.is_a?(Array)
    [raw_input, {}]
  elsif raw_input.is_a?(Hash)
    [[], raw_input.transform_keys(&:to_sym)]
  elsif raw_input.nil?
    [[], {}]
  else
    [[raw_input], {}]
  end
end

.marshal_value(value) ⇒ String?

Marshal a value to a Base64-encoded string for Ruby-to-Ruby reconstruction. Handles arbitrary Ruby objects including custom classes.

Parameters:

  • value (Object)

    any Ruby value

Returns:

  • (String, nil)

    Base64-encoded Marshal dump, or nil if marshalling fails



54
55
56
57
58
59
# File 'lib/bitfab/serialize.rb', line 54

def marshal_value(value)
  Base64.strict_encode64(Marshal.dump(value))
rescue TypeError, ArgumentError
  # Some objects (Proc, IO, etc.) can't be marshalled
  nil
end

.serialize_inputs(args, kwargs = {}) ⇒ Object

Serialize function inputs (args + kwargs) for span data (human-readable).



43
44
45
46
47
# File 'lib/bitfab/serialize.rb', line 43

def serialize_inputs(args, kwargs = {})
  serialized = args.map { |arg| serialize_value(arg) }
  serialized << kwargs.transform_keys(&:to_s).transform_values { |v| serialize_value(v) } unless kwargs.empty?
  serialized
end

.serialize_value(value) ⇒ Object

Serialize a value for JSON storage (human-readable). Handles primitives, hashes, arrays, and objects with common conversion methods. Note: We intentionally avoid as_json here because it requires ActiveSupport, and we want to keep the SDK dependency-free (stdlib only).



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
# File 'lib/bitfab/serialize.rb', line 15

def serialize_value(value)
  case value
  when nil, true, false, Integer, Float, String
    value
  when Hash
    value.transform_keys(&:to_s).transform_values { |v| serialize_value(v) }
  when Array
    value.map { |v| serialize_value(v) }
  when Set
    value.map { |v| serialize_value(v) }
  when Time, DateTime
    value.iso8601(3)
  when Date
    value.to_s
  when Symbol
    value.to_s
  else
    if value.respond_to?(:to_h)
      serialize_value(value.to_h)
    elsif value.respond_to?(:to_a)
      serialize_value(value.to_a)
    else
      value.to_s
    end
  end
end

.unmarshal_value(encoded) ⇒ Object

Unmarshal a Base64-encoded string back into a Ruby object.

Parameters:

  • encoded (String)

    Base64-encoded Marshal dump

Returns:

  • (Object)

    the reconstructed Ruby object



65
66
67
# File 'lib/bitfab/serialize.rb', line 65

def unmarshal_value(encoded)
  Marshal.load(Base64.strict_decode64(encoded)) # rubocop:disable Security/MarshalLoad
end