Module: CTypes::Type

Included in:
Array, Bitfield, Bitmap, Enum, Int, Pad, String, Struct, Terminated, Union
Defined in:
lib/ctypes/type.rb

Overview

interface for all supported types

Instance Attribute Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#dry_typeObject (readonly)

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.

Dry::Type used for constraint checking & defaults



11
12
13
# File 'lib/ctypes/type.rb', line 11

def dry_type
  @dry_type
end

#endianObject (readonly)

endian to use when packing/unpacking. nil means CTypes.default_endian will be used.



16
17
18
# File 'lib/ctypes/type.rb', line 16

def endian
  @endian
end

Instance Method Details

#default_endianObject

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.



185
186
187
# File 'lib/ctypes/type.rb', line 185

def default_endian
  @endian || CTypes.default_endian
end

#default_valueObject

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.



180
181
182
# File 'lib/ctypes/type.rb', line 180

def default_value
  dry_type[]
end

#fixed_size?Boolean

check if this is a fixed-size type

Returns:

  • (Boolean)


175
176
177
# File 'lib/ctypes/type.rb', line 175

def fixed_size?
  !!@size&.is_a?(Integer)
end

#greedy?Boolean

Returns:

  • (Boolean)

Raises:

  • (NotImplementedError)


170
171
172
# File 'lib/ctypes/type.rb', line 170

def greedy?
  raise NotImplementedError, "Type must implement `.greedy?`: %p" % [self]
end

#pack(value, endian: default_endian, validate: true) ⇒ ::String

encode a ruby type into a String containing the binary representation of the c type

Parameters:

  • value

    value to be encoded

  • endian (Symbol) (defaults to: default_endian)

    endian to pack with

  • validate (Boolean) (defaults to: true)

    set to false to disable value validation

Returns:

  • (::String)

    binary encoding for value

Raises:

  • (NotImplementedError)

See Also:



31
32
33
# File 'lib/ctypes/type.rb', line 31

def pack(value, endian: default_endian, validate: true)
  raise NotImplementedError
end

#pread(io, pos, endian: default_endian) ⇒ Object

read a fixed-sized type from an IO instance at a specific offset and unpack it

Parameters:

  • buf (::String)

    bytes that make up the type

  • pos (::Integer)

    seek position

  • endian (Symbol) (defaults to: default_endian)

    endian of data within buf

Returns:

  • decoded type



107
108
109
110
111
112
113
114
# File 'lib/ctypes/type.rb', line 107

def pread(io, pos, endian: default_endian)
  unless fixed_size?
    raise NotImplementedError,
      "pread() does not support variable-length types"
  end

  unpack(io.pread(@size, pos), endian: default_endian)
end

#read(io, endian: default_endian) ⇒ Object

read a fixed-sized type from an IO instance and unpack it

Parameters:

  • buf (::String)

    bytes that make up the type

  • endian (Symbol) (defaults to: default_endian)

    endian of data within buf

Returns:

  • decoded type



91
92
93
94
95
96
97
98
# File 'lib/ctypes/type.rb', line 91

def read(io, endian: default_endian)
  unless fixed_size?
    raise NotImplementedError,
      "read() does not support variable-length types"
  end

  unpack(io.read(@size), endian: default_endian)
end

#unpack(buf, endian: default_endian) ⇒ Object

convert a String containing the binary represention of a c type into the equivalent ruby type

Parameters:

  • buf (::String)

    bytes that make up the type

  • endian (Symbol) (defaults to: default_endian)

    endian of data within buf

Returns:

  • decoded type

See Also:



49
50
51
52
# File 'lib/ctypes/type.rb', line 49

def unpack(buf, endian: default_endian)
  o, = unpack_one(buf, endian:)
  o
end

#unpack_all(buf, endian: default_endian) ⇒ Object

unpack as many instances of Type are present in the supplied string

Parameters:

  • buf (String)

    bytes that make up the type

  • endian (Symbol) (defaults to: default_endian)

    endian of data within buf



77
78
79
80
81
82
83
84
# File 'lib/ctypes/type.rb', line 77

def unpack_all(buf, endian: default_endian)
  out = []
  until buf.empty?
    t, buf = unpack_one(buf, endian:)
    out << t
  end
  out
end

#unpack_one(buf, endian: default_endian) ⇒ Array(Object, ::String)

convert a String containing the binary represention of a c type into the equivalent ruby type

Parameters:

  • buf (String)

    bytes that make up the type

  • endian (Symbol) (defaults to: default_endian)

    endian of data within buf

Returns:

  • (Array(Object, ::String))

    decoded type, and remaining bytes

Raises:

  • (NotImplementedError)

See Also:



68
69
70
# File 'lib/ctypes/type.rb', line 68

def unpack_one(buf, endian: default_endian)
  raise NotImplementedError
end

#with_endian(value) ⇒ Type

get a fixed-endian instance of this type.

If a type has a fixed endian, it will override the default endian set with CTypes.default_endian=.

Examples:

uint32_t

t = CTypes::UInt32
t.pack(1)                 # => "\1\0\0\0"
b = t.with_endian(:big)
b.pack(1)                 # => "\0\0\0\1"
l = t.with_endian(:little)
l.pack(1)                 # => "\1\0\0\0"

array

include Ctype::Helpers
t = array(uint32, 2)
t.pack([1,2])             # => "\1\0\0\0\2\0\0\0"
b = t.with_endian(:big)
b.pack([1,2])             # => "\0\0\0\1\0\0\0\2"
l = t.with_endian(:little)
l.pack([1,2])             # => "\1\0\0\0\2\0\0\0"

struct with mixed endian fields

include Ctype::Helpers
t = struct do
  attribute native: uint32
  attribute big: uint32.with_endian(:big)
  attribute little: uint32.with_endian(:little)
end
t.pack({native: 1, big: 2, little: 3}) # => "\1\0\0\0\0\0\0\2\3\0\0\0"

Parameters:

  • value (Symbol)

    endian; ‘:big` or `:little`

Returns:



149
150
151
152
153
154
155
156
157
158
159
160
# File 'lib/ctypes/type.rb', line 149

def with_endian(value)
  return self if value == @endian

  endian = Endian[value]
  @with_endian ||= {}
  @with_endian[endian] ||= begin
    o = clone
    o.instance_variable_set(:@without_endian, self) unless @endian
    o.instance_variable_set(:@endian, endian)
    o
  end
end

#without_endianObject



162
163
164
165
166
167
168
# File 'lib/ctypes/type.rb', line 162

def without_endian
  @without_endian ||= begin
    o = clone
    o.remove_instance_variable(:@endian)
    o
  end
end