This is an automated email from the ASF dual-hosted git repository.
xiazcy pushed a commit to branch 3.8-dev
in repository https://gitbox.apache.org/repos/asf/tinkerpop.git
The following commit(s) were added to refs/heads/3.8-dev by this push:
new e2cc4ea409 Switched `gremlin-net` byte serializers to signed bytes
(`sbyte`) to be consistent with IO doc (#3206)
e2cc4ea409 is described below
commit e2cc4ea409412c677229454f68277188d46370f3
Author: Yang Xia <[email protected]>
AuthorDate: Mon Sep 22 16:10:38 2025 -0700
Switched `gremlin-net` byte serializers to signed bytes (`sbyte`) to be
consistent with IO doc (#3206)
---
CHANGELOG.asciidoc | 1 +
docs/src/upgrade/release-3.8.x.asciidoc | 9 +++
.../translator/DotNetTranslateVisitor.java | 4 +-
.../language/translator/GremlinTranslatorTest.java | 6 +-
.../Structure/IO/GraphBinary/StreamExtensions.cs | 23 ++++++++
.../IO/GraphBinary/TypeSerializerRegistry.cs | 2 +-
.../IO/GraphBinary/Types/SingleTypeSerializer.cs | 8 +--
.../Structure/IO/GraphSON/GraphSONReader.cs | 2 +-
.../Structure/IO/GraphSON/GraphSONWriter.cs | 2 +-
.../{ByteConverter.cs => SByteConverter.cs} | 6 +-
.../Gherkin/CommonSteps.cs | 2 +-
.../Gremlin.Net.IntegrationTest/Gherkin/Gremlin.cs | 38 ++++++-------
.../Structure/IO/GraphBinary/GraphBinaryTests.cs | 65 +++++++++++++++++++++-
.../Structure/IO/GraphSON/GraphSONReaderTests.cs | 14 +++++
.../Structure/IO/GraphSON/GraphSONWriterTests.cs | 29 +++++++++-
15 files changed, 174 insertions(+), 37 deletions(-)
diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc
index 26bf36c219..83aa2cc808 100644
--- a/CHANGELOG.asciidoc
+++ b/CHANGELOG.asciidoc
@@ -102,6 +102,7 @@ This release also includes changes from <<release-3-7-XXX,
3.7.XXX>>.
* Introduced `GValue` to represent parameterized values in a `GraphTraversal`
* Added optional traversal cache to `GremlinLangScriptEngine`
* Introduced step interfaces for all parameterizable steps
+* Switched `gremlin-net` byte serializers to signed bytes (`sbyte`) to be
consistent with IO doc
* Removed auto-unfold of singleton collections from `range()`, `limit()`, and
`tail()` local scope steps to improve consistency of output.
* Renamed `MergeElementStep` to `MergeElementStep` as it is a base class to
`mergeV()` and `mergeE()`.
* Renamed `MergeStep` of `merge()` to `MergeElementStep` for consistency.
diff --git a/docs/src/upgrade/release-3.8.x.asciidoc
b/docs/src/upgrade/release-3.8.x.asciidoc
index 297742f13a..8578783ab4 100644
--- a/docs/src/upgrade/release-3.8.x.asciidoc
+++ b/docs/src/upgrade/release-3.8.x.asciidoc
@@ -277,6 +277,15 @@ See:
link:https://issues.apache.org/jira/browse/TINKERPOP-3083[TINKERPOP-3083]
Starting from this version, `gremlin-javascript` will deserialize `Set` data
into a ECMAScript 2015 Set. Previously,
these were deserialized into arrays.
+==== .NET Byte Serialization Change
+
+The Gremlin .NET serializers has been updated to correctly handle byte values
as signed integers to align with the IO
+specification, whereas previously it incorrectly serialized and deserialized
bytes as unsigned values.
+
+This is a breaking change for .NET applications that rely on byte values.
Existing applications using byte values should consider switching to `sbyte`
for signed byte operations or `short` for a wider range of values to maintain
compatibility.
+
+See: link:https://issues.apache.org/jira/browse/TINKERPOP-3161[TINKERPOP-3161]
+
==== Removal of P.getOriginalValue()
`P.getOriginalValue()` has been removed as it was not offering much value and
was often confused with `P.getValue()`.
diff --git
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/translator/DotNetTranslateVisitor.java
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/translator/DotNetTranslateVisitor.java
index 04660efa18..638fb450e4 100644
---
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/translator/DotNetTranslateVisitor.java
+++
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/translator/DotNetTranslateVisitor.java
@@ -93,8 +93,8 @@ public class DotNetTranslateVisitor extends
AbstractTranslateVisitor {
final char lastCharacter = integerLiteral.charAt(lastCharIndex);
switch (lastCharacter) {
case 'b':
- // parse B/b as byte
- sb.append("(byte) ");
+ // parse B/b as sbyte
+ sb.append("(sbyte) ");
sb.append(integerLiteral, 0, lastCharIndex);
break;
case 's':
diff --git
a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/language/translator/GremlinTranslatorTest.java
b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/language/translator/GremlinTranslatorTest.java
index d04b4d10fb..1b557be5d6 100644
---
a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/language/translator/GremlinTranslatorTest.java
+++
b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/language/translator/GremlinTranslatorTest.java
@@ -353,7 +353,7 @@ public class GremlinTranslatorTest {
{"g.with('x', 1b)",
null,
"g.with(string0, byte0)",
- "g.With(\"x\", (byte) 1)",
+ "g.With(\"x\", (sbyte) 1)",
"g.With(\"x\", int8(1))",
"g.with('x', new Byte(1))",
"g.with(\"x\", new Byte(1))",
@@ -362,7 +362,7 @@ public class GremlinTranslatorTest {
{"g.with('x', 1B)",
"g.with('x', 1b)",
"g.with(string0, byte0)",
- "g.With(\"x\", (byte) 1)",
+ "g.With(\"x\", (sbyte) 1)",
"g.With(\"x\", int8(1))",
"g.with('x', new Byte(1))",
"g.with(\"x\", new Byte(1))",
@@ -371,7 +371,7 @@ public class GremlinTranslatorTest {
{"g.with('x', -1b)",
null,
"g.with(string0, byte0)",
- "g.With(\"x\", (byte) -1)",
+ "g.With(\"x\", (sbyte) -1)",
"g.With(\"x\", int8(-1))",
"g.with('x', new Byte(-1))",
"g.with(\"x\", new Byte(-1))",
diff --git
a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/StreamExtensions.cs
b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/StreamExtensions.cs
index 155a5758ed..6a81b1c2f7 100644
---
a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/StreamExtensions.cs
+++
b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/StreamExtensions.cs
@@ -59,6 +59,29 @@ namespace Gremlin.Net.Structure.IO.GraphBinary
return readBuffer[0];
}
+ /// <summary>
+ /// Asynchronously writes a <see cref="sbyte"/> to a <see
cref="Stream"/>.
+ /// </summary>
+ /// <param name="stream">The <see cref="Stream"/> to write the <see
cref="sbyte"/> to.</param>
+ /// <param name="value">The <see cref="sbyte"/> to write.</param>
+ /// <param name="cancellationToken">The token to cancel the operation.
The default value is None.</param>
+ public static async Task WriteSByteAsync(this Stream stream, sbyte
value,
+ CancellationToken cancellationToken = default)
+ {
+ await stream.WriteByteAsync((byte)value,
cancellationToken).ConfigureAwait(false);
+ }
+
+ /// <summary>
+ /// Asynchronously reads a <see cref="sbyte"/> from a <see
cref="Stream"/>.
+ /// </summary>
+ /// <param name="stream">The <see cref="Stream"/> to read from.</param>
+ /// <param name="cancellationToken">The token to cancel the operation.
The default value is None.</param>
+ /// <returns>The read <see cref="sbyte"/>.</returns>
+ public static async Task<sbyte> ReadSByteAsync(this Stream stream,
CancellationToken cancellationToken = default)
+ {
+ return (sbyte)await
stream.ReadByteAsync(cancellationToken).ConfigureAwait(false);
+ }
+
/// <summary>
/// Asynchronously writes an <see cref="int"/> to a <see
cref="Stream"/>.
/// </summary>
diff --git
a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/TypeSerializerRegistry.cs
b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/TypeSerializerRegistry.cs
index 74e00001e0..5c0894af9b 100644
---
a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/TypeSerializerRegistry.cs
+++
b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/TypeSerializerRegistry.cs
@@ -76,7 +76,7 @@ namespace Gremlin.Net.Structure.IO.GraphBinary
{typeof(Traverser), new TraverserSerializer()},
{typeof(decimal), new BigDecimalSerializer()},
{typeof(BigInteger), new BigIntegerSerializer()},
- {typeof(byte), SingleTypeSerializers.ByteSerializer},
+ {typeof(sbyte), SingleTypeSerializers.ByteSerializer},
{typeof(byte[]), new ByteBufferSerializer()},
{typeof(short), SingleTypeSerializers.ShortSerializer},
{typeof(bool), SingleTypeSerializers.BooleanSerializer},
diff --git
a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/SingleTypeSerializer.cs
b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/SingleTypeSerializer.cs
index 04830cffba..537f15eac9 100644
---
a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/SingleTypeSerializer.cs
+++
b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/SingleTypeSerializer.cs
@@ -81,11 +81,11 @@ namespace Gremlin.Net.Structure.IO.GraphBinary.Types
(stream, cancellationToken) =>
stream.ReadBoolAsync(cancellationToken));
/// <summary>
- /// A serializer for <see cref="byte"/> values.
+ /// A serializer for <see cref="sbyte"/> values.
/// </summary>
- public static readonly SingleTypeSerializer<byte> ByteSerializer = new
SingleTypeSerializer<byte>(DataType.Byte,
- (value, stream, cancellationToken) => stream.WriteByteAsync(value,
cancellationToken),
- (stream, cancellationToken) =>
stream.ReadByteAsync(cancellationToken));
+ public static readonly SingleTypeSerializer<sbyte> ByteSerializer =
new SingleTypeSerializer<sbyte>(DataType.Byte,
+ (value, stream, cancellationToken) =>
stream.WriteSByteAsync(value, cancellationToken),
+ (stream, cancellationToken) =>
stream.ReadSByteAsync(cancellationToken));
}
/// <summary>
diff --git
a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/GraphSONReader.cs
b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/GraphSONReader.cs
index 52e26992a6..b9c7039493 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/GraphSONReader.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/GraphSONReader.cs
@@ -63,7 +63,7 @@ namespace Gremlin.Net.Structure.IO.GraphSON
{ "gx:BigDecimal", new DecimalConverter() },
{ "gx:Duration", new DurationDeserializer() },
{ "gx:BigInteger", new BigIntegerDeserializer() },
- { "gx:Byte", new ByteConverter() },
+ { "gx:Byte", new SByteConverter() },
{ "gx:ByteBuffer", new ByteBufferDeserializer() },
{ "gx:Char", new CharConverter() },
{ "gx:Int16", new Int16Converter() }
diff --git
a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/GraphSONWriter.cs
b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/GraphSONWriter.cs
index b883582321..4424505261 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/GraphSONWriter.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/GraphSONWriter.cs
@@ -73,7 +73,7 @@ namespace Gremlin.Net.Structure.IO.GraphSON
{ typeof(decimal), new DecimalConverter() },
{ typeof(TimeSpan), new DurationSerializer() },
{ typeof(BigInteger), new BigIntegerSerializer() },
- { typeof(byte), new ByteConverter() },
+ { typeof(sbyte), new SByteConverter() },
{ typeof(byte[]), new ByteBufferSerializer() },
{ typeof(char), new CharConverter() },
{ typeof(short), new Int16Converter() }
diff --git
a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/ByteConverter.cs
b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/SByteConverter.cs
similarity index 92%
rename from
gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/ByteConverter.cs
rename to gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/SByteConverter.cs
index c9fc8a5abe..755405205d 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/ByteConverter.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/SByteConverter.cs
@@ -24,10 +24,10 @@ using System.Text.Json;
namespace Gremlin.Net.Structure.IO.GraphSON
{
- internal class ByteConverter : NumberConverter<byte>
+ internal class SByteConverter : NumberConverter<sbyte>
{
protected override string GraphSONTypeName => "Byte";
protected override string Prefix => "gx";
- protected override dynamic FromJsonElement(JsonElement graphson) =>
graphson.GetByte();
+ protected override dynamic FromJsonElement(JsonElement graphson) =>
graphson.GetSByte();
}
-}
\ No newline at end of file
+}
diff --git
a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/CommonSteps.cs
b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/CommonSteps.cs
index 2ffe19a577..29f40ed955 100644
--- a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/CommonSteps.cs
+++ b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/CommonSteps.cs
@@ -87,7 +87,7 @@ namespace Gremlin.Net.IntegrationTest.Gherkin
private static readonly IDictionary<char, Func<string, object>>
NumericParsers =
new Dictionary<char, Func<string, object>>
{
- { 'b', s => Convert.ToByte(s) },
+ { 'b', s => Convert.ToSByte(s) },
{ 's', s => Convert.ToInt16(s) },
{ 'i', s => Convert.ToInt32(s) },
{ 'l', s => Convert.ToInt64(s) },
diff --git a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/Gremlin.cs
b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/Gremlin.cs
index f9787aec36..bb686d83bd 100644
--- a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/Gremlin.cs
+++ b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/Gremlin.cs
@@ -726,7 +726,7 @@ namespace Gremlin.Net.IntegrationTest.Gherkin
{"g_injectX1_2X_asDate", new List<Func<GraphTraversalSource,
IDictionary<string, object>, ITraversal>> {(g,p) =>g.Inject<object>(new
List<object> { 1, 2 }).AsDate()}},
{"g_injectXnullX_asDate", new List<Func<GraphTraversalSource,
IDictionary<string, object>, ITraversal>> {(g,p)
=>g.Inject<object>(null).AsDate()}},
{"g_injectXinvalidstrX_asDate", new
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>>
{(g,p) =>g.Inject<object>("This String is not an ISO 8601 Date").AsDate()}},
- {"g_injectX5bX_asNumber", new List<Func<GraphTraversalSource,
IDictionary<string, object>, ITraversal>> {(g,p) =>g.Inject<object>((byte)
5).AsNumber()}},
+ {"g_injectX5bX_asNumber", new List<Func<GraphTraversalSource,
IDictionary<string, object>, ITraversal>> {(g,p) =>g.Inject<object>((sbyte)
5).AsNumber()}},
{"g_injectX5sX_asNumber", new List<Func<GraphTraversalSource,
IDictionary<string, object>, ITraversal>> {(g,p) =>g.Inject<object>((short)
5).AsNumber()}},
{"g_injectX5iX_asNumber", new List<Func<GraphTraversalSource,
IDictionary<string, object>, ITraversal>> {(g,p)
=>g.Inject<object>(5).AsNumber()}},
{"g_injectX5lX_asNumber", new List<Func<GraphTraversalSource,
IDictionary<string, object>, ITraversal>> {(g,p)
=>g.Inject<object>(5l).AsNumber()}},
@@ -1447,7 +1447,7 @@ namespace Gremlin.Net.IntegrationTest.Gherkin
{"g_V_hasLabelXsoftwareX_valueXnameX_substringX1_neg1X", new
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>>
{(g,p) =>g.V().HasLabel("software").Values<object>("name").Substring(1, -1)}},
{"g_V_hasLabelXsoftwareX_valueXnameX_substringXneg4_2X", new
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>>
{(g,p) =>g.V().HasLabel("software").Values<object>("name").Substring(-4, 2)}},
{"g_V_hasLabelXsoftwareX_valueXnameX_substringXneg3_neg1X", new
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>>
{(g,p) =>g.V().HasLabel("software").Values<object>("name").Substring(-3, -1)}},
- {"g_V_injectX127b_1bX_sumXX", new
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>>
{(g,p) =>g.Inject<object>((byte) 127, (byte) 1).Sum<object>()}},
+ {"g_V_injectX127b_1bX_sumXX", new
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>>
{(g,p) =>g.Inject<object>((sbyte) 127, (sbyte) 1).Sum<object>()}},
{"g_V_injectX_128b__1bX_sumXX", new
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>>
{(g,p) =>g.Inject<object>((short) -128, (short) -1).Sum<object>()}},
{"g_V_injectX32767s_1sX_sumXX", new
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>>
{(g,p) =>g.Inject<object>((short) 32767, (short) 1).Sum<object>()}},
{"g_V_injectX_32768s__1sX_sumXX", new
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>>
{(g,p) =>g.Inject<object>((short) -32768, (short) -1).Sum<object>()}},
@@ -1471,14 +1471,14 @@ namespace Gremlin.Net.IntegrationTest.Gherkin
{"g_VX1X_valuesXageX_sumXlocalX", new
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>>
{(g,p) =>g.V(p["vid1"]).Values<object>("age").Sum<object>(Scope.Local)}},
{"g_V_localXunionXvaluesXageX_outE_valuesXweightXX_foldX_sumXlocalX", new
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>>
{(g,p) =>g.V().Local<object>(__.Union<object>(__.Values<object>("age"),
__.OutE().Values<object>("weight")).Fold()).Sum<object>(Scope.Local)}},
{"g_V_age_injectX1000nX_sum", new
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>>
{(g,p)
=>g.V().Values<object>("age").Inject(BigInteger.Parse("1000")).Sum<object>()}},
- {"g_injectX1b_2b_3bX_sum", new List<Func<GraphTraversalSource,
IDictionary<string, object>, ITraversal>> {(g,p) =>g.Inject<object>((byte) 1,
(byte) 2, (byte) 3).Sum<object>()}},
- {"g_injectX1b_2b_3sX_sum", new List<Func<GraphTraversalSource,
IDictionary<string, object>, ITraversal>> {(g,p) =>g.Inject<object>((byte) 1,
(byte) 2, (short) 3).Sum<object>()}},
- {"g_injectX1b_26b_3iX_sum", new List<Func<GraphTraversalSource,
IDictionary<string, object>, ITraversal>> {(g,p) =>g.Inject<object>((byte) 1,
(byte) 2, 3).Sum<object>()}},
+ {"g_injectX1b_2b_3bX_sum", new List<Func<GraphTraversalSource,
IDictionary<string, object>, ITraversal>> {(g,p) =>g.Inject<object>((sbyte) 1,
(sbyte) 2, (sbyte) 3).Sum<object>()}},
+ {"g_injectX1b_2b_3sX_sum", new List<Func<GraphTraversalSource,
IDictionary<string, object>, ITraversal>> {(g,p) =>g.Inject<object>((sbyte) 1,
(sbyte) 2, (short) 3).Sum<object>()}},
+ {"g_injectX1b_26b_3iX_sum", new List<Func<GraphTraversalSource,
IDictionary<string, object>, ITraversal>> {(g,p) =>g.Inject<object>((sbyte) 1,
(sbyte) 2, 3).Sum<object>()}},
{"g_injectX1f_26f_3fX_sum", new List<Func<GraphTraversalSource,
IDictionary<string, object>, ITraversal>> {(g,p) =>g.Inject<object>(1f, 2f,
3f).Sum<object>()}},
{"g_V_age_injectX1000nX_fold_sumXlocalX", new
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>>
{(g,p)
=>g.V().Values<object>("age").Inject(BigInteger.Parse("1000")).Fold().Sum<object>(Scope.Local)}},
- {"g_injectX1b_2b_3bX_fold_sumXlocalX", new
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>>
{(g,p) =>g.Inject<object>((byte) 1, (byte) 2, (byte)
3).Fold().Sum<object>(Scope.Local)}},
- {"g_injectX1b_2b_3sX_fold_sumXlocalX", new
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>>
{(g,p) =>g.Inject<object>((byte) 1, (byte) 2, (short)
3).Fold().Sum<object>(Scope.Local)}},
- {"g_injectX1b_26b_3iX_fold_sumXlocalX", new
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>>
{(g,p) =>g.Inject<object>((byte) 1, (byte) 2,
3).Fold().Sum<object>(Scope.Local)}},
+ {"g_injectX1b_2b_3bX_fold_sumXlocalX", new
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>>
{(g,p) =>g.Inject<object>((sbyte) 1, (sbyte) 2, (sbyte)
3).Fold().Sum<object>(Scope.Local)}},
+ {"g_injectX1b_2b_3sX_fold_sumXlocalX", new
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>>
{(g,p) =>g.Inject<object>((sbyte) 1, (sbyte) 2, (short)
3).Fold().Sum<object>(Scope.Local)}},
+ {"g_injectX1b_26b_3iX_fold_sumXlocalX", new
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>>
{(g,p) =>g.Inject<object>((sbyte) 1, (sbyte) 2,
3).Fold().Sum<object>(Scope.Local)}},
{"g_injectX1f_26f_3fX_fold_sumXlocalX", new
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>>
{(g,p) =>g.Inject<object>(1f, 2f, 3f).Fold().Sum<object>(Scope.Local)}},
{"g_injectXfeature_test_nullX_toLower", new
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>>
{(g,p) =>g.Inject<object>("FEATURE", "tESt", null).ToLower()}},
{"g_injectXfeature_test_nullX_toLowerXlocalX", new
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>>
{(g,p) =>g.Inject<object>(new List<object> { "FEATURE", "tESt", null
}).ToLower<object>(Scope.Local)}},
@@ -1635,14 +1635,14 @@ namespace Gremlin.Net.IntegrationTest.Gherkin
{"InjectXInfX_ltXNegInfX", new List<Func<GraphTraversalSource,
IDictionary<string, object>, ITraversal>> {(g,p)
=>g.Inject<object>(Double.PositiveInfinity).Is(P.Lt(Double.NegativeInfinity))}},
{"InjectXNegInfX_ltXInfX", new List<Func<GraphTraversalSource,
IDictionary<string, object>, ITraversal>> {(g,p)
=>g.Inject<object>(Double.NegativeInfinity).Is(P.Lt(Double.PositiveInfinity))}},
{"InjectXNegInfX_gtXInfX", new List<Func<GraphTraversalSource,
IDictionary<string, object>, ITraversal>> {(g,p)
=>g.Inject<object>(Double.NegativeInfinity).Is(P.Gt(Double.PositiveInfinity))}},
- {"Primitives_Number_eqXbyteX", new
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>>
{(g,p) =>g.Inject<object>(new List<object> { (byte) 1, (short) 1, 1, 1l, 1f,
1d, 1000, (decimal) 1, BigInteger.Parse("1")
}).Unfold<object>().Where(__.Is(p["xx1"]))}},
- {"Primitives_Number_eqXshortX", new
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>>
{(g,p) =>g.Inject<object>(new List<object> { (byte) 1, (short) 1, 1, 1l, 1f,
1d, 1000, (decimal) 1, BigInteger.Parse("1")
}).Unfold<object>().Where(__.Is(p["xx1"]))}},
- {"Primitives_Number_eqXintX", new
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>>
{(g,p) =>g.Inject<object>(new List<object> { (byte) 1, (short) 1, 1, 1l, 1f,
1d, 1000, (decimal) 1, BigInteger.Parse("1")
}).Unfold<object>().Where(__.Is(p["xx1"]))}},
- {"Primitives_Number_eqXlongX", new
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>>
{(g,p) =>g.Inject<object>(new List<object> { (byte) 1, (short) 1, 1, 1l, 1f,
1d, 1000, (decimal) 1, BigInteger.Parse("1")
}).Unfold<object>().Where(__.Is(p["xx1"]))}},
- {"Primitives_Number_eqXbigintX", new
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>>
{(g,p) =>g.Inject<object>(new List<object> { (byte) 1, (short) 1, 1, 1l, 1f,
1d, 1000, (decimal) 1, BigInteger.Parse("1")
}).Unfold<object>().Where(__.Is(p["xx1"]))}},
- {"Primitives_Number_eqXfloatX", new
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>>
{(g,p) =>g.Inject<object>(new List<object> { (byte) 1, (short) 1, 1, 1l, 1f,
1d, 1000, (decimal) 1, BigInteger.Parse("1")
}).Unfold<object>().Where(__.Is(p["xx1"]))}},
- {"Primitives_Number_eqXdoubleX", new
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>>
{(g,p) =>g.Inject<object>(new List<object> { (byte) 1, (short) 1, 1, 1l, 1f,
1d, 1000, (decimal) 1, BigInteger.Parse("1")
}).Unfold<object>().Where(__.Is(p["xx1"]))}},
- {"Primitives_Number_eqXbigdecimalX", new
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>>
{(g,p) =>g.Inject<object>(new List<object> { (byte) 1, (short) 1, 1, 1l, 1f,
1d, 1000, (decimal) 1, BigInteger.Parse("1")
}).Unfold<object>().Where(__.Is(p["xx1"]))}},
+ {"Primitives_Number_eqXbyteX", new
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>>
{(g,p) =>g.Inject<object>(new List<object> { (sbyte) 1, (short) 1, 1, 1l, 1f,
1d, 1000, (decimal) 1, BigInteger.Parse("1")
}).Unfold<object>().Where(__.Is(p["xx1"]))}},
+ {"Primitives_Number_eqXshortX", new
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>>
{(g,p) =>g.Inject<object>(new List<object> { (sbyte) 1, (short) 1, 1, 1l, 1f,
1d, 1000, (decimal) 1, BigInteger.Parse("1")
}).Unfold<object>().Where(__.Is(p["xx1"]))}},
+ {"Primitives_Number_eqXintX", new
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>>
{(g,p) =>g.Inject<object>(new List<object> { (sbyte) 1, (short) 1, 1, 1l, 1f,
1d, 1000, (decimal) 1, BigInteger.Parse("1")
}).Unfold<object>().Where(__.Is(p["xx1"]))}},
+ {"Primitives_Number_eqXlongX", new
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>>
{(g,p) =>g.Inject<object>(new List<object> { (sbyte) 1, (short) 1, 1, 1l, 1f,
1d, 1000, (decimal) 1, BigInteger.Parse("1")
}).Unfold<object>().Where(__.Is(p["xx1"]))}},
+ {"Primitives_Number_eqXbigintX", new
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>>
{(g,p) =>g.Inject<object>(new List<object> { (sbyte) 1, (short) 1, 1, 1l, 1f,
1d, 1000, (decimal) 1, BigInteger.Parse("1")
}).Unfold<object>().Where(__.Is(p["xx1"]))}},
+ {"Primitives_Number_eqXfloatX", new
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>>
{(g,p) =>g.Inject<object>(new List<object> { (sbyte) 1, (short) 1, 1, 1l, 1f,
1d, 1000, (decimal) 1, BigInteger.Parse("1")
}).Unfold<object>().Where(__.Is(p["xx1"]))}},
+ {"Primitives_Number_eqXdoubleX", new
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>>
{(g,p) =>g.Inject<object>(new List<object> { (sbyte) 1, (short) 1, 1, 1l, 1f,
1d, 1000, (decimal) 1, BigInteger.Parse("1")
}).Unfold<object>().Where(__.Is(p["xx1"]))}},
+ {"Primitives_Number_eqXbigdecimalX", new
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>>
{(g,p) =>g.Inject<object>(new List<object> { (sbyte) 1, (short) 1, 1, 1l, 1f,
1d, 1000, (decimal) 1, BigInteger.Parse("1")
}).Unfold<object>().Where(__.Is(p["xx1"]))}},
{"g_V_values_order", new List<Func<GraphTraversalSource,
IDictionary<string, object>, ITraversal>> {(g,p)
=>g.V().Values<object>().Order()}},
{"g_V_properties_order", new List<Func<GraphTraversalSource,
IDictionary<string, object>, ITraversal>> {(g,p)
=>g.V().Properties<object>().Order()}},
{"g_V_properties_order_id", new List<Func<GraphTraversalSource,
IDictionary<string, object>, ITraversal>> {(g,p)
=>g.V().Properties<object>().Order().Id()}},
@@ -1771,7 +1771,7 @@ namespace Gremlin.Net.IntegrationTest.Gherkin
{"g_io_read_withXreader_graphsonX", new
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>>
{(g,p) =>g.Io<object>("data/tinkerpop-modern.json").With(IO.Reader,
IO.GraphSON).Read(), (g,p) =>g.V(), (g,p) =>g.E()}},
{"g_io_readXgraphmlX", new List<Func<GraphTraversalSource,
IDictionary<string, object>, ITraversal>> {(g,p)
=>g.Io<object>("data/tinkerpop-modern.xml").Read(), (g,p) =>g.V(), (g,p)
=>g.E()}},
{"g_io_read_withXreader_graphmlX", new
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>>
{(g,p) =>g.Io<object>("data/tinkerpop-modern.xml").With(IO.Reader,
IO.GraphML).Read(), (g,p) =>g.V(), (g,p) =>g.E()}},
- {"g_withSackX127bX_injectX1bX_sackXsumX_sack", new
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>>
{(g,p) =>g.WithSack((byte) 127).Inject<object>((byte)
1).Sack(Operator.Sum).Sack<object>()}},
+ {"g_withSackX127bX_injectX1bX_sackXsumX_sack", new
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>>
{(g,p) =>g.WithSack((sbyte) 127).Inject<object>((sbyte)
1).Sack(Operator.Sum).Sack<object>()}},
{"g_withSackX32767sX_injectX1sX_sackXsumX_sack", new
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>>
{(g,p) =>g.WithSack((short) 32767).Inject<object>((short)
1).Sack(Operator.Sum).Sack<object>()}},
{"g_withSackX2147483647iX_injectX1iX_sackXsumX_sack", new
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>>
{(g,p)
=>g.WithSack(2147483647).Inject<object>(1).Sack(Operator.Sum).Sack<object>()}},
{"g_withSackX1_7976931348623157E_308dX_injectX1_7976931348623157E_308dX_sackXsumX_sack",
new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>>
{(g,p)
=>g.WithSack(1.7976931348623157e+308d).Inject<object>(1.7976931348623157e+308d).Sack(Operator.Sum).Sack<object>()}},
@@ -1779,11 +1779,11 @@ namespace Gremlin.Net.IntegrationTest.Gherkin
{"g_withSackX_32768sX_injectX1sX_sackXminusX_sack", new
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>>
{(g,p) =>g.WithSack((short) -32768).Inject<object>((short)
1).Sack(Operator.Minus).Sack<object>()}},
{"g_withSackX_2147483648iX_injectX1iX_sackXminusX_sack", new
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>>
{(g,p)
=>g.WithSack(-2147483648).Inject<object>(1).Sack(Operator.Minus).Sack<object>()}},
{"g_withSackX_1_7976931348623157E_308dX_injectX1_7976931348623157E_308dX_sackXminusX_sack",
new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>>
{(g,p)
=>g.WithSack(-1.7976931348623157e+308d).Inject<object>(1.7976931348623157e+308d).Sack(Operator.Minus).Sack<object>()}},
- {"g_withSackX127bX_injectX2bX_sackXmultX_sack", new
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>>
{(g,p) =>g.WithSack((byte) 127).Inject<object>((byte)
2).Sack(Operator.Mult).Sack<object>()}},
+ {"g_withSackX127bX_injectX2bX_sackXmultX_sack", new
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>>
{(g,p) =>g.WithSack((sbyte) 127).Inject<object>((sbyte)
2).Sack(Operator.Mult).Sack<object>()}},
{"g_withSackX32767sX_injectX2sX_sackXmultX_sack", new
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>>
{(g,p) =>g.WithSack((short) 32767).Inject<object>((short)
2).Sack(Operator.Mult).Sack<object>()}},
{"g_withSackX2147483647iX_injectX2iX_sackXmultX_sack", new
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>>
{(g,p)
=>g.WithSack(2147483647).Inject<object>(2).Sack(Operator.Mult).Sack<object>()}},
{"g_withSackX1_7976931348623157E_308dX_injectX2dX_sackXmultX_sack", new
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>>
{(g,p)
=>g.WithSack(1.7976931348623157e+308d).Inject<object>(2d).Sack(Operator.Mult).Sack<object>()}},
- {"g_withSackX127bX_injectX0_5fX_sackXdivX_sack", new
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>>
{(g,p) =>g.WithSack((byte)
127).Inject<object>(0.5f).Sack(Operator.Div).Sack<object>()}},
+ {"g_withSackX127bX_injectX0_5fX_sackXdivX_sack", new
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>>
{(g,p) =>g.WithSack((sbyte)
127).Inject<object>(0.5f).Sack(Operator.Div).Sack<object>()}},
{"g_withSackX32767sX_injectX0_5fX_sackXdivX_sack", new
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>>
{(g,p) =>g.WithSack((short)
32767).Inject<object>(0.5f).Sack(Operator.Div).Sack<object>()}},
{"g_withSackX2147483647iX_injectX0_5fX_sackXdivX_sack", new
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>>
{(g,p)
=>g.WithSack(2147483647).Inject<object>(0.5f).Sack(Operator.Div).Sack<object>()}},
{"g_withSackX1_7976931348623157E_308dX_injectX0_5dX_sackXdivX_sack", new
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>>
{(g,p)
=>g.WithSack(1.7976931348623157e+308d).Inject<object>(0.5d).Sack(Operator.Div).Sack<object>()}},
diff --git
a/gremlin-dotnet/test/Gremlin.Net.UnitTest/Structure/IO/GraphBinary/GraphBinaryTests.cs
b/gremlin-dotnet/test/Gremlin.Net.UnitTest/Structure/IO/GraphBinary/GraphBinaryTests.cs
index 1f172f6acc..df8e189cdf 100644
---
a/gremlin-dotnet/test/Gremlin.Net.UnitTest/Structure/IO/GraphBinary/GraphBinaryTests.cs
+++
b/gremlin-dotnet/test/Gremlin.Net.UnitTest/Structure/IO/GraphBinary/GraphBinaryTests.cs
@@ -708,7 +708,10 @@ namespace Gremlin.Net.UnitTest.Structure.IO.GraphBinary
[Theory]
[InlineData(1)]
[InlineData(123)]
- public async Task TestByte(byte expected)
+ [InlineData(-1)]
+ [InlineData(-128)]
+ [InlineData(127)]
+ public async Task TestSByte(sbyte expected)
{
var writer = CreateGraphBinaryWriter();
var reader = CreateGraphBinaryReader();
@@ -721,6 +724,66 @@ namespace Gremlin.Net.UnitTest.Structure.IO.GraphBinary
Assert.Equal(expected, actual);
}
+ [Theory]
+ [InlineData((sbyte)0, new byte[] { 0x00 })]
+ [InlineData((sbyte)1, new byte[] { 0x01 })]
+ [InlineData((sbyte)127, new byte[] { 0x7F })]
+ [InlineData((sbyte)-1, new byte[] { 0xFF })]
+ [InlineData((sbyte)-128, new byte[] { 0x80 })]
+ public async Task TestSByteSerializationSpec(sbyte value, byte[]
expected)
+ {
+ var writer = new GraphBinaryWriter();
+ var serializationStream = new MemoryStream();
+
+ await writer.WriteNonNullableValueAsync(value,
serializationStream);
+
+ var serBytes = serializationStream.ToArray();
+ Assert.Equal(expected, serBytes);
+ }
+
+ [Theory]
+ [InlineData((sbyte)0)]
+ [InlineData((sbyte)1)]
+ [InlineData((sbyte)127)]
+ [InlineData((sbyte)-1)]
+ [InlineData((sbyte)-128)]
+ [InlineData((sbyte)42)]
+ [InlineData((sbyte)-42)]
+ public async Task TestSByteRoundTrip(sbyte expected)
+ {
+ var writer = new GraphBinaryWriter();
+ var reader = new GraphBinaryReader();
+ var serializationStream = new MemoryStream();
+
+ await writer.WriteAsync(expected, serializationStream);
+ serializationStream.Position = 0;
+ var actual = await reader.ReadAsync(serializationStream);
+
+ Assert.Equal(expected, actual);
+ Assert.IsType<sbyte>(actual);
+ }
+
+ [Fact]
+ public async Task TestSByteMinMaxValues()
+ {
+ var writer = new GraphBinaryWriter();
+ var reader = new GraphBinaryReader();
+
+ // Test minimum value
+ var minStream = new MemoryStream();
+ await writer.WriteAsync(sbyte.MinValue, minStream);
+ minStream.Position = 0;
+ var actualMin = await reader.ReadAsync(minStream);
+ Assert.Equal(sbyte.MinValue, actualMin);
+
+ // Test maximum value
+ var maxStream = new MemoryStream();
+ await writer.WriteAsync(sbyte.MaxValue, maxStream);
+ maxStream.Position = 0;
+ var actualMax = await reader.ReadAsync(maxStream);
+ Assert.Equal(sbyte.MaxValue, actualMax);
+ }
+
[Fact]
public async Task TestByteBuffer()
{
diff --git
a/gremlin-dotnet/test/Gremlin.Net.UnitTest/Structure/IO/GraphSON/GraphSONReaderTests.cs
b/gremlin-dotnet/test/Gremlin.Net.UnitTest/Structure/IO/GraphSON/GraphSONReaderTests.cs
index e5c1d8a88a..05a3ee1585 100644
---
a/gremlin-dotnet/test/Gremlin.Net.UnitTest/Structure/IO/GraphSON/GraphSONReaderTests.cs
+++
b/gremlin-dotnet/test/Gremlin.Net.UnitTest/Structure/IO/GraphSON/GraphSONReaderTests.cs
@@ -262,6 +262,20 @@ namespace Gremlin.Net.UnitTest.Structure.IO.GraphSON
var deserializedValue = reader.ToObject(jsonElement);
Assert.Equal(1, deserializedValue);
+ Assert.IsType<sbyte>(deserializedValue);
+ }
+
+ [Theory, MemberData(nameof(Versions))]
+ public void ShouldDeserializeByteNegative(int version)
+ {
+ const string serializedValue =
"{\"@type\":\"gx:Byte\",\"@value\":-42}";
+ var reader = CreateStandardGraphSONReader(version);
+
+ var jsonElement =
JsonSerializer.Deserialize<JsonElement>(serializedValue);
+ var deserializedValue = reader.ToObject(jsonElement);
+
+ Assert.Equal(-42, deserializedValue);
+ Assert.IsType<sbyte>(deserializedValue);
}
[Theory, MemberData(nameof(Versions))]
diff --git
a/gremlin-dotnet/test/Gremlin.Net.UnitTest/Structure/IO/GraphSON/GraphSONWriterTests.cs
b/gremlin-dotnet/test/Gremlin.Net.UnitTest/Structure/IO/GraphSON/GraphSONWriterTests.cs
index 34cdd8e534..a73c8d1693 100644
---
a/gremlin-dotnet/test/Gremlin.Net.UnitTest/Structure/IO/GraphSON/GraphSONWriterTests.cs
+++
b/gremlin-dotnet/test/Gremlin.Net.UnitTest/Structure/IO/GraphSON/GraphSONWriterTests.cs
@@ -24,6 +24,7 @@
using System;
using System.Collections.Generic;
using System.Numerics;
+using System.Text.Json;
using Gremlin.Net.Process.Traversal;
using Gremlin.Net.Process.Traversal.Strategy.Decoration;
using Gremlin.Net.Process.Traversal.Strategy.Optimization;
@@ -582,10 +583,36 @@ namespace Gremlin.Net.UnitTest.Structure.IO.GraphSON
{
var writer = CreateGraphSONWriter(version);
- var graphSon = writer.WriteObject((byte)1);
+ var graphSon = writer.WriteObject((sbyte)1);
Assert.Equal("{\"@type\":\"gx:Byte\",\"@value\":1}", graphSon);
}
+
+ [Theory, MemberData(nameof(Versions))]
+ public void ShouldSerializeByteNegativeValue(int version)
+ {
+ var writer = CreateGraphSONWriter(version);
+
+ var graphSon = writer.WriteObject((sbyte)-42);
+
+ Assert.Equal("{\"@type\":\"gx:Byte\",\"@value\":-42}", graphSon);
+ }
+
+ [Theory, MemberData(nameof(Versions))]
+ public void TestSByteGraphSONFormat(int version)
+ {
+ var writer = CreateGraphSONWriter(version);
+ var value = (sbyte)42;
+
+ var serialized = writer.WriteObject(value);
+ var jsonDoc = JsonDocument.Parse(serialized);
+
+ Assert.True(jsonDoc.RootElement.TryGetProperty("@type", out var
typeProperty));
+ Assert.Equal("gx:Byte", typeProperty.GetString());
+
+ Assert.True(jsonDoc.RootElement.TryGetProperty("@value", out var
valueProperty));
+ Assert.Equal(42, valueProperty.GetSByte());
+ }
[Theory, MemberData(nameof(Versions))]
public void ShouldSerializeByteBuffer(int version)