summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStefano Pigozzi <stefano.pigozzi@gmail.com>2017-12-29 16:21:12 +0100
committerStefano Pigozzi <stefano.pigozzi@gmail.com>2017-12-29 16:21:12 +0100
commit01502578393f1c08d27d15d279c13e05888ac72b (patch)
tree4225dbc454b89971fb801fcce3557e1758e17dae
parent5a5cc02793ad28ecdc50d3df66b7913a0b467ac6 (diff)
downloadmpv-01502578393f1c08d27d15d279c13e05888ac72b.tar.bz2
mpv-01502578393f1c08d27d15d279c13e05888ac72b.tar.xz
mruby: return api mpv queries as either monads
-rw-r--r--player/mruby.c12
-rw-r--r--player/mruby/either.mrb49
-rw-r--r--player/mruby/reply.mrb37
-rw-r--r--player/mruby/test.mrb12
-rw-r--r--wscript_build.py2
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(