class FFI::Struct

def self.alignment

def self.alignment
  @layout.alignment
end

def self.auto_ptr

def self.auto_ptr
  @managed_type ||= Type::Mapped.new(ManagedStructConverter.new(self))
end

def self.by_ref(flags = :inout)

def self.by_ref(flags = :inout)
  self.ptr(flags)
end

def self.by_value

def self.by_value
  self.val
end

def self.in

def self.in
  ptr(:in)
end

def self.members

def self.members
  @layout.members
end

def self.offset_of(name)

def self.offset_of(name)
  @layout.offset_of(name)
end

def self.offsets

def self.offsets
  @layout.offsets
end

def self.out

def self.out
  ptr(:out)
end

def self.ptr(flags = :inout)

def self.ptr(flags = :inout)
  @ref_data_type ||= Type::Mapped.new(StructByReference.new(self))
end

def self.size

def self.size
  defined?(@layout) ? @layout.size : defined?(@size) ? @size : 0
end

def self.size=(size)

def self.size=(size)
  raise ArgumentError, "Size already set" if defined?(@size) || defined?(@layout)
  @size = size
end

def self.val

def self.val
  @val_data_type ||= StructByValue.new(self)
end

def aligned(alignment = 1)

def aligned(alignment = 1)
  @min_alignment = alignment
end

def alignment

def alignment
  self.class.alignment
end

def array_layout(builder, spec)

def array_layout(builder, spec)
  i = 0
  while i < spec.size
    name, type = spec[i, 2]
    i += 2
    # If the next param is a Integer, it specifies the offset
    if spec[i].kind_of?(Integer)
      offset = spec[i]
      i += 1
    else
      offset = nil
    end
    builder.add name, find_field_type(type), offset
  end
end

def callback(params, ret)

def callback(params, ret)
  mod = enclosing_module
  FFI::CallbackInfo.new(find_type(ret, mod), params.map { |e| find_type(e, mod) })
end

def clear

def clear
  pointer.clear
  self
end

def enclosing_module

def enclosing_module
  begin
    mod = self.name.split("::")[0..-2].inject(Object) { |obj, c| obj.const_get(c) }
    mod.respond_to?(:find_type) ? mod : nil
  rescue Exception
    nil
  end
end

def find_field_type(type, mod = enclosing_module)

def find_field_type(type, mod = enclosing_module)
  if type.kind_of?(Class) && type < Struct
    FFI::Type::Struct.new(type)
  elsif type.kind_of?(Class) && type < FFI::StructLayout::Field
    type
  elsif type.kind_of?(::Array)
    FFI::Type::Array.new(find_field_type(type[0]), type[1])
  else
    find_type(type, mod)
  end
end

def find_type(type, mod = enclosing_module)

def find_type(type, mod = enclosing_module)
  if mod
    mod.find_type(type)
  end || FFI.find_type(type)
end

def hash_layout(builder, spec)

def hash_layout(builder, spec)
  raise "Ruby version not supported" if RUBY_VERSION =~ /1.8.*/
  spec[0].each do |name, type|
    builder.add name, find_field_type(type), nil
  end
end

def layout(*spec)

def layout(*spec)
   raise RuntimeError, "struct layout already defined for #{self.inspect}" if defined?(@layout)
  return @layout if spec.size == 0
  builder = StructLayoutBuilder.new
  builder.union = self < Union
  builder.packed = @packed if defined?(@packed)
  builder.alignment = @min_alignment if defined?(@min_alignment)
  if spec[0].kind_of?(Hash)
    hash_layout(builder, spec)
  else
    array_layout(builder, spec)
  end
  builder.size = @size if defined?(@size) && @size > builder.size
  cspec = builder.build
  @layout = cspec unless self == Struct
  @size = cspec.size
  return cspec
end

def members

def members
  self.class.members
end

def offset_of(name)

def offset_of(name)
  self.class.offset_of(name)
end

def offsets

def offsets
  self.class.offsets
end

def packed(packed = 1)

def packed(packed = 1)
  @packed = packed
end

def size

def size
  self.class.size
end

def to_ptr

def to_ptr
  pointer
end

def values

def values
  members.map { |m| self[m] }
end