Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docfx/docs/built-in-converters.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ Enums, arrays and various dictionary types that utilize these types are implicit
## Other

- @System.Boolean
- @System.Drawing.Color
- <xref:System.Drawing.Color> - represented by an ARGB integer, or the boolean `false` for `Color.Empty`.
- @System.Globalization.CultureInfo
- @System.Text.Encoding
- @System.EventArgs
Expand Down
32 changes: 27 additions & 5 deletions src/Nerdbank.MessagePack/Converters/BclConverters.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,17 +16,39 @@ namespace Nerdbank.MessagePack.Converters;
internal class SystemDrawingColorConverter : MessagePackConverter<Color>
{
public override Color Read(ref MessagePackReader reader, SerializationContext context)
=> Color.FromArgb(reader.ReadInt32());
{
if (reader.NextMessagePackType == MessagePackType.Boolean)
{
if (!reader.ReadBoolean())
{
return Color.Empty;
}

throw new MessagePackSerializationException("Unexpected true value while deserializing System.Drawing.Color.");
}

return Color.FromArgb(reader.ReadInt32());
}

public override void Write(ref MessagePackWriter writer, in Color value, SerializationContext context)
=> writer.Write(value.ToArgb());
{
if (value.IsEmpty)
{
writer.Write(false);
}
else
{
writer.Write(value.ToArgb());
}
}

public override JsonObject? GetJsonSchema(JsonSchemaContext context, ITypeShape typeShape)
=> new()
{
["type"] = "integer",
["format"] = "int32",
["description"] = "An ARGB color value.",
["anyOf"] = new JsonArray(
new JsonObject { ["type"] = "boolean", ["enum"] = new JsonArray(false) },
new JsonObject { ["type"] = "integer", ["format"] = "int32" }),
Comment thread
AArnott marked this conversation as resolved.
Resolved
["description"] = "An ARGB color value, or false for Color.Empty.",
};
}

Expand Down
35 changes: 35 additions & 0 deletions test/Nerdbank.MessagePack.TUnit/BuiltInConverterTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,40 @@ public partial class BuiltInConverterTests : MessagePackSerializerTestBase
[Test]
public void SystemDrawingColor() => this.AssertRoundtrip<Color, Witness>(Color.FromArgb(1, 2, 3, 4));

[Test]
public void SystemDrawingColor_Empty()
{
ReadOnlySequence<byte> msgpack = this.AssertRoundtrip<Color, Witness>(Color.Empty);
Assert.Equal(MessagePackType.Boolean, new MessagePackReader(msgpack).NextMessagePackType);
Assert.True(this.Serializer.Deserialize<Color, Witness>(msgpack, this.TimeoutToken).IsEmpty);
}

[Test]
public void SystemDrawingColor_TransparentBlack()
{
Color transparentBlack = Color.FromArgb(0);
ReadOnlySequence<byte> msgpack = this.AssertRoundtrip<Color, Witness>(transparentBlack);
Assert.Equal(MessagePackType.Integer, new MessagePackReader(msgpack).NextMessagePackType);
Assert.False(this.Serializer.Deserialize<Color, Witness>(msgpack, this.TimeoutToken).IsEmpty);
}

[Test]
public void NullableSystemDrawingColor_Null()
{
ReadOnlySequence<byte> msgpack = this.AssertRoundtrip<Color?, Witness>(null);
Assert.Equal(MessagePackType.Nil, new MessagePackReader(msgpack).NextMessagePackType);
Assert.Null(this.Serializer.Deserialize<Color?, Witness>(msgpack, this.TimeoutToken));
}

[Test]
public void NullableSystemDrawingColor_Empty()
{
ReadOnlySequence<byte> msgpack = this.AssertRoundtrip<Color?, Witness>(Color.Empty);
Color? result = this.Serializer.Deserialize<Color?, Witness>(msgpack, this.TimeoutToken);
Assert.True(result.HasValue);
Assert.True(result.Value.IsEmpty);
}

[Test]
public void SystemDrawingPoint() => this.AssertRoundtrip<Point, Witness>(new Point(1, 1));

Expand Down Expand Up @@ -596,6 +630,7 @@ public partial record HasDateTimeOffset(DateTimeOffset Value);
[GenerateShapeFor<Guid>]
[GenerateShapeFor<Point>]
[GenerateShapeFor<Color>]
[GenerateShapeFor<Color?>]
[GenerateShapeFor<byte[]>]
[GenerateShapeFor<CultureInfo>]
[GenerateShapeFor<EventArgs>]
Expand Down
13 changes: 13 additions & 0 deletions test/Nerdbank.MessagePack.TUnit/SchemaTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#endif

using System.ComponentModel;
using System.Drawing;
using System.Globalization;
using System.Reflection;
using System.Runtime.CompilerServices;
Expand Down Expand Up @@ -42,6 +43,15 @@ internal enum Sex
Female,
}

[Test, MatrixDataSource]
public void NullableColorSchema(JsonSchemaDialect dialect)
{
JsonObject schema = this.Serializer.GetJsonSchema<HasNullableColors>(new JsonSchemaOptions { Dialect = dialect });
JSchema parsedSchema = JSchema.Parse(SchemaToString(schema));
JToken.Parse("""{"Color":null,"Colors":[null,false,0]}""").Validate(parsedSchema);
Assert.False(JToken.Parse("""{"Color":true,"Colors":[]}""").IsValid(parsedSchema));
}

[Test, MatrixDataSource]
public void BasicObject_Map(JsonSchemaDialect dialect) => this.AssertSchema(dialect, [new BasicObject { IntProperty = 3, StringProperty = "hi" }]);

Expand Down Expand Up @@ -514,4 +524,7 @@ public override void Write(ref MessagePackWriter writer, in CustomType? value, S
writer.WriteMapHeader(0);
}
}

[GenerateShape]
public partial record HasNullableColors(Color? Color, Color?[] Colors);
}
Loading