Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added more node ID value serializers. #7538

Merged
merged 1 commit into from
Sep 30, 2024
Merged
Show file tree
Hide file tree
Changes from all 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
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,9 @@ public static IRequestExecutorBuilder AddDefaultNodeIdSerializer(
builder.Services.AddSingleton<INodeIdValueSerializer, Int32NodeIdValueSerializer>();
builder.Services.AddSingleton<INodeIdValueSerializer, Int64NodeIdValueSerializer>();
builder.Services.AddSingleton<INodeIdValueSerializer>(new GuidNodeIdValueSerializer(compress: outputNewIdFormat));
builder.Services.AddSingleton<INodeIdValueSerializer, DecimalNodeIdValueSerializer>();
builder.Services.AddSingleton<INodeIdValueSerializer, SingleNodeIdValueSerializer>();
builder.Services.AddSingleton<INodeIdValueSerializer, DoubleNodeIdValueSerializer>();
}

builder.Services.TryAddSingleton<INodeIdSerializer>(sp =>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
#nullable enable
using System.Buffers.Text;
using System.Diagnostics.CodeAnalysis;

namespace HotChocolate.Types.Relay;

internal sealed class DecimalNodeIdValueSerializer : INodeIdValueSerializer
{
public bool IsSupported(Type type) => type == typeof(decimal) || type == typeof(decimal?);

public NodeIdFormatterResult Format(Span<byte> buffer, object value, out int written)
{
if (value is decimal i)
{
return Utf8Formatter.TryFormat(i, buffer, out written)
? NodeIdFormatterResult.Success
: NodeIdFormatterResult.BufferTooSmall;
}

written = 0;
return NodeIdFormatterResult.InvalidValue;
}

public bool TryParse(ReadOnlySpan<byte> buffer, [NotNullWhen(true)] out object? value)
{
if (Utf8Parser.TryParse(buffer, out decimal parsedValue, out _))
{
value = parsedValue;
return true;
}

value = null;
return false;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
#nullable enable
using System.Buffers.Text;
using System.Diagnostics.CodeAnalysis;

namespace HotChocolate.Types.Relay;

internal sealed class DoubleNodeIdValueSerializer : INodeIdValueSerializer
{
public bool IsSupported(Type type) => type == typeof(double) || type == typeof(double?);

public NodeIdFormatterResult Format(Span<byte> buffer, object value, out int written)
{
if (value is double i)
{
return Utf8Formatter.TryFormat(i, buffer, out written)
? NodeIdFormatterResult.Success
: NodeIdFormatterResult.BufferTooSmall;
}

written = 0;
return NodeIdFormatterResult.InvalidValue;
}

public bool TryParse(ReadOnlySpan<byte> buffer, [NotNullWhen(true)] out object? value)
{
if (Utf8Parser.TryParse(buffer, out double parsedValue, out _))
{
value = parsedValue;
return true;
}

value = null;
return false;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
#nullable enable
using System.Buffers.Text;
using System.Diagnostics.CodeAnalysis;

namespace HotChocolate.Types.Relay;

internal sealed class SingleNodeIdValueSerializer : INodeIdValueSerializer
{
public bool IsSupported(Type type) => type == typeof(float) || type == typeof(float?);

public NodeIdFormatterResult Format(Span<byte> buffer, object value, out int written)
{
if (value is float i)
{
return Utf8Formatter.TryFormat(i, buffer, out written)
? NodeIdFormatterResult.Success
: NodeIdFormatterResult.BufferTooSmall;
}

written = 0;
return NodeIdFormatterResult.InvalidValue;
}

public bool TryParse(ReadOnlySpan<byte> buffer, [NotNullWhen(true)] out object? value)
{
if (Utf8Parser.TryParse(buffer, out float parsedValue, out _))
{
value = parsedValue;
return true;
}

value = null;
return false;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,36 @@ public void Format_Int64Id_Legacy_Format()
Assert.Equal("Rm9vCmw2NA==", id);
}

[Fact]
public void Format_DecimalId()
{
var serializer = CreateSerializer("Foo", new DecimalNodeIdValueSerializer());

var id = serializer.Format("Foo", (decimal)6);

Assert.Equal("Rm9vOjY=", id);
}

[Fact]
public void Format_FloatId()
{
var serializer = CreateSerializer("Foo", new SingleNodeIdValueSerializer());

var id = serializer.Format("Foo", (float)6);

Assert.Equal("Rm9vOjY=", id);
}

[Fact]
public void Format_DoubleId()
{
var serializer = CreateSerializer("Foo", new DoubleNodeIdValueSerializer());

var id = serializer.Format("Foo", (double)6);

Assert.Equal("Rm9vOjY=", id);
}

[Fact]
public void Format_Empty_Guid()
{
Expand Down Expand Up @@ -363,6 +393,39 @@ public void Parse_Legacy_Int64Id()
Assert.Equal((long)123, id.InternalId);
}

[Fact]
public void Parse_DecimalId()
{
var serializer = CreateSerializer("Foo", new DecimalNodeIdValueSerializer());

var id = serializer.Parse("Rm9vOjEyMw==", typeof(decimal));

Assert.Equal("Foo", id.TypeName);
Assert.Equal((decimal)123, id.InternalId);
}

[Fact]
public void Parse_SingleId()
{
var serializer = CreateSerializer("Foo", new SingleNodeIdValueSerializer());

var id = serializer.Parse("Rm9vOjEyMw==", typeof(float));

Assert.Equal("Foo", id.TypeName);
Assert.Equal((float)123, id.InternalId);
}

[Fact]
public void Parse_DoublelId()
{
var serializer = CreateSerializer("Foo", new DoubleNodeIdValueSerializer());

var id = serializer.Parse("Rm9vOjEyMw==", typeof(double));

Assert.Equal("Foo", id.TypeName);
Assert.Equal((double)123, id.InternalId);
}

[Fact]
public void Parse_CompositeId()
{
Expand Down Expand Up @@ -497,7 +560,7 @@ protected override NodeIdFormatterResult Format(Span<byte> buffer, CompositeId v

protected override bool TryParse(ReadOnlySpan<byte> buffer, out CompositeId value)
{
if(TryParseIdPart(buffer, out string a, out var ac) &&
if (TryParseIdPart(buffer, out string a, out var ac) &&
TryParseIdPart(buffer.Slice(ac), out int b, out var bc) &&
TryParseIdPart(buffer.Slice(ac + bc), out Guid c, out var cc) &&
TryParseIdPart(buffer.Slice(ac + bc + cc), out bool d, out _))
Expand Down
Loading