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
MINIMUM_ALLOCATION =
1024
VERSION =
'0.1.2'

Instance Method Summary collapse

Instance Method Details

#allocate_cbuffer(size) ⇒ Object



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

def allocate_cbuffer(size)
  size = [size, MINIMUM_ALLOCATION].max
  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



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

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
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



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

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

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

#load_library(lib_root_path, name, functions) ⇒ Object



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

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



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

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



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

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