Method: CTypes::Struct::Builder#attribute

Defined in:
lib/ctypes/struct/builder.rb

#attribute(name, type = nil) ⇒ Object

declare an attribute in the structure This function supports the use of CTypes::Struct and Union types for declaring unnamed fields (ISO C11). See example below for more details.

Examples:

attribute(:name, string)

add an attribute with a struct type

include CTypes::Helpers
attribute(:header, struct(id: uint32, len: uint32))

add an unnamed field (ISO C11)

include CTypes::Helpers

# declare the type to be used in the unnamed field
header = struct(id: uint32, len: uint32)

# create our struct type with an unnamed field
t = struct do
  # add the unnamed field, in this case the header type
  attribute(header)

  # add any other field needed in the struct
  attribute(:body, string)
  size { |struct| struct[:len] }
end

# now unpack an instance of the struct type
packet = t.unpack("\x01\0\0\0\x13\0\0\0hello worldXXX")

# access the unnamed struct fields directly by the inner names
p.id    # => 1
p.len   # => 19

# access the body
p.body  # => "hello world"

Parameters:

  • name

    name of the attribute, optional for unnamed fields

  • type (CTypes::Type) (defaults to: nil)

    type of the field



141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
# File 'lib/ctypes/struct/builder.rb', line 141

def attribute(name, type = nil)
  # handle a named field
  if type
    name = name.to_sym
    if @default.has_key?(name)
      raise Error, "duplicate field name: %p" % name
    end

    @fields << [name, type]
    @schema << Dry::Types::Schema::Key.new(type.dry_type, name)
    @default[name] = type.default_value

  # handle the unnamed field by adding the child fields to our type
  else
    type = name
    dry_keys = type.dry_type.keys or
      raise Error, "unsupported type for unnamed field: %p" % [type]
    names = dry_keys.map(&:name)

    if (duplicate = names.any? { |n| @default.has_key?(n) })
      raise Error, "duplicate field name %p in unnamed field: %p" %
        [duplicate, type]
    end

    @fields << [names, type]
    @schema += dry_keys
    @default.merge!(type.default_value)
  end

  # adjust the byte count for this type
  if @bytes && type.fixed_size?
    @bytes += type.size
  else
    @bytes = nil
  end

  self
end