|
# System backend controller |
|
module PluggableSystem::Env |
|
#include BackendController |
|
|
|
OS_BACKEND = Crystal::System::Env::PLUGGABLESYSTEM_OS_BACKEND |
|
|
|
class_getter current_impl : Interface = OS_BACKEND |
|
|
|
protected def self.set_current_impl(impl : Interface) : Nil |
|
current_impl.__on_deinit |
|
@@current_impl = impl |
|
current_impl.__on_init |
|
end |
|
|
|
def self.use(impl : Interface) |
|
self.set_current_impl(impl) |
|
end |
|
|
|
def self.use_os |
|
self.set_current_impl(OS_BACKEND) |
|
end |
|
|
|
def self.halt |
|
end |
|
|
|
def self.resume |
|
end |
|
|
|
#-------------------------------------- |
|
|
|
module Interface |
|
annotation DefineSystemFunc; end |
|
|
|
macro freeze_interface! |
|
# Well, it doesn't 'freeze' anything.. |
|
|
|
{% for def_node in @type.methods.select { |d| d.annotation(DefineSystemFunc) } %} |
|
# use def_node here! |
|
{% end %} |
|
end |
|
|
|
@[DefineSystemFunc(:set)] |
|
abstract def set(key : String, value : String) : Nil |
|
|
|
@[DefineSystemFunc(:unset)] |
|
abstract def set(key : String, value : Nil) : Nil |
|
|
|
@[DefineSystemFunc(:get)] |
|
abstract def get(key : String) : String? |
|
|
|
@[DefineSystemFunc(:has?)] |
|
abstract def has_key?(key : String) : Bool |
|
|
|
@[DefineSystemFunc(:each)] |
|
abstract def each(&block : String, String ->) |
|
|
|
freeze_interface! |
|
|
|
# backend hooks |
|
|
|
# Hook called when the backend is going to be activated |
|
def __on_init |
|
end |
|
|
|
# Hook called when the backend is going to be halted (desactivated temporarily) |
|
def __on_halt |
|
end |
|
|
|
# Hook called when the backend is going to be resumed (after being halted) |
|
def __on_unhalt |
|
end |
|
|
|
# Hook called when the backend is going to be desactivated |
|
def __on_deinit |
|
end |
|
|
|
# need macro on 'finished' that checks that all system funcs are implemented? |
|
# (with types..) |
|
end |
|
end |
|
|
|
class PluggableSystem::BackendWrapper(T) |
|
include PluggableSystem::Env::Interface |
|
|
|
def initialize(@mod_impl : T.class) |
|
end |
|
|
|
def set(key : String, value : String) : Nil |
|
@mod_impl.set(key, value) |
|
end |
|
|
|
def set(key : String, value : Nil) : Nil |
|
@mod_impl.set(key, value) |
|
end |
|
|
|
def get(key : String) : String? |
|
puts "env wrapper: get #{key}" |
|
@mod_impl.get(key) |
|
end |
|
|
|
def has_key?(key : String) : Bool |
|
@mod_impl.has_key?(key) |
|
end |
|
|
|
def each(&block : String, String ->) |
|
@mod_impl.each(&block) |
|
end |
|
|
|
# backend hooks |
|
|
|
def __on_init |
|
if (mod = @mod_impl).responds_to? :__on_init |
|
mod.__on_init |
|
end |
|
end |
|
|
|
def __on_halt |
|
if (mod = @mod_impl).responds_to? :__on_halt |
|
mod.__on_halt |
|
end |
|
end |
|
|
|
def __on_unhalt |
|
if (mod = @mod_impl).responds_to? :__on_unhalt |
|
mod.__on_unhalt |
|
end |
|
end |
|
|
|
def __on_deinit |
|
if (mod = @mod_impl).responds_to? :__on_deinit |
|
mod.__on_deinit |
|
end |
|
end |
|
end |
|
|
|
module Crystal::System::Env |
|
PLUGGABLESYSTEM_OS_BACKEND = PluggableSystem::BackendWrapper.new(Crystal::System::Env) |
|
|
|
# Override all the things! \o/ |
|
|
|
def self.set(key : String, value : String) : Nil |
|
impl = PluggableSystem::Env.current_impl |
|
if impl == PLUGGABLESYSTEM_OS_BACKEND |
|
puts "system env: set #{key} → #{value}" |
|
previous_def |
|
else |
|
impl.set(key, value) |
|
end |
|
end |
|
|
|
def self.set(key : String, value : Nil) : Nil |
|
impl = PluggableSystem::Env.current_impl |
|
if impl == PLUGGABLESYSTEM_OS_BACKEND |
|
puts "system env: unset #{key}" |
|
previous_def |
|
else |
|
impl.set(key, value) |
|
end |
|
end |
|
|
|
def self.get(key : String) : String? |
|
impl = PluggableSystem::Env.current_impl |
|
|
|
if impl == PLUGGABLESYSTEM_OS_BACKEND |
|
puts "system env: get #{key}" |
|
previous_def |
|
else |
|
impl.get(key) |
|
end |
|
end |
|
|
|
def self.has_key?(key : String) : Bool |
|
impl = PluggableSystem::Env.current_impl |
|
if impl == PLUGGABLESYSTEM_OS_BACKEND |
|
puts "system env: has? #{key}" |
|
previous_def |
|
else |
|
impl.has_key?(key) |
|
end |
|
end |
|
|
|
def self.each(&block : String, String ->) |
|
impl = PluggableSystem::Env.current_impl |
|
if impl == PLUGGABLESYSTEM_OS_BACKEND |
|
puts "system env: each" |
|
previous_def |
|
else |
|
# FIXME: ENV.to_h doesn't compile with this.. |
|
impl.each(&block) |
|
end |
|
end |
|
end |