From d750528f06db1e0914cc27caa768f7320f1e6fd2 Mon Sep 17 00:00:00 2001 From: Felipe Pena Date: Sat, 1 Jun 2024 18:44:28 -0300 Subject: [PATCH] parser: allow multiple flag values in enum.from() for flag enums (fix #21569) (#21615) --- vlib/v/parser/parser.v | 19 +++++++++++-------- vlib/v/tests/enum_flag_from_test.v | 21 +++++++++++++++++++++ 2 files changed, 32 insertions(+), 8 deletions(-) create mode 100644 vlib/v/tests/enum_flag_from_test.v diff --git a/vlib/v/parser/parser.v b/vlib/v/parser/parser.v index 213cd751ccf20e..23abfd95d8bf4d 100644 --- a/vlib/v/parser/parser.v +++ b/vlib/v/parser/parser.v @@ -4161,15 +4161,18 @@ fn (mut p Parser) enum_decl() ast.EnumDecl { isb.write_string(' val := unsafe{ ${enum_name}(input) }\n') if is_flag { isb.write_string(' if input == 0 { return val }\n') + all_bits_set_value := '0b' + '1'.repeat(fields.len) + isb.write_string(' if input & ~${all_bits_set_value} == 0 { return val }\n') + } else { + isb.write_string(' match val {\n') + for f in fields { + isb.write_string(' .${f.source_name} { return ${enum_name}.${f.source_name} }\n') + } + if is_flag { + isb.write_string(' else{}\n') + } + isb.write_string(' }\n') } - isb.write_string(' match val {\n') - for f in fields { - isb.write_string(' .${f.source_name} { return ${enum_name}.${f.source_name} }\n') - } - if is_flag { - isb.write_string(' else{}\n') - } - isb.write_string(' }\n') isb.write_string(' }\n') isb.write_string(' \$if input is \$string {\n') isb.write_string(' val := input.str()\n') // TODO: this should not be needed, the `$if input is $string` above should have already smartcasted `input` diff --git a/vlib/v/tests/enum_flag_from_test.v b/vlib/v/tests/enum_flag_from_test.v new file mode 100644 index 00000000000000..70fffa4927f503 --- /dev/null +++ b/vlib/v/tests/enum_flag_from_test.v @@ -0,0 +1,21 @@ +@[flag] +pub enum Flag as u8 { + flag0 + flag1 + flag2 + flag3 + flag4 + flag5 + flag6 + flag7 +} + +fn test_ok() { + a := Flag.from(0b10101110) or { panic(err) } + assert a == Flag.flag1 | .flag2 | .flag3 | .flag5 | .flag7 +} + +fn test_fail() { + a := Flag.from(0b110101110) or { Flag(Flag.flag0) } + assert a == Flag.flag0 +}