1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00

Define Struct#deconstruct_keys

This commit is contained in:
Kazuki Tsujimoto 2019-11-08 11:37:07 +09:00
parent 7661150109
commit d4da74ea78
No known key found for this signature in database
GPG key ID: BCEA306C49B81CD7
3 changed files with 64 additions and 0 deletions

View file

@ -944,6 +944,33 @@ rb_struct_to_h(VALUE s)
return h;
}
static VALUE
rb_struct_deconstruct_keys(VALUE s, VALUE keys)
{
VALUE h;
long i;
if (NIL_P(keys)) {
return rb_struct_to_h(s);
}
if (UNLIKELY(!RB_TYPE_P(keys, T_ARRAY))) {
rb_raise(rb_eTypeError,
"wrong argument type %"PRIsVALUE" (expected Array or nil)",
rb_obj_class(keys));
}
h = rb_hash_new_with_size(RARRAY_LEN(keys));
for (i=0; i<RARRAY_LEN(keys); i++) {
VALUE key = RARRAY_AREF(keys, i);
int i = rb_struct_pos(s, &key);
if (i < 0) {
return rb_hash_new_with_size(0);
}
rb_hash_aset(h, key, RSTRUCT_GET(s, i));
}
return h;
}
/* :nodoc: */
VALUE
rb_struct_init_copy(VALUE copy, VALUE s)
@ -1357,6 +1384,7 @@ InitVM_Struct(void)
rb_define_method(rb_cStruct, "dig", rb_struct_dig, -1);
rb_define_method(rb_cStruct, "deconstruct", rb_struct_to_a, 0);
rb_define_method(rb_cStruct, "deconstruct_keys", rb_struct_deconstruct_keys, 1);
}
#undef rb_intern

View file

@ -1230,6 +1230,30 @@ END
true
end
end
s = Struct.new(:a, :b, keyword_init: true)
assert_block do
case s[a: 0, b: 1]
in **r
r == {a: 0, b: 1}
end
end
assert_block do
s = Struct.new(:a, :b, keyword_init: true)
case s[a: 0, b: 1]
in a:, b:
a == 0 && b == 1
end
end
assert_block do
s = Struct.new(:a, :b, keyword_init: true)
case s[a: 0, b: 1]
in a:, c:
flunk
in b:
b == 1
end
end
end
################################################################

View file

@ -431,6 +431,18 @@ module TestStruct
}
end
def test_deconstruct_keys
klass = @Struct.new(:a, :b)
o = klass.new(1, 2)
assert_equal({a: 1, b: 2}, o.deconstruct_keys(nil))
assert_equal({a: 1, b: 2}, o.deconstruct_keys([:b, :a]))
assert_equal({a: 1}, o.deconstruct_keys([:a]))
assert_equal({}, o.deconstruct_keys([:a, :c]))
assert_raise(TypeError) {
o.deconstruct_keys(0)
}
end
class TopStruct < Test::Unit::TestCase
include TestStruct