hugopl/gi-crystal

::Bytes should be used on array of unsigned chars parameters

Closed this issue · 0 comments

This example is from Gio module.

def self.content_type_guess(filename : ::String?, data : Enumerable(UInt8)?) : ::String
  # g_content_type_guess: (None)
  # @filename: (nullable)
  # @data: (nullable) (array length=data_size element-type UInt8)
  # @data_size:
  # @result_uncertain: (out) (transfer full) (optional)
  # Returns: (transfer full)

  # Generator::NullableArrayPlan
  filename = if filename.nil?
               Pointer(LibC::Char).null
             else
               filename.to_unsafe
             end
  # Generator::ArrayLengthArgPlan
  data_size = data.try(&.size) || 0 # Generator::NullableArrayPlan
  data = if data.nil?
           Pointer(UInt8).null
         else
           data.to_a.to_unsafe
         end
  # Generator::OutArgUsedInReturnPlan
  result_uncertain = Pointer(LibC::Int).null
  # C call
  _retval = LibGio.g_content_type_guess(filename, data, data_size, result_uncertain)

  # Return value handling
  GICrystal.transfer_full(_retval)
end

This function accepts Bytes already, however it does a data.to_a.to_unsafe to be sure that all bytes are contiguous in memory, and this will be really slow if the type isn't already an Array.

Since 99% of the times in C APIs array of unsigned char means some buffer, Crystal ::Bytes is the type that must be used here.