diff options
author | Stefano Pigozzi <stefano.pigozzi@gmail.com> | 2017-12-29 16:21:12 +0100 |
---|---|---|
committer | Stefano Pigozzi <stefano.pigozzi@gmail.com> | 2017-12-29 16:21:12 +0100 |
commit | 01502578393f1c08d27d15d279c13e05888ac72b (patch) | |
tree | 4225dbc454b89971fb801fcce3557e1758e17dae | |
parent | 5a5cc02793ad28ecdc50d3df66b7913a0b467ac6 (diff) | |
download | mpv-01502578393f1c08d27d15d279c13e05888ac72b.tar.bz2 mpv-01502578393f1c08d27d15d279c13e05888ac72b.tar.xz |
mruby: return api mpv queries as either monads
-rw-r--r-- | player/mruby.c | 12 | ||||
-rw-r--r-- | player/mruby/either.mrb | 49 | ||||
-rw-r--r-- | player/mruby/reply.mrb | 37 | ||||
-rw-r--r-- | player/mruby/test.mrb | 12 | ||||
-rw-r--r-- | wscript_build.py | 2 |
5 files changed, 63 insertions, 49 deletions
diff --git a/player/mruby.c b/player/mruby.c index f82fa54aaa..864043e7d0 100644 --- a/player/mruby.c +++ b/player/mruby.c @@ -34,8 +34,8 @@ #include "mpv_talloc.h" static const char * const mruby_scripts[][2] = { - {"mpv/reply.mrb", -# include "player/mruby/reply.inc" + {"mpv/either.mrb", +# include "player/mruby/either.inc" }, {"mpv/logging.mrb", # include "player/mruby/logging.inc" @@ -74,11 +74,11 @@ static int get_loglevel(char *level) static mrb_value api_return(mrb_state *mrb, int err, mrb_value value) { - const char* status = mpv_error_string(err); + bool ok = err == MPV_ERROR_SUCCESS; struct RClass *M = mrb_module_get(mrb, "M"); - struct RClass *c = mrb_class_get_under(mrb, M, "Reply"); - mrb_value init_args[2] = { value, mrb_str_new_cstr(mrb, status) }; - return mrb_obj_new(mrb, c, MP_ARRAY_SIZE(init_args), init_args); + struct RClass *c = mrb_class_get_under(mrb, M, ok ? "Right" : "Left"); + mrb_value val = ok ? value : mrb_str_new_cstr(mrb, mpv_error_string(err)); + return mrb_obj_new(mrb, c, 1, &val); } #define api_return_bool(mrb, err) api_return(mrb, err, mrb_bool_value(err >= 0)) diff --git a/player/mruby/either.mrb b/player/mruby/either.mrb new file mode 100644 index 0000000000..becec6c961 --- /dev/null +++ b/player/mruby/either.mrb @@ -0,0 +1,49 @@ +module M + class ReplyError < StandardError; end + + class Either + def initialize(value) + @value = value + end + + def to_s + "#<#{self.class.name} value=#{@value}>" + end + end + + class Left < Either + def map(&block) + self + end + + def get_or_else(value) + value + end + + def get! + raise ReplyError, @value + end + + def success? + false + end + end + + class Right < Either + def map(&block) + Right.new(block.call(@value)) + end + + def get_or_else(_value) + @value + end + + def get! + @value + end + + def success? + true + end + end +end diff --git a/player/mruby/reply.mrb b/player/mruby/reply.mrb deleted file mode 100644 index 4ae65dbd3f..0000000000 --- a/player/mruby/reply.mrb +++ /dev/null @@ -1,37 +0,0 @@ -module M - class ReplyError < StandardError; end - class Reply < Struct.new(:val, :status) - %w(b f i s).map{|type| "to_#{type}"}.map(&:intern).each do |method| - define_method(method) { unbox!.send(method) } - end - - def unbox(default=nil, &block) - unbox!(&block) - rescue ReplyError - default - end - - def unbox!(&block) - if success? - block_given? ? yield(val) : val - else - raise ReplyError, status - end - end - - private :val - - private - def success? - status == "success" - end - - def method_missing(method, *args, &block) - if success? and val.respond_to?(method) - val.send(method, *args, &block) - else - super - end - end - end -end diff --git a/player/mruby/test.mrb b/player/mruby/test.mrb index 4fb68d76ea..2a4f8687b1 100644 --- a/player/mruby/test.mrb +++ b/player/mruby/test.mrb @@ -5,8 +5,8 @@ end def with_unbox(a, &block) case [a.class] - when [M::Reply] then - a.unbox(&block) + when [M::Left], [M::Right] then + a.map(&block).get_or_else(false) else yield(a) end @@ -22,7 +22,8 @@ def assert_class(a, klass) end def assert_include(a, b) - raise "Expected:\n#{a}\nto include\n#{b}\n" unless a.include?(b) + raise "Expected:\n#{a}\nto include\n#{b}\n" \ + unless with_unbox(a) { |v| v.include?(b) } end def ok(s) @@ -55,7 +56,8 @@ def run end assert ".property_list returns an array" do - assert_class(M.get_property('property-list').val, Array) + assert_class(M.get_property('property-list').get!, Array) + assert_class(M.get_property('property-list'), Array) end assert ".property_list contains options" do @@ -67,7 +69,7 @@ assert ".get_property returns proper values" do assert_class(M.get_property("volume"), Float) assert_class(M.get_property("osd-width"), Fixnum) assert_class(M.get_property("vf"), Array) - assert_include([true, false], M.get_property("mute").unbox!) + assert_equal(M.get_property("mute"), false) end assert ".set_property works on complex types" do diff --git a/wscript_build.py b/wscript_build.py index 332bc9e596..8dc72aee96 100644 --- a/wscript_build.py +++ b/wscript_build.py @@ -109,7 +109,7 @@ def build(ctx): target = os.path.splitext(fn)[0] + ".inc", ) - mruby_files = ['events.mrb', 'logging.mrb', 'reply.mrb'] + mruby_files = ['events.mrb', 'logging.mrb', 'either.mrb'] for fn in mruby_files: fn = "player/mruby/" + fn ctx( |