Skip to content
Open
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
143 changes: 143 additions & 0 deletions gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary4/DataType.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
#region License

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

#endregion

using System;

namespace Gremlin.Net.Structure.IO.GraphBinary4
{
/// <summary>
/// Represents a GraphBinary 4.0 data type.
/// </summary>
public class DataType : IEquatable<DataType>
{
#pragma warning disable 1591
public static readonly DataType Int = new DataType(0x01);
public static readonly DataType Long = new DataType(0x02);
public static readonly DataType String = new DataType(0x03);
public static readonly DataType DateTime = new DataType(0x04);
public static readonly DataType Double = new DataType(0x07);
public static readonly DataType Float = new DataType(0x08);
public static readonly DataType List = new DataType(0x09);
public static readonly DataType Map = new DataType(0x0A);
public static readonly DataType Set = new DataType(0x0B);
public static readonly DataType Uuid = new DataType(0x0C);
public static readonly DataType Edge = new DataType(0x0D);
public static readonly DataType Path = new DataType(0x0E);
public static readonly DataType Property = new DataType(0x0F);
// Not yet implemented
// public static readonly DataType Graph = new DataType(0x10);
public static readonly DataType Vertex = new DataType(0x11);
public static readonly DataType VertexProperty = new DataType(0x12);
public static readonly DataType Direction = new DataType(0x18);
public static readonly DataType T = new DataType(0x20);
public static readonly DataType BigDecimal = new DataType(0x22);
public static readonly DataType BigInteger = new DataType(0x23);
public static readonly DataType Byte = new DataType(0x24);
public static readonly DataType Binary = new DataType(0x25);
public static readonly DataType Short = new DataType(0x26);
public static readonly DataType Boolean = new DataType(0x27);
// Not yet implemented
// public static readonly DataType Tree = new DataType(0x2B);
public static readonly DataType Merge = new DataType(0x2E);
// Not yet implemented
// public static readonly DataType CompositePDT = new DataType(0xF0);
// public static readonly DataType PrimitivePDT = new DataType(0xF1);
public static readonly DataType Char = new DataType(0x80);
public static readonly DataType Duration = new DataType(0x81);
public static readonly DataType Marker = new DataType(0xFD);
#pragma warning restore 1591

/// <summary>
/// A null value for an unspecified Object value.
/// </summary>
public static readonly DataType UnspecifiedNull = new DataType(0xFE);

private DataType(int code)
{
TypeCode = (byte) code;
}

/// <summary>
/// Gets the type code of this data type.
/// </summary>
public byte TypeCode { get; }

/// <summary>
/// Creates a new <see cref="DataType"/> instance for the given type code.
/// </summary>
public static DataType FromTypeCode(int code)
{
return new DataType(code);
}

/// <inheritdoc />
public bool Equals(DataType? other)
{
if (ReferenceEquals(null, other)) return false;
if (ReferenceEquals(this, other)) return true;
return TypeCode == other.TypeCode;
}

/// <inheritdoc />
public override bool Equals(object? obj)
{
if (ReferenceEquals(null, obj)) return false;
if (ReferenceEquals(this, obj)) return true;
if (obj.GetType() != GetType()) return false;
return Equals((DataType) obj);
}

/// <inheritdoc />
public override int GetHashCode()
{
return TypeCode.GetHashCode();
}

/// <summary>
/// Determines whether two specified <see cref="DataType"/> have the same values.
/// </summary>
public static bool operator ==(DataType? first, DataType? second)
{
if (ReferenceEquals(null, first))
{
return ReferenceEquals(null, second);
}

return first.Equals(second);
}

/// <summary>
/// Determines whether two specified <see cref="DataType"/> have different values.
/// </summary>
public static bool operator !=(DataType? first, DataType? second)
{
return !(first == second);
}

/// <inheritdoc />
public override string ToString()
{
return $"DataType{{ TypeCode = {TypeCode} }}";
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
#region License

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

#endregion

using System.IO;
using System.Threading;
using System.Threading.Tasks;

namespace Gremlin.Net.Structure.IO.GraphBinary4
{
/// <summary>
/// Allows to deserialize objects from GraphBinary v4.
/// </summary>
public class GraphBinaryReader
{
private readonly TypeSerializerRegistry _registry;

/// <summary>
/// Initializes a new instance of the <see cref="GraphBinaryReader" /> class.
/// </summary>
/// <param name="registry">The <see cref="TypeSerializerRegistry"/> to use for deserialization.</param>
public GraphBinaryReader(TypeSerializerRegistry? registry = null)
{
_registry = registry ?? TypeSerializerRegistry.Instance;
}

/// <summary>
/// Reads only the value for a specific type <typeparamref name="T"/>.
/// </summary>
/// <param name="stream">The GraphBinary data to parse.</param>
/// <param name="cancellationToken">The token to cancel the operation. The default value is None.</param>
/// <typeparam name="T">The type of the object to read.</typeparam>
/// <returns>The read value.</returns>
public async Task<object?> ReadNullableValueAsync<T>(Stream stream,
CancellationToken cancellationToken = default)
{
var typedSerializer = _registry.GetSerializerFor(typeof(T));
return await typedSerializer.ReadNullableValueAsync(stream, this, cancellationToken)
.ConfigureAwait(false);
}

/// <summary>
/// Reads only the value for a specific type <typeparamref name="T"/>.
/// </summary>
/// <param name="stream">The GraphBinary data to parse.</param>
/// <param name="cancellationToken">The token to cancel the operation. The default value is None.</param>
/// <typeparam name="T">The type of the object to read.</typeparam>
/// <returns>The read value.</returns>
public async Task<object> ReadNonNullableValueAsync<T>(Stream stream,
CancellationToken cancellationToken = default)
{
var typedSerializer = _registry.GetSerializerFor(typeof(T));
return await typedSerializer.ReadNonNullableValueAsync(stream, this, cancellationToken)
.ConfigureAwait(false);
}

/// <summary>
/// Reads the type code, information and value with fully-qualified format.
/// </summary>
/// <param name="stream">The GraphBinary data to parse.</param>
/// <param name="cancellationToken">The token to cancel the operation. The default value is None.</param>
/// <returns>The read value.</returns>
public async Task<object?> ReadAsync(Stream stream, CancellationToken cancellationToken = default)
{
var type = DataType.FromTypeCode(await stream.ReadByteAsync(cancellationToken).ConfigureAwait(false));

if (type == DataType.UnspecifiedNull)
{
await stream.ReadByteAsync(cancellationToken).ConfigureAwait(false); // read value byte to advance the index
return null;
}

var typeSerializer = _registry.GetSerializerFor(type);
return await typeSerializer.ReadAsync(stream, this, cancellationToken).ConfigureAwait(false);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
#region License

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

#endregion

using System;
using System.IO;
using System.Threading;
using System.Threading.Tasks;

namespace Gremlin.Net.Structure.IO.GraphBinary4
{
/// <summary>
/// Allows to serialize objects to GraphBinary v4.
/// </summary>
public class GraphBinaryWriter
{
private const byte ValueFlagNull = 1;
private const byte ValueFlagNone = 0;

/// <summary>
/// A <see cref="byte"/> representing the version of the GraphBinary v4 specification.
/// </summary>
public const byte VersionByte = 0x84;

private static readonly byte[] UnspecifiedNullBytes = {DataType.UnspecifiedNull.TypeCode, 0x01};

private readonly TypeSerializerRegistry _registry;

/// <summary>
/// Initializes a new instance of the <see cref="GraphBinaryWriter" /> class.
/// </summary>
/// <param name="registry">The <see cref="TypeSerializerRegistry"/> to use for serialization.</param>
public GraphBinaryWriter(TypeSerializerRegistry? registry = null)
{
_registry = registry ?? TypeSerializerRegistry.Instance;
}

/// <summary>
/// Writes a nullable value without including type information.
/// </summary>
/// <param name="value">The value to write.</param>
/// <param name="stream">The stream to write to.</param>
/// <param name="cancellationToken">The token to cancel the operation. The default value is None.</param>
/// <returns>A task that represents the asynchronous write operation.</returns>
public async Task WriteNullableValueAsync(object? value, Stream stream,
CancellationToken cancellationToken = default)
{
if (value == null)
{
await WriteValueFlagNullAsync(stream, cancellationToken).ConfigureAwait(false);
return;
}

var valueType = value.GetType();
var serializer = _registry.GetSerializerFor(valueType);
await serializer.WriteNullableValueAsync(value, stream, this, cancellationToken).ConfigureAwait(false);
}

/// <summary>
/// Writes a non-nullable value without including type information.
/// </summary>
/// <param name="value">The value to write.</param>
/// <param name="stream">The stream to write to.</param>
/// <param name="cancellationToken">The token to cancel the operation. The default value is None.</param>
/// <returns>A task that represents the asynchronous write operation.</returns>
public async Task WriteNonNullableValueAsync(object value, Stream stream,
CancellationToken cancellationToken = default)
{
if (value == null) throw new IOException($"{nameof(value)} cannot be null");
var valueType = value.GetType();
var serializer = _registry.GetSerializerFor(valueType);
await serializer.WriteNonNullableValueAsync(value, stream, this, cancellationToken).ConfigureAwait(false);
}

/// <summary>
/// Writes an object in fully-qualified format, containing {type_code}{type_info}{value_flag}{value}.
/// </summary>
/// <param name="value">The value to write.</param>
/// <param name="stream">The stream to write to.</param>
/// <param name="cancellationToken">The token to cancel the operation. The default value is None.</param>
/// <returns>A task that represents the asynchronous write operation.</returns>
public async Task WriteAsync(object? value, Stream stream, CancellationToken cancellationToken = default)
{
if (value == null)
{
await stream.WriteAsync(UnspecifiedNullBytes, cancellationToken).ConfigureAwait(false);
return;
}

var valueType = value.GetType();
var serializer = _registry.GetSerializerFor(valueType);

await stream.WriteByteAsync(serializer.DataType.TypeCode, cancellationToken).ConfigureAwait(false);
await serializer.WriteAsync(value, stream, this, cancellationToken).ConfigureAwait(false);
}

/// <summary>
/// Writes a single byte representing the null value_flag.
/// </summary>
/// <param name="stream">The stream to write to.</param>
/// <param name="cancellationToken">The token to cancel the operation. The default value is None.</param>
/// <returns>A task that represents the asynchronous write operation.</returns>
public async Task WriteValueFlagNullAsync(Stream stream, CancellationToken cancellationToken = default)
{
await stream.WriteByteAsync(ValueFlagNull, cancellationToken).ConfigureAwait(false);
}

/// <summary>
/// Writes a single byte with value 0, representing an unset value_flag.
/// </summary>
/// <param name="stream">The stream to write to.</param>
/// <param name="cancellationToken">The token to cancel the operation. The default value is None.</param>
/// <returns>A task that represents the asynchronous write operation.</returns>
public async Task WriteValueFlagNoneAsync(Stream stream, CancellationToken cancellationToken = default) {
await stream.WriteByteAsync(ValueFlagNone, cancellationToken).ConfigureAwait(false);
}


}
}
Loading
Loading