<commit_before>require 'forwardable'
require 'gir_ffi/registered_type_base'

module GirFFI
  # Base class for all generated classes and structs. Contains code for dealing
  # with the generated nested Struct classes.
  class ClassBase
    extend RegisteredTypeBase
    extend Forwardable

    attr_reader :struct
    def_delegators :@struct, :to_ptr

    def setup_and_call method, arguments, &block
      method_name = self.class.try_in_ancestors(:setup_instance_method, method.to_s)

      unless method_name
        raise "Unable to set up instance method '#{method}' in #{self}"
      end

      send method_name, *arguments, &block
    end

    # NOTE: JRuby should fix FFI::MemoryPointer#== to return true for
    # equivalent FFI::Pointer. For now, user to_ptr.address
    def == other
      other.class == self.class && to_ptr.address == other.to_ptr.address
    end

    def self.setup_and_call method, arguments, &block
      method_name = try_in_ancestors(:setup_method, method.to_s)

      unless method_name
        raise "Unable to set up method '#{method}' in #{self}"
      end

      send method_name, *arguments, &block
    end

    def self.try_in_ancestors method, *arguments
      ancestors.each do |klass|
        if klass.respond_to?(method)
          result = klass.send(method, *arguments)
          return result if result
        end
      end
    end

    def self.to_ffi_type
      self::Struct
    end

    def self.setup_method name
      gir_ffi_builder.setup_method name
    end

    def self.setup_instance_method name
      gir_ffi_builder.setup_instance_method name
    end

    class << self
      undef new
    end

    # Wrap the passed pointer in an instance of the current class, or a
    # descendant type if applicable.
    def self.wrap ptr
      direct_wrap ptr
    end

    # Wrap the passed pointer in an instance of the current class. Will not
    # do any casting to subtypes.
    def self.direct_wrap ptr
      return nil if !ptr || ptr.null?
      obj = allocate
      obj.__send__ :store_pointer, ptr
      obj
    end

    # Pass-through casting method. This may become a type checking
    # method. It is overridden by GValue to implement wrapping of plain
    # Ruby objects.
    def self.from val
      val
    end

    #
    # Wraps a pointer retrieved from a constructor method. Here, it is simply
    # defined as a wrapper around direct_wrap, but, e.g., InitiallyUnowned
    # overrides it to sink the floating object.
    #
    # This method assumes the pointer will always be of the type corresponding
    # to the current class, and never of a subtype.
    #
    # @param ptr Pointer to the object's C structure
    #
    # @return An object of the current class wrapping the pointer
    #
    def self.constructor_wrap ptr
      direct_wrap ptr
    end

    private

    def store_pointer ptr
      @struct = self.class::Struct.new(ptr)
    end
  end
end<commit_msg>Ensure direct_wrap only assigns the pointer<commit_after>require 'forwardable'
require 'gir_ffi/registered_type_base'

module GirFFI
  # Base class for all generated classes and structs. Contains code for dealing
  # with the generated nested Struct classes.
  class ClassBase
    extend RegisteredTypeBase
    extend Forwardable

    attr_reader :struct
    def_delegators :@struct, :to_ptr

    def setup_and_call method, arguments, &block
      method_name = self.class.try_in_ancestors(:setup_instance_method, method.to_s)

      unless method_name
        raise "Unable to set up instance method '#{method}' in #{self}"
      end

      send method_name, *arguments, &block
    end

    # NOTE: JRuby should fix FFI::MemoryPointer#== to return true for
    # equivalent FFI::Pointer. For now, user to_ptr.address
    def == other
      other.class == self.class && to_ptr.address == other.to_ptr.address
    end

    def self.setup_and_call method, arguments, &block
      method_name = try_in_ancestors(:setup_method, method.to_s)

      unless method_name
        raise "Unable to set up method '#{method}' in #{self}"
      end

      send method_name, *arguments, &block
    end

    def self.try_in_ancestors method, *arguments
      ancestors.each do |klass|
        if klass.respond_to?(method)
          result = klass.send(method, *arguments)
          return result if result
        end
      end
    end

    def self.to_ffi_type
      self::Struct
    end

    def self.setup_method name
      gir_ffi_builder.setup_method name
    end

    def self.setup_instance_method name
      gir_ffi_builder.setup_instance_method name
    end

    class << self
      undef new
    end

    # Wrap the passed pointer in an instance of the current class, or a
    # descendant type if applicable.
    def self.wrap ptr
      direct_wrap ptr
    end

    # Wrap the passed pointer in an instance of the current class. Will not
    # do any casting to subtypes or additional processing.
    def self.direct_wrap ptr
      return nil if !ptr || ptr.null?
      obj = allocate
      obj.__send__ :assign_pointer, ptr
      obj
    end

    # Pass-through casting method. This may become a type checking
    # method. It is overridden by GValue to implement wrapping of plain
    # Ruby objects.
    def self.from val
      val
    end

    #
    # Wraps a pointer retrieved from a constructor method. Here, it is simply
    # defined as a wrapper around direct_wrap, but, e.g., InitiallyUnowned
    # overrides it to sink the floating object.
    #
    # This method assumes the pointer will always be of the type corresponding
    # to the current class, and never of a subtype.
    #
    # @param ptr Pointer to the object's C structure
    #
    # @return An object of the current class wrapping the pointer
    #
    def self.constructor_wrap ptr
      direct_wrap ptr
    end

    private

    def store_pointer ptr
      assign_pointer ptr
    end

    def assign_pointer ptr
      @struct = self.class::Struct.new(ptr)
    end
  end
end
{'fraction_non_alphanumeric': 0.05956165300317885, 'fraction_numerical': 0.0, 'mean_word_length': 2.5968712394705173, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1429179', 'n_tokens_mistral': 1742, 'n_tokens_neox': 1694, 'n_words': 639}