Class: BinaryCodec::STArray

Inherits:
SerializedType show all
Defined in:
lib/binary-codec/types/st_array.rb

Instance Attribute Summary

Attributes inherited from SerializedType

#bytes

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from SerializedType

from_bytes, from_hex, from_json, get_type_by_name, #to_byte_sink, #to_bytes, #to_hex, #value_of

Constructor Details

#initialize(byte_buf = nil) ⇒ STArray

Returns a new instance of STArray.



5
6
7
# File 'lib/binary-codec/types/st_array.rb', line 5

def initialize(byte_buf = nil)
  super(byte_buf || [])
end

Class Method Details

.from(value, definitions = nil) ⇒ STArray

Creates a new STArray instance from a value.

Parameters:

  • value (STArray, String, Array<Hash>)

    The value to convert.

  • definitions (Definitions, nil) (defaults to: nil)

    Optional definitions.

Returns:

  • (STArray)

    The created instance.

Raises:

  • (StandardError)


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
# File 'lib/binary-codec/types/st_array.rb', line 13

def self.from(value, definitions = nil)
  return value if value.is_a?(STArray)
  definitions ||= Definitions.instance

  if value.is_a?(String)
    return STArray.new(hex_to_bytes(value))
  end

  if value.is_a?(Array)
    bytes = []
    value.each do |item|
      # item should be a hash with one key (the field name)
      # e.g., {"Signer" => { ... }}
      if item.is_a?(::Hash)
        # Use keys.first and unwrap directly
        field_name = item.keys.first.to_s
        field_value = item[item.keys.first]
        
        field = definitions.get_field_instance(field_name)
        bytes.concat(field.header.to_bytes)
        
        obj = STObject.from(field_value, nil, definitions)
        bytes.concat(obj.to_bytes)
        bytes.concat([0xE1]) unless bytes.last == 0xE1
      else
        raise StandardError, "STArray item must be a Hash, got #{item.class}"
      end
    end
    bytes.concat([0xF1]) # ArrayEndMarker
    return STArray.new(bytes)
  end

  raise StandardError, "Cannot construct STArray from #{value.class}"
end

.from_parser(parser, _hint = nil) ⇒ STArray

Creates an STArray instance from a parser.

Parameters:

  • parser (BinaryParser)

    The parser to read from.

  • _hint (Integer, nil) (defaults to: nil)

    Unused.

Returns:

  • (STArray)

    The created instance.



52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
# File 'lib/binary-codec/types/st_array.rb', line 52

def self.from_parser(parser, _hint = nil)
  bytes = []
  until parser.end?
    # Check if we reached the ArrayEndMarker (0xF1)
    if parser.peek == 0xF1
      parser.read(1) # Consume 0xF1
      break
    end

    # In STArray, each item is an STObject with its field header.
    # So we read the field header first.
    field_header = parser.read_field_header
    
    # Then we read the STObject
    obj = STObject.from_parser(parser)
    
    # Reconstruct the serialized item: [FieldHeader][STObject][ObjectEndMarker]
    bytes.concat(field_header.to_bytes)
    bytes.concat(obj.to_bytes)
    bytes.concat([0xE1]) unless bytes.last == 0xE1
  end
  STArray.new(bytes)
end

Instance Method Details

#to_json(definitions = nil, _field_name = nil) ⇒ Array<Hash>

Returns the JSON representation of the STArray.

Parameters:

  • definitions (Definitions, nil) (defaults to: nil)

    Definitions for lookup.

  • _field_name (String, nil) (defaults to: nil)

    Unused.

Returns:

  • (Array<Hash>)

    The JSON representation.



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
# File 'lib/binary-codec/types/st_array.rb', line 80

def to_json(definitions = nil, _field_name = nil)
  definitions ||= Definitions.instance
  parser = BinaryParser.new(to_hex)
  result = []
  until parser.end?
    begin
      # Check if we reached the ArrayEndMarker (0xF1) or if peek fails
      break if parser.peek == 0xF1
      
      # Read field header of the array item (e.g., "Signer")
      field_header = parser.read_field_header
      field_name = definitions.get_field_name_from_header(field_header)
      
      # Read the STObject item
      obj = STObject.from_parser(parser)
      
      # Array item in JSON is { "FieldName": { ... } }
      item_json = obj.to_json(definitions)
      result << { field_name => item_json.is_a?(String) ? JSON.parse(item_json) : item_json }
    rescue => e
      break
    end
  end
  result
end