Module: Blusher::Native

Defined in:
lib/blusher/native.rb

Overview

The native boundary to the carmine engine. Coarse lex-or-decline contract: ‘Native.lex(table_json, input)` returns either

- an Array of [token_qualname, value] String pairs (carmine lexed it), or
- nil (a callback rule blocks native lexing → caller falls back to rouge).

Two backends, in preference order:

1. the rb-sys/magnus native extension (`blusher.{bundle,so}`), which
   builds the token Array DIRECTLY as Ruby objects — no JSON round-trip.
   This is the release path and the only one that beats rouge.
2. the `carmine-ffi` cdylib via Fiddle, marshaling tokens through JSON.
   A dependency-light bootstrap kept for environments without the
   precompiled ext; the JSON serialize/parse makes it a net loss vs rouge,
   so it exists for correctness/coverage, not speed.

Constant Summary collapse

DLEXT =
(RbConfig::CONFIG["host_os"] =~ /darwin/ ? "dylib" : "so")
DLEXT_RB =

— backend 1: magnus native extension ——————————– The loadable object’s name must match the ‘Init_blusher` symbol and use the platform’s Ruby ext suffix (.bundle/.so) — ‘require` won’t load a raw cargo ‘.dylib`. `rake compile` stages it here from the cargo target dir.

RbConfig::CONFIG["DLEXT"]
RUBY_ABI =

“3.4” — fat gems stage per ABI

RUBY_VERSION[/\d+\.\d+/]
EXT_CANDIDATES =
[
  # precompiled fat gem (rake-compiler stages per Ruby ABI): lib/blusher/3.4/blusher.<dlext>
  File.expand_path("#{RUBY_ABI}/blusher.#{DLEXT_RB}", __dir__),
  # source gem (create_rust_makefile installs here): lib/blusher/blusher.<dlext>
  File.expand_path("blusher.#{DLEXT_RB}", __dir__),
  # dev: `rake compile` stages the cargo build at lib/blusher.<dlext>
  File.expand_path("../blusher.#{DLEXT_RB}", __dir__),
  File.expand_path("../blusher.bundle", __dir__),
  File.expand_path("../blusher.so", __dir__),
].freeze
FFI_CANDIDATES =
[
  File.expand_path("../../ext/libcarmine_ffi.#{DLEXT}", __dir__),
  File.expand_path("../../../target/release/libcarmine_ffi.#{DLEXT}", __dir__),
  File.expand_path("../../../target/debug/libcarmine_ffi.#{DLEXT}", __dir__),
].freeze
LIB =
Fiddle.dlopen(path)
FFI_LEX =
Fiddle::Function.new(
  LIB["carmine_lex"],
  [Fiddle::TYPE_VOIDP, Fiddle::TYPE_VOIDP, Fiddle::TYPE_SIZE_T],
  Fiddle::TYPE_VOIDP
)
FFI_FREE =
Fiddle::Function.new(LIB["carmine_free"], [Fiddle::TYPE_VOIDP], Fiddle::TYPE_VOID)

Class Attribute Summary collapse

Class Method Summary collapse

Class Attribute Details

.backendObject (readonly)

Returns the value of attribute backend.



77
78
79
# File 'lib/blusher/native.rb', line 77

def backend
  @backend
end

Class Method Details

.format_html(_tag, _table_json, _input, _shortname) ⇒ Object

The FFI/JSON backend can’t fuse profitably (it would re-cross the JSON boundary); decline so the shim uses rouge’s formatter on FFI tokens.



93
94
95
# File 'lib/blusher/native.rb', line 93

def self.format_html(tag, table_json, input, shortname)
  Blusher::Engine.format_html(tag, table_json, input, shortname)
end

.fused_html?Boolean

Returns:

  • (Boolean)


116
117
118
# File 'lib/blusher/native.rb', line 116

def self.fused_html?
  @backend == :ext
end

.lex(_tag, table_json, input, qualname) ⇒ Object



86
87
88
# File 'lib/blusher/native.rb', line 86

def self.lex(tag, table_json, input, qualname)
  Blusher::Engine.lex(tag, table_json, input, qualname)
end