diff --git a/src/AvroConvert/AvroObjectServices/Schemas/EnumSchema.cs b/src/AvroConvert/AvroObjectServices/Schemas/EnumSchema.cs index 5d8c6552..04fb306b 100644 --- a/src/AvroConvert/AvroObjectServices/Schemas/EnumSchema.cs +++ b/src/AvroConvert/AvroObjectServices/Schemas/EnumSchema.cs @@ -83,7 +83,7 @@ internal EnumSchema( int v = Convert.ToInt32(values.GetValue(i), CultureInfo.InvariantCulture); this.avroToCSharpValueMapping.Add(Convert.ToInt64(values.GetValue(i), CultureInfo.InvariantCulture)); this.symbolToValue.Add(this.symbols[i], v); - this.valueToSymbol.Add(v, this.symbols[i]); + this.valueToSymbol.TryAdd(v, this.symbols[i]); } } } @@ -92,6 +92,9 @@ internal EnumSchema( internal bool TryGetSymbolValue(string symbol, out int value) => this.symbolToValue.TryGetValue(symbol, out value); + + internal int GetSymbolPosition(string symbol) => + this.symbols.IndexOf(symbol); internal string GetSymbolByValue(int value) { diff --git a/src/AvroConvert/AvroObjectServices/Write/Resolvers/Enum.cs b/src/AvroConvert/AvroObjectServices/Write/Resolvers/Enum.cs index 61c0028d..6b13dd89 100644 --- a/src/AvroConvert/AvroObjectServices/Write/Resolvers/Enum.cs +++ b/src/AvroConvert/AvroObjectServices/Write/Resolvers/Enum.cs @@ -36,14 +36,14 @@ internal Encoder.WriteItem ResolveEnum(EnumSchema schema) { value = EnumParser.GetEnumName(enumType, value.ToString()); } - - if (!schema.TryGetSymbolValue(value.ToString(), out var symbolValue)) + var position = schema.GetSymbolPosition(value.ToString()); + if (position < 0) { throw new AvroTypeException( $"[Enum] Provided value is not of the enum [{schema.Name}] members"); } - e.WriteEnum(symbolValue); + e.WriteEnum(position); }; } } diff --git a/tests/AvroConvertTests/FullSerializationAndDeserialization/EnumTests.cs b/tests/AvroConvertTests/FullSerializationAndDeserialization/EnumTests.cs index 75273bc0..941f449d 100644 --- a/tests/AvroConvertTests/FullSerializationAndDeserialization/EnumTests.cs +++ b/tests/AvroConvertTests/FullSerializationAndDeserialization/EnumTests.cs @@ -146,5 +146,44 @@ public void Class_with_enum_with_member_value_attributes(Func engine) + { + var itemsToTest = + new [] { + TestDuplicateEnum.Test, + TestDuplicateEnum.Exam, //Compilation already sets these values to the primary duplicate value. + TestDuplicateEnum.Error, + TestDuplicateEnum.Fail, + TestDuplicateEnum.TestLabel, + TestDuplicateEnum.TestLabel2 + }; + + foreach (var toSerialize in itemsToTest) + { + //Act + var deserialized = engine.Invoke(toSerialize, typeof(TestDuplicateEnum)); + + //Assert + Assert.Equal((int)toSerialize, (int)deserialized); + } + } + + [Theory] + [MemberData(nameof(TestEngine.All), MemberType = typeof(TestEngine))] + public void Class_with_enum_with_duplicate_value(Func engine) + { + //Arrange + ClassWithDuplicateEnums toSerialize = _fixture.Create(); + + //Act + var deserialized = engine.Invoke(toSerialize, typeof(ClassWithDuplicateEnums)); + + //Assert + Assert.NotNull(deserialized); + Assert.Equal(toSerialize, deserialized); + } } } diff --git a/tests/AvroConvertTests/TestClasses.cs b/tests/AvroConvertTests/TestClasses.cs index 597235f3..55c34ec6 100644 --- a/tests/AvroConvertTests/TestClasses.cs +++ b/tests/AvroConvertTests/TestClasses.cs @@ -353,6 +353,25 @@ public class ClassWithEnum public TestEnum? SecondEnumProp { get; set; } } + public enum TestDuplicateEnum { + Test = 0, + Exam = Test, + Fail = 1, + Error = Fail, + TestLabel = 2, + TestLabel2 = 2 + } + + [Equals(DoNotAddEqualityOperators = true)] + public class ClassWithDuplicateEnums { + [DefaultValue(TestDuplicateEnum.Fail)] + public TestDuplicateEnum? EnumProp { get; set; } + [DefaultValue("Error")] + public TestDuplicateEnum? EnumProp2 { get; set;} + [DefaultValue(2)] + public TestDuplicateEnum? EnumProp3 { get; set; } + } + public class ClassWithEnumDefiningMembers { public TestEnumWithMembers? EnumProp { get; set; }