blob: 155a5758ed00bf08de3ddafc3218a68e7d5b668e [file] [log] [blame]
#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.GraphBinary
{
/// <summary>
/// Provides extension methods for <see cref="Stream" /> that are mostly useful when implementing GraphBinary
/// serializers.
/// </summary>
public static class StreamExtensions
{
/// <summary>
/// Asynchronously writes a <see cref="byte"/> to a <see cref="Stream"/>.
/// </summary>
/// <param name="stream">The <see cref="Stream"/> to write the <see cref="byte"/> to.</param>
/// <param name="value">The <see cref="byte"/> to write.</param>
/// <param name="cancellationToken">The token to cancel the operation. The default value is None.</param>
public static async Task WriteByteAsync(this Stream stream, byte value,
CancellationToken cancellationToken = default)
{
await stream.WriteAsync(new[] {value}, 0, 1, cancellationToken).ConfigureAwait(false);
}
/// <summary>
/// Asynchronously reads a <see cref="byte"/> 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="byte"/>.</returns>
public static async Task<byte> ReadByteAsync(this Stream stream, CancellationToken cancellationToken = default)
{
var readBuffer = new byte[1];
await stream.ReadAsync(readBuffer, 0, 1, cancellationToken).ConfigureAwait(false);
return readBuffer[0];
}
/// <summary>
/// Asynchronously writes an <see cref="int"/> to a <see cref="Stream"/>.
/// </summary>
/// <param name="stream">The <see cref="Stream"/> to write the <see cref="int"/> to.</param>
/// <param name="value">The <see cref="int"/> to write.</param>
/// <param name="cancellationToken">The token to cancel the operation. The default value is None.</param>
public static async Task WriteIntAsync(this Stream stream, int value,
CancellationToken cancellationToken = default)
{
var bytes = BitConverter.GetBytes(value);
await stream.WriteAsync(new[] { bytes[3], bytes[2], bytes[1], bytes[0] }, 0, 4, cancellationToken).ConfigureAwait(false);
}
/// <summary>
/// Asynchronously reads an <see cref="int"/> 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="int"/>.</returns>
public static async Task<int> ReadIntAsync(this Stream stream, CancellationToken cancellationToken = default)
{
var bytes = new byte[4];
await stream.ReadAsync(bytes, 0, 4, cancellationToken).ConfigureAwait(false);
return BitConverter.ToInt32(new []{bytes[3], bytes[2], bytes[1], bytes[0]}, 0);
}
/// <summary>
/// Asynchronously writes a <see cref="long"/> to a <see cref="Stream"/>.
/// </summary>
/// <param name="stream">The <see cref="Stream"/> to write the <see cref="long"/> to.</param>
/// <param name="value">The <see cref="long"/> to write.</param>
/// <param name="cancellationToken">The token to cancel the operation. The default value is None.</param>
public static async Task WriteLongAsync(this Stream stream, long value,
CancellationToken cancellationToken = default)
{
var bytes = BitConverter.GetBytes(value);
await stream
.WriteAsync(new[] { bytes[7], bytes[6], bytes[5], bytes[4], bytes[3], bytes[2], bytes[1], bytes[0] }, 0,
8, cancellationToken).ConfigureAwait(false);
}
/// <summary>
/// Asynchronously reads a <see cref="long"/> 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="long"/>.</returns>
public static async Task<long> ReadLongAsync(this Stream stream, CancellationToken cancellationToken = default)
{
var bytes = new byte[8];
await stream.ReadAsync(bytes, 0, 8, cancellationToken).ConfigureAwait(false);
return BitConverter.ToInt64(
new[] {bytes[7], bytes[6], bytes[5], bytes[4], bytes[3], bytes[2], bytes[1], bytes[0]}, 0);
}
/// <summary>
/// Asynchronously writes a <see cref="float"/> to a <see cref="Stream"/>.
/// </summary>
/// <param name="stream">The <see cref="Stream"/> to write the <see cref="float"/> to.</param>
/// <param name="value">The <see cref="float"/> to write.</param>
/// <param name="cancellationToken">The token to cancel the operation. The default value is None.</param>
public static async Task WriteFloatAsync(this Stream stream, float value,
CancellationToken cancellationToken = default)
{
var bytes = BitConverter.GetBytes(value);
await stream.WriteAsync(new[] { bytes[3], bytes[2], bytes[1], bytes[0] }, 0, 4, cancellationToken)
.ConfigureAwait(false);
}
/// <summary>
/// Asynchronously reads a <see cref="float"/> 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="float"/>.</returns>
public static async Task<float> ReadFloatAsync(this Stream stream,
CancellationToken cancellationToken = default)
{
var bytes = new byte[4];
await stream.ReadAsync(bytes, 0, 4, cancellationToken).ConfigureAwait(false);
return BitConverter.ToSingle(new []{bytes[3], bytes[2], bytes[1], bytes[0]}, 0);
}
/// <summary>
/// Asynchronously writes a <see cref="double"/> to a <see cref="Stream"/>.
/// </summary>
/// <param name="stream">The <see cref="Stream"/> to write the <see cref="double"/> to.</param>
/// <param name="value">The <see cref="double"/> to write.</param>
/// <param name="cancellationToken">The token to cancel the operation. The default value is None.</param>
public static async Task WriteDoubleAsync(this Stream stream, double value,
CancellationToken cancellationToken = default)
{
var bytes = BitConverter.GetBytes(value);
await stream
.WriteAsync(new[] {bytes[7], bytes[6], bytes[5], bytes[4], bytes[3], bytes[2], bytes[1], bytes[0]}, 0,
8, cancellationToken).ConfigureAwait(false);
}
/// <summary>
/// Asynchronously reads a <see cref="double"/> 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="double"/>.</returns>
public static async Task<double> ReadDoubleAsync(this Stream stream,
CancellationToken cancellationToken = default)
{
var bytes = new byte[8];
await stream.ReadAsync(bytes, 0, 8, cancellationToken).ConfigureAwait(false);
return BitConverter.ToDouble(
new[] {bytes[7], bytes[6], bytes[5], bytes[4], bytes[3], bytes[2], bytes[1], bytes[0]}, 0);
}
/// <summary>
/// Asynchronously writes a <see cref="short"/> to a <see cref="Stream"/>.
/// </summary>
/// <param name="stream">The <see cref="Stream"/> to write the <see cref="short"/> to.</param>
/// <param name="value">The <see cref="short"/> to write.</param>
/// <param name="cancellationToken">The token to cancel the operation. The default value is None.</param>
public static async Task WriteShortAsync(this Stream stream, short value,
CancellationToken cancellationToken = default)
{
var bytes = BitConverter.GetBytes(value);
await stream.WriteAsync(new[] { bytes[1], bytes[0] }, 0, 2, cancellationToken).ConfigureAwait(false);
}
/// <summary>
/// Asynchronously reads a <see cref="short"/> 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="short"/>.</returns>
public static async Task<short> ReadShortAsync(this Stream stream,
CancellationToken cancellationToken = default)
{
var bytes = new byte[2];
await stream.ReadAsync(bytes, 0, 2, cancellationToken).ConfigureAwait(false);
return BitConverter.ToInt16(new []{bytes[1], bytes[0]}, 0);
}
/// <summary>
/// Asynchronously writes a <see cref="bool"/> to a <see cref="Stream"/>.
/// </summary>
/// <param name="stream">The <see cref="Stream"/> to write the <see cref="bool"/> to.</param>
/// <param name="value">The <see cref="bool"/> to write.</param>
/// <param name="cancellationToken">The token to cancel the operation. The default value is None.</param>
public static async Task WriteBoolAsync(this Stream stream, bool value,
CancellationToken cancellationToken = default)
{
await stream.WriteByteAsync((byte)(value ? 1 : 0), cancellationToken).ConfigureAwait(false);
}
/// <summary>
/// Asynchronously reads a <see cref="bool"/> 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="bool"/>.</returns>
public static async Task<bool> ReadBoolAsync(this Stream stream, CancellationToken cancellationToken = default)
{
var b = await stream.ReadByteAsync(cancellationToken).ConfigureAwait(false);
return b switch
{
1 => true,
0 => false,
_ => throw new IOException($"Cannot read byte {b} as a boolean.")
};
}
/// <summary>
/// Asynchronously writes a <see cref="T:byte[]"/> to a <see cref="Stream"/>.
/// </summary>
/// <param name="stream">The <see cref="Stream"/> to write the <see cref="T:byte[]"/> to.</param>
/// <param name="value">The <see cref="T:byte[]"/> to write.</param>
/// <param name="cancellationToken">The token to cancel the operation. The default value is None.</param>
public static async Task WriteAsync(this Stream stream, byte[] value,
CancellationToken cancellationToken = default)
{
await stream.WriteAsync(value, 0, value.Length, cancellationToken).ConfigureAwait(false);
}
/// <summary>
/// Asynchronously reads a <see cref="T:byte[]"/> from a <see cref="Stream"/> into a buffer.
/// </summary>
/// <param name="stream">The <see cref="Stream"/> to read from.</param>
/// <param name="count">The number of bytes to read.</param>
/// <param name="cancellationToken">The token to cancel the operation. The default value is None.</param>
/// <returns>The read <see cref="T:byte[]"/>.</returns>
public static async Task<byte[]> ReadAsync(this Stream stream, int count,
CancellationToken cancellationToken = default)
{
var buffer = new byte[count];
await stream.ReadAsync(buffer, 0, count, cancellationToken).ConfigureAwait(false);
return buffer;
}
}
}