class YARP::Serialize::Loader

Attributes

constant_pool[R]
constant_pool_offset[R]
encoding[R]
input[R]
io[R]
serialized[R]
source[R]

Public Class Methods

new(source, serialized) click to toggle source
# File yarp/serialize.rb, line 45
def initialize(source, serialized)
  @encoding = Encoding::UTF_8

  @input = source.source.dup
  @serialized = serialized
  @io = StringIO.new(serialized)
  @io.set_encoding(Encoding::BINARY)

  @constant_pool_offset = nil
  @constant_pool = nil

  @source = source
end

Public Instance Methods

load_encoding() click to toggle source
# File yarp/serialize.rb, line 59
def load_encoding
  Encoding.find(io.read(load_varint))
end
load_metadata() click to toggle source
# File yarp/serialize.rb, line 63
def load_metadata
  comments = load_varint.times.map { Comment.new(Comment::TYPES.fetch(load_varint), load_location) }
  errors = load_varint.times.map { ParseError.new(load_embedded_string, load_location) }
  warnings = load_varint.times.map { ParseWarning.new(load_embedded_string, load_location) }
  [comments, errors, warnings]
end
load_nodes() click to toggle source
# File yarp/serialize.rb, line 96
def load_nodes
  raise "Invalid serialization" if io.read(4) != "YARP"
  raise "Invalid serialization" if io.read(3).unpack("C3") != [MAJOR_VERSION, MINOR_VERSION, PATCH_VERSION]

  @encoding = load_encoding
  @input = input.force_encoding(@encoding).freeze

  comments, errors, warnings = load_metadata

  @constant_pool_offset = io.read(4).unpack1("L")
  @constant_pool = Array.new(load_varint, nil)

  [load_node, comments, errors, warnings]
end
load_result() click to toggle source
# File yarp/serialize.rb, line 111
def load_result
  node, comments, errors, warnings = load_nodes
  YARP::ParseResult.new(node, comments, errors, warnings, @source)
end
load_tokens() click to toggle source
# File yarp/serialize.rb, line 70
def load_tokens
  tokens = []
  while type = TOKEN_TYPES.fetch(load_varint)
    start = load_varint
    length = load_varint
    lex_state = load_varint
    location = Location.new(@source, start, length)
    tokens << [YARP::Token.new(type, location.slice, location), lex_state]
  end

  tokens
end
load_tokens_result() click to toggle source
# File yarp/serialize.rb, line 83
def load_tokens_result
  tokens = load_tokens
  encoding = load_encoding
  comments, errors, warnings = load_metadata

  if encoding != @encoding
    tokens.each { |token,| token.value.force_encoding(encoding) }
  end

  raise "Expected to consume all bytes while deserializing" unless @io.eof?
  YARP::ParseResult.new(tokens, comments, errors, warnings, @source)
end

Private Instance Methods

load_constant(index) click to toggle source
# File yarp/serialize.rb, line 168
def load_constant(index)
  constant = constant_pool[index]

  unless constant
    offset = constant_pool_offset + index * 8
    start = serialized.unpack1("L", offset: offset)
    length = serialized.unpack1("L", offset: offset + 4)

    constant =
      if start.nobits?(1 << 31)
        input.byteslice(start, length).to_sym
      else
        serialized.byteslice(start & ((1 << 31) - 1), length).to_sym
      end

    constant_pool[index] = constant
  end

  constant
end
load_embedded_string() click to toggle source
# File yarp/serialize.rb, line 145
def load_embedded_string
  io.read(load_varint).force_encoding(encoding)
end
load_location() click to toggle source
# File yarp/serialize.rb, line 160
def load_location
  Location.new(source, load_varint, load_varint)
end
load_node() click to toggle source
# File yarp/serialize.rb, line 198
def load_node
  type = io.getbyte
  location = load_location

  case type
  when 1 then
    AliasGlobalVariableNode.new(load_node, load_node, load_location, location)
  when 2 then
    AliasMethodNode.new(load_node, load_node, load_location, location)
  when 3 then
    AlternationPatternNode.new(load_node, load_node, load_location, location)
  when 4 then
    AndNode.new(load_node, load_node, load_location, location)
  when 5 then
    ArgumentsNode.new(Array.new(load_varint) { load_node }, location)
  when 6 then
    ArrayNode.new(Array.new(load_varint) { load_node }, load_optional_location, load_optional_location, location)
  when 7 then
    ArrayPatternNode.new(load_optional_node, Array.new(load_varint) { load_node }, load_optional_node, Array.new(load_varint) { load_node }, load_optional_location, load_optional_location, location)
  when 8 then
    AssocNode.new(load_node, load_optional_node, load_optional_location, location)
  when 9 then
    AssocSplatNode.new(load_optional_node, load_location, location)
  when 10 then
    BackReferenceReadNode.new(location)
  when 11 then
    BeginNode.new(load_optional_location, load_optional_node, load_optional_node, load_optional_node, load_optional_node, load_optional_location, location)
  when 12 then
    BlockArgumentNode.new(load_optional_node, load_location, location)
  when 13 then
    BlockLocalVariableNode.new(load_required_constant, location)
  when 14 then
    BlockNode.new(Array.new(load_varint) { load_required_constant }, load_optional_node, load_optional_node, load_location, load_location, location)
  when 15 then
    BlockParameterNode.new(load_optional_constant, load_optional_location, load_location, location)
  when 16 then
    BlockParametersNode.new(load_optional_node, Array.new(load_varint) { load_node }, load_optional_location, load_optional_location, location)
  when 17 then
    BreakNode.new(load_optional_node, load_location, location)
  when 18 then
    CallAndWriteNode.new(load_optional_node, load_optional_location, load_optional_location, load_optional_location, load_optional_node, load_optional_location, load_varint, load_string, load_string, load_location, load_node, location)
  when 19 then
    CallNode.new(load_optional_node, load_optional_location, load_optional_location, load_optional_location, load_optional_node, load_optional_location, load_optional_node, load_varint, load_string, location)
  when 20 then
    CallOperatorWriteNode.new(load_optional_node, load_optional_location, load_optional_location, load_optional_location, load_optional_node, load_optional_location, load_varint, load_string, load_string, load_required_constant, load_location, load_node, location)
  when 21 then
    CallOrWriteNode.new(load_optional_node, load_optional_location, load_optional_location, load_optional_location, load_optional_node, load_optional_location, load_varint, load_string, load_string, load_location, load_node, location)
  when 22 then
    CapturePatternNode.new(load_node, load_node, load_location, location)
  when 23 then
    CaseNode.new(load_optional_node, Array.new(load_varint) { load_node }, load_optional_node, load_location, load_location, location)
  when 24 then
    ClassNode.new(Array.new(load_varint) { load_required_constant }, load_location, load_node, load_optional_location, load_optional_node, load_optional_node, load_location, load_required_constant, location)
  when 25 then
    ClassVariableAndWriteNode.new(load_required_constant, load_location, load_location, load_node, location)
  when 26 then
    ClassVariableOperatorWriteNode.new(load_required_constant, load_location, load_location, load_node, load_required_constant, location)
  when 27 then
    ClassVariableOrWriteNode.new(load_required_constant, load_location, load_location, load_node, location)
  when 28 then
    ClassVariableReadNode.new(load_required_constant, location)
  when 29 then
    ClassVariableTargetNode.new(load_required_constant, location)
  when 30 then
    ClassVariableWriteNode.new(load_required_constant, load_location, load_node, load_optional_location, location)
  when 31 then
    ConstantAndWriteNode.new(load_required_constant, load_location, load_location, load_node, location)
  when 32 then
    ConstantOperatorWriteNode.new(load_required_constant, load_location, load_location, load_node, load_required_constant, location)
  when 33 then
    ConstantOrWriteNode.new(load_required_constant, load_location, load_location, load_node, location)
  when 34 then
    ConstantPathAndWriteNode.new(load_node, load_location, load_node, location)
  when 35 then
    ConstantPathNode.new(load_optional_node, load_node, load_location, location)
  when 36 then
    ConstantPathOperatorWriteNode.new(load_node, load_location, load_node, load_required_constant, location)
  when 37 then
    ConstantPathOrWriteNode.new(load_node, load_location, load_node, location)
  when 38 then
    ConstantPathTargetNode.new(load_optional_node, load_node, load_location, location)
  when 39 then
    ConstantPathWriteNode.new(load_node, load_location, load_node, location)
  when 40 then
    ConstantReadNode.new(load_required_constant, location)
  when 41 then
    ConstantTargetNode.new(load_required_constant, location)
  when 42 then
    ConstantWriteNode.new(load_required_constant, load_location, load_node, load_location, location)
  when 43 then
    load_serialized_length
    DefNode.new(load_required_constant, load_location, load_optional_node, load_optional_node, load_optional_node, Array.new(load_varint) { load_required_constant }, load_location, load_optional_location, load_optional_location, load_optional_location, load_optional_location, load_optional_location, location)
  when 44 then
    DefinedNode.new(load_optional_location, load_node, load_optional_location, load_location, location)
  when 45 then
    ElseNode.new(load_location, load_optional_node, load_optional_location, location)
  when 46 then
    EmbeddedStatementsNode.new(load_location, load_optional_node, load_location, location)
  when 47 then
    EmbeddedVariableNode.new(load_location, load_node, location)
  when 48 then
    EnsureNode.new(load_location, load_optional_node, load_location, location)
  when 49 then
    FalseNode.new(location)
  when 50 then
    FindPatternNode.new(load_optional_node, load_node, Array.new(load_varint) { load_node }, load_node, load_optional_location, load_optional_location, location)
  when 51 then
    FlipFlopNode.new(load_optional_node, load_optional_node, load_location, load_varint, location)
  when 52 then
    FloatNode.new(location)
  when 53 then
    ForNode.new(load_node, load_node, load_optional_node, load_location, load_location, load_optional_location, load_location, location)
  when 54 then
    ForwardingArgumentsNode.new(location)
  when 55 then
    ForwardingParameterNode.new(location)
  when 56 then
    ForwardingSuperNode.new(load_optional_node, location)
  when 57 then
    GlobalVariableAndWriteNode.new(load_required_constant, load_location, load_location, load_node, location)
  when 58 then
    GlobalVariableOperatorWriteNode.new(load_required_constant, load_location, load_location, load_node, load_required_constant, location)
  when 59 then
    GlobalVariableOrWriteNode.new(load_required_constant, load_location, load_location, load_node, location)
  when 60 then
    GlobalVariableReadNode.new(load_required_constant, location)
  when 61 then
    GlobalVariableTargetNode.new(load_required_constant, location)
  when 62 then
    GlobalVariableWriteNode.new(load_required_constant, load_location, load_node, load_location, location)
  when 63 then
    HashNode.new(load_location, Array.new(load_varint) { load_node }, load_location, location)
  when 64 then
    HashPatternNode.new(load_optional_node, Array.new(load_varint) { load_node }, load_optional_node, load_optional_location, load_optional_location, location)
  when 65 then
    IfNode.new(load_optional_location, load_node, load_optional_node, load_optional_node, load_optional_location, location)
  when 66 then
    ImaginaryNode.new(load_node, location)
  when 67 then
    InNode.new(load_node, load_optional_node, load_location, load_optional_location, location)
  when 68 then
    InstanceVariableAndWriteNode.new(load_required_constant, load_location, load_location, load_node, location)
  when 69 then
    InstanceVariableOperatorWriteNode.new(load_required_constant, load_location, load_location, load_node, load_required_constant, location)
  when 70 then
    InstanceVariableOrWriteNode.new(load_required_constant, load_location, load_location, load_node, location)
  when 71 then
    InstanceVariableReadNode.new(load_required_constant, location)
  when 72 then
    InstanceVariableTargetNode.new(load_required_constant, location)
  when 73 then
    InstanceVariableWriteNode.new(load_required_constant, load_location, load_node, load_location, location)
  when 74 then
    IntegerNode.new(load_varint, location)
  when 75 then
    InterpolatedMatchLastLineNode.new(load_location, Array.new(load_varint) { load_node }, load_location, load_varint, location)
  when 76 then
    InterpolatedRegularExpressionNode.new(load_location, Array.new(load_varint) { load_node }, load_location, load_varint, location)
  when 77 then
    InterpolatedStringNode.new(load_optional_location, Array.new(load_varint) { load_node }, load_optional_location, location)
  when 78 then
    InterpolatedSymbolNode.new(load_optional_location, Array.new(load_varint) { load_node }, load_optional_location, location)
  when 79 then
    InterpolatedXStringNode.new(load_location, Array.new(load_varint) { load_node }, load_location, location)
  when 80 then
    KeywordHashNode.new(Array.new(load_varint) { load_node }, location)
  when 81 then
    KeywordParameterNode.new(load_required_constant, load_location, load_optional_node, location)
  when 82 then
    KeywordRestParameterNode.new(load_optional_constant, load_optional_location, load_location, location)
  when 83 then
    LambdaNode.new(Array.new(load_varint) { load_required_constant }, load_location, load_location, load_location, load_optional_node, load_optional_node, location)
  when 84 then
    LocalVariableAndWriteNode.new(load_location, load_location, load_node, load_required_constant, load_varint, location)
  when 85 then
    LocalVariableOperatorWriteNode.new(load_location, load_location, load_node, load_required_constant, load_required_constant, load_varint, location)
  when 86 then
    LocalVariableOrWriteNode.new(load_location, load_location, load_node, load_required_constant, load_varint, location)
  when 87 then
    LocalVariableReadNode.new(load_required_constant, load_varint, location)
  when 88 then
    LocalVariableTargetNode.new(load_required_constant, load_varint, location)
  when 89 then
    LocalVariableWriteNode.new(load_required_constant, load_varint, load_location, load_node, load_location, location)
  when 90 then
    MatchLastLineNode.new(load_location, load_location, load_location, load_string, load_varint, location)
  when 91 then
    MatchPredicateNode.new(load_node, load_node, load_location, location)
  when 92 then
    MatchRequiredNode.new(load_node, load_node, load_location, location)
  when 93 then
    MissingNode.new(location)
  when 94 then
    ModuleNode.new(Array.new(load_varint) { load_required_constant }, load_location, load_node, load_optional_node, load_location, load_required_constant, location)
  when 95 then
    MultiTargetNode.new(Array.new(load_varint) { load_node }, load_optional_location, load_optional_location, location)
  when 96 then
    MultiWriteNode.new(Array.new(load_varint) { load_node }, load_optional_location, load_optional_location, load_location, load_node, location)
  when 97 then
    NextNode.new(load_optional_node, load_location, location)
  when 98 then
    NilNode.new(location)
  when 99 then
    NoKeywordsParameterNode.new(load_location, load_location, location)
  when 100 then
    NumberedReferenceReadNode.new(load_varint, location)
  when 101 then
    OptionalParameterNode.new(load_required_constant, load_location, load_location, load_node, location)
  when 102 then
    OrNode.new(load_node, load_node, load_location, location)
  when 103 then
    ParametersNode.new(Array.new(load_varint) { load_node }, Array.new(load_varint) { load_node }, load_optional_node, Array.new(load_varint) { load_node }, Array.new(load_varint) { load_node }, load_optional_node, load_optional_node, location)
  when 104 then
    ParenthesesNode.new(load_optional_node, load_location, load_location, location)
  when 105 then
    PinnedExpressionNode.new(load_node, load_location, load_location, load_location, location)
  when 106 then
    PinnedVariableNode.new(load_node, load_location, location)
  when 107 then
    PostExecutionNode.new(load_optional_node, load_location, load_location, load_location, location)
  when 108 then
    PreExecutionNode.new(load_optional_node, load_location, load_location, load_location, location)
  when 109 then
    ProgramNode.new(Array.new(load_varint) { load_required_constant }, load_node, location)
  when 110 then
    RangeNode.new(load_optional_node, load_optional_node, load_location, load_varint, location)
  when 111 then
    RationalNode.new(load_node, location)
  when 112 then
    RedoNode.new(location)
  when 113 then
    RegularExpressionNode.new(load_location, load_location, load_location, load_string, load_varint, location)
  when 114 then
    RequiredDestructuredParameterNode.new(Array.new(load_varint) { load_node }, load_location, load_location, location)
  when 115 then
    RequiredParameterNode.new(load_required_constant, location)
  when 116 then
    RescueModifierNode.new(load_node, load_location, load_node, location)
  when 117 then
    RescueNode.new(load_location, Array.new(load_varint) { load_node }, load_optional_location, load_optional_node, load_optional_node, load_optional_node, location)
  when 118 then
    RestParameterNode.new(load_optional_constant, load_optional_location, load_location, location)
  when 119 then
    RetryNode.new(location)
  when 120 then
    ReturnNode.new(load_location, load_optional_node, location)
  when 121 then
    SelfNode.new(location)
  when 122 then
    SingletonClassNode.new(Array.new(load_varint) { load_required_constant }, load_location, load_location, load_node, load_optional_node, load_location, location)
  when 123 then
    SourceEncodingNode.new(location)
  when 124 then
    SourceFileNode.new(load_string, location)
  when 125 then
    SourceLineNode.new(location)
  when 126 then
    SplatNode.new(load_location, load_optional_node, location)
  when 127 then
    StatementsNode.new(Array.new(load_varint) { load_node }, location)
  when 128 then
    StringConcatNode.new(load_node, load_node, location)
  when 129 then
    StringNode.new(load_optional_location, load_location, load_optional_location, load_string, location)
  when 130 then
    SuperNode.new(load_location, load_optional_location, load_optional_node, load_optional_location, load_optional_node, location)
  when 131 then
    SymbolNode.new(load_optional_location, load_optional_location, load_optional_location, load_string, location)
  when 132 then
    TrueNode.new(location)
  when 133 then
    UndefNode.new(Array.new(load_varint) { load_node }, load_location, location)
  when 134 then
    UnlessNode.new(load_location, load_node, load_optional_node, load_optional_node, load_optional_location, location)
  when 135 then
    UntilNode.new(load_location, load_optional_location, load_node, load_optional_node, load_varint, location)
  when 136 then
    WhenNode.new(load_location, Array.new(load_varint) { load_node }, load_optional_node, location)
  when 137 then
    WhileNode.new(load_location, load_optional_location, load_node, load_optional_node, load_varint, location)
  when 138 then
    XStringNode.new(load_location, load_location, load_location, load_string, location)
  when 139 then
    YieldNode.new(load_location, load_optional_location, load_optional_node, load_optional_location, location)
  end
end
load_optional_constant() click to toggle source
# File yarp/serialize.rb, line 193
def load_optional_constant
  index = load_varint
  load_constant(index - 1) if index != 0
end
load_optional_location() click to toggle source
# File yarp/serialize.rb, line 164
def load_optional_location
  load_location if io.getbyte != 0
end
load_optional_node() click to toggle source
# File yarp/serialize.rb, line 138
def load_optional_node
  if io.getbyte != 0
    io.pos -= 1
    load_node
  end
end
load_required_constant() click to toggle source
# File yarp/serialize.rb, line 189
def load_required_constant
  load_constant(load_varint - 1)
end
load_serialized_length() click to toggle source
# File yarp/serialize.rb, line 134
def load_serialized_length
  io.read(4).unpack1("L")
end
load_string() click to toggle source
# File yarp/serialize.rb, line 149
def load_string
  case io.getbyte
  when 1
    input.byteslice(load_varint, load_varint).force_encoding(encoding)
  when 2
    load_embedded_string
  else
    raise
  end
end
load_varint() click to toggle source

variable-length integer using en.wikipedia.org/wiki/LEB128 This is also what protobuf uses: protobuf.dev/programming-guides/encoding/#varints

# File yarp/serialize.rb, line 120
def load_varint
  n = io.getbyte
  if n < 128
    n
  else
    n -= 128
    shift = 0
    while (b = io.getbyte) >= 128
      n += (b - 128) << (shift += 7)
    end
    n + (b << (shift + 7))
  end
end