rinru 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/lib/rinru.rb +116 -0
- metadata +52 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: a738e53fa302793dce1926e5911d2f90281ecf114f12f0a987c477c1c2f47f28
|
|
4
|
+
data.tar.gz: 9a4b037d240916b2a14226020dcacc4786b2a3bb960ca134a5d79170ebc9eaa9
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: d211f7e8baa57b11c7583df4e53cb4c4c5520f602b613ed39b80194d30b2c9b04c3394ddce04c182b08009d55e1b4cf55125fed2d0b20ff9b097e50276232ac1
|
|
7
|
+
data.tar.gz: dd04b42572fa4c6d647f30a3179583ce5a747af6263c08869890b4ee42c697e0ab4e0878e92719f236f0455656178aa7e8eb3293d59641a4737c7a27ab07ced9
|
data/lib/rinru.rb
ADDED
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
require 'ffi'
|
|
2
|
+
require 'fileutils'
|
|
3
|
+
require 'tmpdir'
|
|
4
|
+
require 'digest'
|
|
5
|
+
|
|
6
|
+
class RinruEngine
|
|
7
|
+
extend FFI::Library
|
|
8
|
+
|
|
9
|
+
def initialize
|
|
10
|
+
@current_file = nil
|
|
11
|
+
@cargo_toml_path = nil
|
|
12
|
+
|
|
13
|
+
gem_root = File.expand_path('../..', __FILE__)
|
|
14
|
+
@shoved_cargo = File.join(gem_root, 'lib', 'rinru', 'bin', 'cargo')
|
|
15
|
+
@shoved_cargo = "cargo" unless File.exist?(@shoved_cargo)
|
|
16
|
+
|
|
17
|
+
@cache_dir = File.join(Dir.home, '.rinru_cache')
|
|
18
|
+
FileUtils.mkdir_p(@cache_dir)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def cargo(toml_path)
|
|
22
|
+
@cargo_toml_path = File.expand_path(toml_path)
|
|
23
|
+
self
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def var(file_path)
|
|
27
|
+
@current_file = File.expand_path(file_path)
|
|
28
|
+
self
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def as(variable_name)
|
|
32
|
+
raise "Rinru Error: No file specified." unless @current_file
|
|
33
|
+
raise "Rinru Error: File not found." unless File.exist?(@current_file)
|
|
34
|
+
|
|
35
|
+
var_name = variable_name.to_s.strip
|
|
36
|
+
|
|
37
|
+
# Track original code structure
|
|
38
|
+
rust_code = File.read(@current_file)
|
|
39
|
+
unless rust_code.include?('extern "C"')
|
|
40
|
+
rust_code = "#[no_mangle]\npub extern \"C\" #{rust_code}"
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
toml_content = @cargo_toml_path && File.exist?(@cargo_toml_path) ? File.read(@cargo_toml_path) : ""
|
|
44
|
+
|
|
45
|
+
# MD5 hash state tokenization
|
|
46
|
+
file_hash = Digest::MD5.hexdigest(rust_code + toml_content)
|
|
47
|
+
ext = Gem::Platform.local.os == 'darwin' ? 'dylib' : 'so'
|
|
48
|
+
binary_path = File.join(@cache_dir, "librinru_#{var_name}_#{file_hash}.#{ext}")
|
|
49
|
+
|
|
50
|
+
# COMPILATION WITH ROBUST ERROR CATCHING
|
|
51
|
+
unless File.exist?(binary_path)
|
|
52
|
+
build_dir = File.join(Dir.tmpdir, "rinru_#{var_name}")
|
|
53
|
+
FileUtils.mkdir_p(File.join(build_dir, "src"))
|
|
54
|
+
|
|
55
|
+
if @cargo_toml_path && File.exist?(@cargo_toml_path)
|
|
56
|
+
FileUtils.cp(@cargo_toml_path, File.join(build_dir, "Cargo.toml"))
|
|
57
|
+
else
|
|
58
|
+
File.write(File.join(build_dir, "Cargo.toml"), <<~TOML)
|
|
59
|
+
[package]
|
|
60
|
+
name = "rinru_#{var_name}"
|
|
61
|
+
version = "0.1.0"
|
|
62
|
+
edition = "2021"
|
|
63
|
+
[lib]
|
|
64
|
+
crate-type = ["cdylib"]
|
|
65
|
+
TOML
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
File.write(File.join(build_dir, "src", "lib.rs"), rust_code)
|
|
69
|
+
|
|
70
|
+
# Capture the compiler stderr outputs cleanly
|
|
71
|
+
compile_cmd = "CARGO_TARGET_DIR=#{build_dir}/target #{@shoved_cargo} build --manifest-path=#{build_dir}/Cargo.toml --release 2>&1"
|
|
72
|
+
compile_output = `#{compile_cmd}`
|
|
73
|
+
|
|
74
|
+
generated_binary = Dir.glob(File.join(build_dir, "target", "release", "*.#{ext}")).first
|
|
75
|
+
|
|
76
|
+
if generated_binary && File.exist?(generated_binary)
|
|
77
|
+
FileUtils.cp(generated_binary, binary_path)
|
|
78
|
+
# Clean up the heavy target workspace after successful build to save space
|
|
79
|
+
FileUtils.rm_rf(build_dir)
|
|
80
|
+
else
|
|
81
|
+
# INTERCEPT AND RAISE A CLEAN USER EXCEPTION INSTEAD OF CRASHING
|
|
82
|
+
raise LoadError, <<~ERR
|
|
83
|
+
|
|
84
|
+
========================================================================
|
|
85
|
+
Rinru Compilation Failure!
|
|
86
|
+
Your Rust code has syntax errors. Details below:
|
|
87
|
+
|
|
88
|
+
#{compile_output}
|
|
89
|
+
========================================================================
|
|
90
|
+
ERR
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
self.class.ffi_lib binary_path
|
|
95
|
+
|
|
96
|
+
engine_class = self.class
|
|
97
|
+
Kernel.send(:define_method, var_name) do |*args|
|
|
98
|
+
ffi_inputs = args.map { |arg| arg.is_a?(String) ? :string : :int }
|
|
99
|
+
|
|
100
|
+
begin
|
|
101
|
+
engine_class.attach_function var_name, ffi_inputs, :int
|
|
102
|
+
rescue FFI::NotFoundError, ArgumentError
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
engine_class.send(var_name, *args)
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
@current_file = nil
|
|
109
|
+
@cargo_toml_path = nil
|
|
110
|
+
true
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
def rinru
|
|
115
|
+
@rinru_instance ||= RinruEngine.new
|
|
116
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: rinru
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.1.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Developer
|
|
8
|
+
bindir: bin
|
|
9
|
+
cert_chain: []
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
11
|
+
dependencies:
|
|
12
|
+
- !ruby/object:Gem::Dependency
|
|
13
|
+
name: ffi
|
|
14
|
+
requirement: !ruby/object:Gem::Requirement
|
|
15
|
+
requirements:
|
|
16
|
+
- - "~>"
|
|
17
|
+
- !ruby/object:Gem::Version
|
|
18
|
+
version: '1.15'
|
|
19
|
+
type: :runtime
|
|
20
|
+
prerelease: false
|
|
21
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
22
|
+
requirements:
|
|
23
|
+
- - "~>"
|
|
24
|
+
- !ruby/object:Gem::Version
|
|
25
|
+
version: '1.15'
|
|
26
|
+
executables: []
|
|
27
|
+
extensions: []
|
|
28
|
+
extra_rdoc_files: []
|
|
29
|
+
files:
|
|
30
|
+
- lib/rinru.rb
|
|
31
|
+
homepage: https://github.com
|
|
32
|
+
licenses:
|
|
33
|
+
- MIT
|
|
34
|
+
metadata: {}
|
|
35
|
+
rdoc_options: []
|
|
36
|
+
require_paths:
|
|
37
|
+
- lib
|
|
38
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
39
|
+
requirements:
|
|
40
|
+
- - ">="
|
|
41
|
+
- !ruby/object:Gem::Version
|
|
42
|
+
version: '0'
|
|
43
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
44
|
+
requirements:
|
|
45
|
+
- - ">="
|
|
46
|
+
- !ruby/object:Gem::Version
|
|
47
|
+
version: '0'
|
|
48
|
+
requirements: []
|
|
49
|
+
rubygems_version: 4.0.22
|
|
50
|
+
specification_version: 4
|
|
51
|
+
summary: Rust-in-Ruby runtime variable method injector framework.
|
|
52
|
+
test_files: []
|