Class: MemoryIO::Types::Type

Inherits:
Object
  • Object
show all
Defined in:
lib/memory_io/types/type.rb

Overview

The base class, all descendants of this class would be consider as a valid ‘type’.

Direct Known Subclasses

CPP::String, Clang::CStr

Constant Summary collapse

SIZE_T =

The size of size_t. i.e. sizeof(size_t).

8

Class Method Summary collapse

Class Method Details

.find(symbol) ⇒ {Symbol => Object}

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Find the subclass of MemoryIO::Types::Type by symbol.

Parameters:

  • symbol (Symbol)

    Symbol that has been registered in register.

Returns:

  • ({Symbol => Object})

    The object that registered in register.

See Also:



90
91
92
# File 'lib/memory_io/types/type.rb', line 90

def find(symbol)
  @map[symbol]
end

.keep_pos(stream, pos: nil) {|stream| ... } ⇒ Object

Yield a block and resume the position of stream.

Examples:

s = StringIO.new('1234')
Type.keep_pos(s, pos: 2) { |s| s.read(2) }
#=> '34'
s.pos
#=> 0

Parameters:

  • stream (#pos, #pos=)

    Stream.

  • pos (Integer) (defaults to: nil)

    Move stream‘s position to pos before invoke the block.

Yield Parameters:

  • stream (#pos, #pos=)

    Same as parameter stream.

Yield Returns:

  • (Object)

    The returned object will be returned by this method.

Returns:

  • (Object)

    Returns the object returned by block.



71
72
73
74
75
76
77
# File 'lib/memory_io/types/type.rb', line 71

def keep_pos(stream, pos: nil)
  org = stream.pos
  stream.pos = pos if pos
  ret = yield stream
  stream.pos = org
  ret
end

.read(_stream) ⇒ Object

This method is abstract.

Raises:

  • (NotImplementedError)


142
143
# File 'lib/memory_io/types/type.rb', line 142

def read(_stream) raise NotImplementedError
end

.read_size_t(stream) ⇒ Integer

Read SIZE_T bytes and cast to a little endian unsigned integer.

Examples:

s = StringIO.new("\xEF\xBE\xAD\xDExV4\x00")
Type.read_size_t(s).to_s(16)
#=> '345678deadbeef'

Parameters:

  • stream (#read)

    Stream to read.

Returns:

  • (Integer)

    Result.



28
29
30
# File 'lib/memory_io/types/type.rb', line 28

def read_size_t(stream)
  MemoryIO::Util.unpack(stream.read(SIZE_T))
end

.register(object, option = {}) ⇒ Array<Symbol>

Note:

If all symbols in alias have been registered, an ArgumentError will be raised. However, if at least one of aliases hasn’t been used, registration will success.

Register a new type.

Examples:

Type.register(MemoryIO::Types::Clang::CStr, alias: :meow)
#=> [:'clang/c_str', :c_str, :meow]

Type.register(ModuleOne::CStr, alias: :my_class)
#=> [:'module_one/c_str', :my_class]

Type.register(AnotherClass, alias: :my_class)
# An error will be raised because the 'alias' has been registered.

Type.register(AnotherClass, alias: [:my_class, my_class2])
#=> [:another_class, :my_class2]

Parameters:

  • object (#read, #write)

    Normally, object is a descendant class of MemoryIO::Types::Type.

  • [Symbol, (Hash)

    a customizable set of options

  • [String] (Hash)

    a customizable set of options

Returns:

  • (Array<Symbol>)

    Array of symbols that can be used for finding the registered object.

See Also:



125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
# File 'lib/memory_io/types/type.rb', line 125

def register(object, option = {})
  @map ||= OpenStruct.new
  aliases = Array(option[:alias])
  reg_fail = ArgumentError.new(<<-EOS.strip)
Register '#{object.inspect}' fails because another object with same name has been registered.
Specify an alias such as `register(MyClass, alias: :custom_alias_name)`.
  EOS
  raise reg_fail if aliases.any? && aliases.all? { |ali| @map[ali] }

  keys = get_keys(object).concat(aliases).uniq.reject { |k| @map[k] }
  raise reg_fail if keys.empty?

  rec = MemoryIO::Types::Record.new(object, keys, option)
  keys.each { |k| @map[k] = rec }
end

.write(_stream, _obj) ⇒ Object

This method is abstract.

Raises:

  • (NotImplementedError)


146
147
# File 'lib/memory_io/types/type.rb', line 146

def write(_stream, _obj) raise NotImplementedError
end

.write_size_t(stream, val) ⇒ void

This method returns an undefined value.

Pack val into SIZE_T bytes and write to stream.

Examples:

s = StringIO.new
Type.write_size_t(s, 0x123)
s.string
#=> "\x23\x01\x00\x00\x00\x00\x00\x00"

Parameters:

  • stream (#write)

    Stream to write.

  • val (Integer)

    Value to be written.



46
47
48
# File 'lib/memory_io/types/type.rb', line 46

def write_size_t(stream, val)
  stream.write(MemoryIO::Util.pack(val, SIZE_T))
end