Class: RBS::WASM::Deserializer

Inherits:
Object
  • Object
show all
Defined in:
lib/rbs/wasm/deserializer.rb

Overview

Rebuilds RBS::AST objects from the binary buffer produced by ‘rbs_serialize_node` (src/serialize.c), driven by the generated SerializationSchema. This is the pure-Ruby counterpart of the C extension’s ast_translation.c, used when the parser runs inside WebAssembly (JRuby).

All locations are reconstructed through the public RBS::Location API, so the same code works whether RBS::Location is backed by the C extension (CRuby) or by a pure-Ruby implementation (JRuby).

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(bytes, buffer) ⇒ Deserializer

Returns a new instance of Deserializer.



34
35
36
37
38
39
40
41
42
43
# File 'lib/rbs/wasm/deserializer.rb', line 34

def initialize(bytes, buffer)
  @bytes = bytes
  @buffer = buffer
  # Symbols and rbs_string fields (comments, annotations) inherit the
  # source encoding, matching ast_translation.c. String/Integer literal
  # nodes are always UTF-8 (see read_node).
  @encoding = buffer.content.encoding
  @pos = 0
  @class_cache = {} #: Hash[String, untyped]
end

Class Method Details

.deserialize(bytes, buffer) ⇒ Object

Deserialize a buffer produced for a whole signature, returning ‘[directives, declarations]` to match RBS::Parser._parse_signature.



18
19
20
# File 'lib/rbs/wasm/deserializer.rb', line 18

def self.deserialize(bytes, buffer)
  new(bytes, buffer).read_node
end

.deserialize_node_list(bytes, buffer) ⇒ Object

Deserialize a bare node list (rbs_serialize_node_list), e.g. the result of RBS::Parser._parse_type_params.



24
25
26
# File 'lib/rbs/wasm/deserializer.rb', line 24

def self.deserialize_node_list(bytes, buffer)
  new(bytes, buffer).read_node_list
end

.deserialize_tokens(bytes, buffer) ⇒ Object

Deserialize the token stream produced by rbs_wasm_lex into the

type, location

pairs RBS::Parser._lex returns.



30
31
32
# File 'lib/rbs/wasm/deserializer.rb', line 30

def self.deserialize_tokens(bytes, buffer)
  new(bytes, buffer).read_tokens
end

Instance Method Details

#read_nodeObject



45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
# File 'lib/rbs/wasm/deserializer.rb', line 45

def read_node
  tag = read_u8
  return nil if tag == 0
  return read_string(@encoding).to_sym if tag == SerializationSchema::SYMBOL_TAG

  entry = SerializationSchema::SCHEMA[tag] or raise "Unknown node tag: #{tag}"

  case entry[0]
  when :node then read_struct(entry)
  when :bool then read_u8 != 0
  when :integer then read_string(Encoding::UTF_8).to_i
  when :string_value then read_string(Encoding::UTF_8)
  when :record_field then [read_node, read_u8 != 0]
  when :signature then [read_node_list, read_node_list]
  when :namespace then RBS::Namespace[read_node_list, read_u8 != 0]
  when :type_name then RBS::TypeName[read_node, read_node]
  else raise "Unknown schema entry kind: #{entry[0].inspect}"
  end
end

#read_node_listObject



65
66
67
# File 'lib/rbs/wasm/deserializer.rb', line 65

def read_node_list
  Array.new(read_count) { read_node }
end

#read_tokensObject

The lex stream has no leading count: read records until the buffer is exhausted. Each is a token type name followed by its character range.



71
72
73
74
75
76
77
78
79
80
# File 'lib/rbs/wasm/deserializer.rb', line 71

def read_tokens
  tokens = [] #: Array[[ Symbol, Location ]]
  until @pos >= @bytes.bytesize
    type = read_string(Encoding::UTF_8).to_sym
    start_char = read_i32
    end_char = read_i32
    tokens << [type, RBS::Location.new(@buffer, start_char, end_char)]
  end
  tokens
end