Module: Cobhan

Includes:
FFI::Library
Defined in:
lib/cobhan.rb,
lib/cobhan/version.rb

Overview

Cobhan module includes helper functions to manage unsafe data marshaling.

Constant Summary collapse

UnsupportedPlatformError =
Class.new(StandardError)
EXTS =
{ 'linux' => 'so', 'darwin' => 'dylib', 'windows' => 'dll' }.freeze
CPU_ARCHS =
{ 'x86_64' => 'x64', 'aarch64' => 'arm64' }.freeze
SIZEOF_INT32 =
32 / 8
BUFFER_HEADER_SIZE =
SIZEOF_INT32 * 2
VERSION =
'0.2.2'

Instance Method Summary collapse

Instance Method Details

#allocate_cbuffer(size) ⇒ Object



68
69
70
71
72
73
# File 'lib/cobhan.rb', line 68

def allocate_cbuffer(size)
  buffer_ptr = FFI::MemoryPointer.new(1, BUFFER_HEADER_SIZE + size, false)
  buffer_ptr.put_int32(0, size)
  buffer_ptr.put_int32(SIZEOF_INT32, 0) # Reserved - must be zero
  buffer_ptr
end

#buffer_to_int(buffer_ptr) ⇒ Object



81
82
83
# File 'lib/cobhan.rb', line 81

def buffer_to_int(buffer_ptr)
  buffer_ptr.get_int64(0)
end

#cbuffer_to_string(buffer) ⇒ Object



50
51
52
53
54
55
56
57
# File 'lib/cobhan.rb', line 50

def cbuffer_to_string(buffer)
  length = buffer.get_int32(0)
  if length >= 0
    buffer.get_bytes(BUFFER_HEADER_SIZE, length)
  else
    temp_to_string(buffer, length)
  end.force_encoding(Encoding::UTF_8)
end

#int_to_buffer(number) ⇒ Object



75
76
77
78
79
# File 'lib/cobhan.rb', line 75

def int_to_buffer(number)
  buffer_ptr = FFI::MemoryPointer.new(1, SIZEOF_INT32 * 2, false)
  buffer_ptr.put_int64(0, number)
  buffer_ptr
end

#library_file_name(name) ⇒ Object



19
20
21
22
23
24
25
26
27
28
29
# File 'lib/cobhan.rb', line 19

def library_file_name(name)
  ext = EXTS[FFI::Platform::OS]
  raise UnsupportedPlatformError, "Unsupported OS: #{FFI::Platform::OS}" unless ext

  cpu_arch = CPU_ARCHS[FFI::Platform::ARCH]
  raise UnsupportedPlatformError, "Unsupported CPU: #{FFI::Platform::ARCH}" unless cpu_arch

  libc_suffix = RbConfig::CONFIG['host_os'] == 'linux-musl' ? '-musl' : ''

  "#{name}-#{cpu_arch}#{libc_suffix}.#{ext}"
end

#load_library(lib_root_path, name, functions) ⇒ Object



31
32
33
34
35
36
37
38
39
40
# File 'lib/cobhan.rb', line 31

def load_library(lib_root_path, name, functions)
  # To load other libs that depend on relative paths, chdir to lib path dir.
  Dir.chdir(lib_root_path) do
    ffi_lib File.join(lib_root_path, library_file_name(name))
  end

  functions.each do |function|
    attach_function(*function)
  end
end

#string_to_cbuffer(input) ⇒ Object



42
43
44
45
46
47
48
# File 'lib/cobhan.rb', line 42

def string_to_cbuffer(input)
  buffer_ptr = FFI::MemoryPointer.new(1, BUFFER_HEADER_SIZE + input.bytesize, false)
  buffer_ptr.put_int32(0, input.bytesize)
  buffer_ptr.put_int32(SIZEOF_INT32, 0) # Reserved - must be zero
  buffer_ptr.put_bytes(BUFFER_HEADER_SIZE, input)
  buffer_ptr
end

#temp_to_string(buffer, length) ⇒ Object



59
60
61
62
63
64
65
66
# File 'lib/cobhan.rb', line 59

def temp_to_string(buffer, length)
  length = 0 - length
  filename = buffer.get_bytes(BUFFER_HEADER_SIZE, length)
  # Read file with name in payload, and replace payload
  bytes = File.binread(filename)
  File.delete(filename)
  bytes
end