diff options
author | Brice Videau <bvideau@anl.gov> | 2022-04-12 22:09:53 -0500 |
---|---|---|
committer | Brice Videau <bvideau@anl.gov> | 2022-04-12 22:20:43 -0500 |
commit | 5f71e6f9624e00bc0618005d5593a0b422df73b7 (patch) | |
tree | 01f8a0e31d110979772fc788ed61a18112f7b3c2 | |
parent | bdb4edeae927b1bf4d867175c21d110c17812fbd (diff) | |
download | ffi-5f71e6f9624e00bc0618005d5593a0b422df73b7.tar.gz |
Simplify from_native and test corner case.
-rw-r--r-- | lib/ffi/enum.rb | 8 | ||||
-rw-r--r-- | spec/ffi/bitmask_spec.rb | 17 |
2 files changed, 20 insertions, 5 deletions
diff --git a/lib/ffi/enum.rb b/lib/ffi/enum.rb index 903525e..83b6d89 100644 --- a/lib/ffi/enum.rb +++ b/lib/ffi/enum.rb @@ -280,15 +280,13 @@ module FFI # @param ctx unused # @return [Array<Symbol, Integer>] list of symbol names corresponding to val, plus an optional remainder if some bits don't match any constant def from_native(val, ctx) - list = @kv_map.select { |_, v| v & val != 0 }.keys + flags = @kv_map.select { |_, v| v & val != 0 } + list = flags.keys # If there are unmatch flags, # return them in an integer, # else information can be lost. # Similar to Enum behavior. - remainder = val ^ list.inject(0) do |tmp, o| - v = @kv_map[o] - if v then tmp |= v else tmp end - end + remainder = val ^ flags.values.reduce(0, :|) list.push remainder unless remainder == 0 return list end diff --git a/spec/ffi/bitmask_spec.rb b/spec/ffi/bitmask_spec.rb index 4a404b0..0cbccfa 100644 --- a/spec/ffi/bitmask_spec.rb +++ b/spec/ffi/bitmask_spec.rb @@ -248,6 +248,23 @@ describe "A tagged typedef bitmask" do expect(TestBitmask4.test_tagged_nonint_bitmask6([1<<14,1<<42,1<<43])).to eq([:c26,:c28,1<<43]) end + it "only remainder is given if only undefined mask are returned" do + expect(TestBitmask3.test_tagged_typedef_bitmask1(1<<4)).to eq([1<<4]) + expect(TestBitmask3.test_tagged_typedef_bitmask1([1<<4])).to eq([1<<4]) + expect(TestBitmask3.test_tagged_typedef_bitmask2(1<<6)).to eq([1<<6]) + expect(TestBitmask3.test_tagged_typedef_bitmask2([1<<6])).to eq([1<<6]) + expect(TestBitmask3.test_tagged_typedef_bitmask3(1<<7)).to eq([1<<7]) + expect(TestBitmask3.test_tagged_typedef_bitmask3([1<<7])).to eq([1<<7]) + expect(TestBitmask3.test_tagged_typedef_bitmask4(1<<9)).to eq([1<<9]) + expect(TestBitmask3.test_tagged_typedef_bitmask4([1<<9])).to eq([1<<9]) + expect(TestBitmask4.test_tagged_nonint_bitmask4(1<<10)).to eq([1<<10]) + expect(TestBitmask4.test_tagged_nonint_bitmask4([1<<10])).to eq([1<<10]) + expect(TestBitmask4.test_tagged_nonint_bitmask5(1<<16)).to eq([1<<16]) + expect(TestBitmask4.test_tagged_nonint_bitmask5([1<<16])).to eq([1<<16]) + expect(TestBitmask4.test_tagged_nonint_bitmask6(1<<43)).to eq([1<<43]) + expect(TestBitmask4.test_tagged_nonint_bitmask6([1<<43])).to eq([1<<43]) + end + it "wrong constants rejected" do expect { TestBitmask3.test_tagged_typedef_bitmask1([:c2,:c4,:c5]) }.to raise_error(ArgumentError) expect { TestBitmask3.test_tagged_typedef_bitmask2([:c6,:c8,:c9]) }.to raise_error(ArgumentError) |