mirror of
https://github.com/FabInfra/capnproto-dotnetcore_Runtime.git
synced 2025-03-12 14:51:41 +01:00
342 lines
16 KiB
C#
342 lines
16 KiB
C#
using System;
|
|
using System.Runtime.InteropServices;
|
|
|
|
namespace Capnp
|
|
{
|
|
/// <summary>
|
|
/// Provides extensions to the <see cref="IStructDeserializer"/> and <see cref="IStructSerializer"/> interfaces for type-safe reading and writing.
|
|
/// </summary>
|
|
public static class SerializerExtensions
|
|
{
|
|
/// <summary>
|
|
/// Reads a boolean field.
|
|
/// </summary>
|
|
/// <typeparam name="T">Type implementing <see cref="IStructDeserializer"/></typeparam>
|
|
/// <param name="d">"this" instance</param>
|
|
/// <param name="bitOffset">Start bit</param>
|
|
/// <param name="defaultValue">Field default value (will be XORed with the result)</param>
|
|
/// <returns>The read value</returns>
|
|
public static bool ReadDataBool<T>(this T d, ulong bitOffset, bool defaultValue = false)
|
|
where T: IStructDeserializer
|
|
{
|
|
return (d.StructReadData(bitOffset, 1) != 0) != defaultValue;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Writes a boolean field.
|
|
/// </summary>
|
|
/// <typeparam name="T">Type implementing <see cref="IStructSerializer"/></typeparam>
|
|
/// <param name="d">"this" instance</param>
|
|
/// <param name="bitOffset">Start bit</param>
|
|
/// <param name="value">Value to write</param>
|
|
/// <param name="defaultValue">Field default value (will be XORed with the value to write)</param>
|
|
public static void WriteData<T>(this T d, ulong bitOffset, bool value, bool defaultValue = false)
|
|
where T : IStructSerializer
|
|
{
|
|
d.StructWriteData(bitOffset, 1, value != defaultValue ? 1ul : 0);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Reads a byte field.
|
|
/// </summary>
|
|
/// <typeparam name="T">Type implementing <see cref="IStructDeserializer"/></typeparam>
|
|
/// <param name="d">"this" instance</param>
|
|
/// <param name="bitOffset">Start bit</param>
|
|
/// <param name="defaultValue">Field default value (will be XORed with the result)</param>
|
|
/// <returns>The read value</returns>
|
|
public static byte ReadDataByte<T>(this T d, ulong bitOffset, byte defaultValue = 0)
|
|
where T : IStructDeserializer
|
|
{
|
|
return (byte)(d.StructReadData(bitOffset, 8) ^ defaultValue);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Writes a byte field.
|
|
/// </summary>
|
|
/// <typeparam name="T">Type implementing <see cref="IStructSerializer"/></typeparam>
|
|
/// <param name="d">"this" instance</param>
|
|
/// <param name="bitOffset">Start bit</param>
|
|
/// <param name="value">Value to write</param>
|
|
/// <param name="defaultValue">Field default value (will be XORed with the value to write)</param>
|
|
public static void WriteData<T>(this T d, ulong bitOffset, byte value, byte defaultValue = 0)
|
|
where T : IStructSerializer
|
|
{
|
|
d.StructWriteData(bitOffset, 8, (byte)(value ^ defaultValue));
|
|
}
|
|
|
|
/// <summary>
|
|
/// Reads a signed byte field.
|
|
/// </summary>
|
|
/// <typeparam name="T">Type implementing <see cref="IStructDeserializer"/></typeparam>
|
|
/// <param name="d">"this" instance</param>
|
|
/// <param name="bitOffset">Start bit</param>
|
|
/// <param name="defaultValue">Field default value (will be XORed with the result)</param>
|
|
/// <returns>The read value</returns>
|
|
public static sbyte ReadDataSByte<T>(this T d, ulong bitOffset, sbyte defaultValue = 0)
|
|
where T : IStructDeserializer
|
|
{
|
|
return (sbyte)((sbyte)d.StructReadData(bitOffset, 8) ^ defaultValue);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Writes a signed byte field.
|
|
/// </summary>
|
|
/// <typeparam name="T">Type implementing <see cref="IStructSerializer"/></typeparam>
|
|
/// <param name="d">"this" instance</param>
|
|
/// <param name="bitOffset">Start bit</param>
|
|
/// <param name="value">Value to write</param>
|
|
/// <param name="defaultValue">Field default value (will be XORed with the value to write)</param>
|
|
public static void WriteData<T>(this T d, ulong bitOffset, sbyte value, sbyte defaultValue = 0)
|
|
where T : IStructSerializer
|
|
{
|
|
d.StructWriteData(bitOffset, 8, unchecked((ulong)(value ^ defaultValue)));
|
|
}
|
|
|
|
/// <summary>
|
|
/// Reads a ushort field.
|
|
/// </summary>
|
|
/// <typeparam name="T">Type implementing <see cref="IStructDeserializer"/></typeparam>
|
|
/// <param name="d">"this" instance</param>
|
|
/// <param name="bitOffset">Start bit</param>
|
|
/// <param name="defaultValue">Field default value (will be XORed with the result)</param>
|
|
/// <returns>The read value</returns>
|
|
public static ushort ReadDataUShort<T>(this T d, ulong bitOffset, ushort defaultValue = 0)
|
|
where T : IStructDeserializer
|
|
{
|
|
return (ushort)(d.StructReadData(bitOffset, 16) ^ defaultValue);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Writes a ushort field.
|
|
/// </summary>
|
|
/// <typeparam name="T">Type implementing <see cref="IStructSerializer"/></typeparam>
|
|
/// <param name="d">"this" instance</param>
|
|
/// <param name="bitOffset">Start bit</param>
|
|
/// <param name="value">Value to write</param>
|
|
/// <param name="defaultValue">Field default value (will be XORed with the value to write)</param>
|
|
public static void WriteData<T>(this T d, ulong bitOffset, ushort value, ushort defaultValue = 0)
|
|
where T : IStructSerializer
|
|
{
|
|
d.StructWriteData(bitOffset, 16, (ushort)(value ^ defaultValue));
|
|
}
|
|
|
|
/// <summary>
|
|
/// Reads a short field.
|
|
/// </summary>
|
|
/// <typeparam name="T">Type implementing <see cref="IStructDeserializer"/></typeparam>
|
|
/// <param name="d">"this" instance</param>
|
|
/// <param name="bitOffset">Start bit</param>
|
|
/// <param name="defaultValue">Field default value (will be XORed with the result)</param>
|
|
/// <returns>The read value</returns>
|
|
public static short ReadDataShort<T>(this T d, ulong bitOffset, short defaultValue = 0)
|
|
where T : IStructDeserializer
|
|
{
|
|
return (short)((short)d.StructReadData(bitOffset, 16) ^ defaultValue);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Writes a short field.
|
|
/// </summary>
|
|
/// <typeparam name="T">Type implementing <see cref="IStructSerializer"/></typeparam>
|
|
/// <param name="d">"this" instance</param>
|
|
/// <param name="bitOffset">Start bit</param>
|
|
/// <param name="value">Value to write</param>
|
|
/// <param name="defaultValue">Field default value (will be XORed with the value to write)</param>
|
|
public static void WriteData<T>(this T d, ulong bitOffset, short value, short defaultValue = 0)
|
|
where T : IStructSerializer
|
|
{
|
|
d.StructWriteData(bitOffset, 16, unchecked((ulong)(value ^ defaultValue)));
|
|
}
|
|
|
|
/// <summary>
|
|
/// Reads a uint field.
|
|
/// </summary>
|
|
/// <typeparam name="T">Type implementing <see cref="IStructDeserializer"/></typeparam>
|
|
/// <param name="d">"this" instance</param>
|
|
/// <param name="bitOffset">Start bit</param>
|
|
/// <param name="defaultValue">Field default value (will be XORed with the result)</param>
|
|
/// <returns>The read value</returns>
|
|
public static uint ReadDataUInt<T>(this T d, ulong bitOffset, uint defaultValue = 0)
|
|
where T : IStructDeserializer
|
|
{
|
|
return (uint)(d.StructReadData(bitOffset, 32) ^ defaultValue);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Writes a uint field.
|
|
/// </summary>
|
|
/// <typeparam name="T">Type implementing <see cref="IStructSerializer"/></typeparam>
|
|
/// <param name="d">"this" instance</param>
|
|
/// <param name="bitOffset">Start bit</param>
|
|
/// <param name="value">Value to write</param>
|
|
/// <param name="defaultValue">Field default value (will be XORed with the value to write)</param>
|
|
public static void WriteData<T>(this T d, ulong bitOffset, uint value, uint defaultValue = 0)
|
|
where T : IStructSerializer
|
|
{
|
|
d.StructWriteData(bitOffset, 32, value ^ defaultValue);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Performs a "reinterpret cast" of the struct's data section and returns a reference to a single element of the cast result.
|
|
/// </summary>
|
|
/// <typeparam name="U">The cast target type. Must be a primitive type which qualifies for <code><![CDATA[MemoryMarshal.Cast<ulong, U>()]]></code></typeparam>
|
|
/// <param name="d">"this" instance</param>
|
|
/// <param name="woffset">Index within the cast result, conceptually into <code>U[]</code></param>
|
|
/// <returns>A reference to the data element</returns>
|
|
public static ref U RefData<U>(this IStructSerializer d, int woffset)
|
|
where U: struct
|
|
{
|
|
var data = MemoryMarshal.Cast<ulong, U>(d.StructDataSection);
|
|
return ref MemoryMarshal.GetReference(data.Slice(woffset, 1));
|
|
}
|
|
|
|
/// <summary>
|
|
/// Reads an int field.
|
|
/// </summary>
|
|
/// <typeparam name="T">Type implementing <see cref="IStructDeserializer"/></typeparam>
|
|
/// <param name="d">"this" instance</param>
|
|
/// <param name="bitOffset">Start bit</param>
|
|
/// <param name="defaultValue">Field default value (will be XORed with the result)</param>
|
|
/// <returns>The read value</returns>
|
|
public static int ReadDataInt<T>(this T d, ulong bitOffset, int defaultValue = 0)
|
|
where T : IStructDeserializer
|
|
{
|
|
return (int)d.StructReadData(bitOffset, 32) ^ defaultValue;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Writes an int field.
|
|
/// </summary>
|
|
/// <typeparam name="T">Type implementing <see cref="IStructSerializer"/></typeparam>
|
|
/// <param name="d">"this" instance</param>
|
|
/// <param name="bitOffset">Start bit</param>
|
|
/// <param name="value">Value to write</param>
|
|
/// <param name="defaultValue">Field default value (will be XORed with the value to write)</param>
|
|
public static void WriteData<T>(this T d, ulong bitOffset, int value, int defaultValue = 0)
|
|
where T : IStructSerializer
|
|
{
|
|
d.StructWriteData(bitOffset, 32, unchecked((ulong)(value ^ defaultValue)));
|
|
}
|
|
|
|
/// <summary>
|
|
/// Reads a ulong field.
|
|
/// </summary>
|
|
/// <typeparam name="T">Type implementing <see cref="IStructDeserializer"/></typeparam>
|
|
/// <param name="d">"this" instance</param>
|
|
/// <param name="bitOffset">Start bit</param>
|
|
/// <param name="defaultValue">Field default value (will be XORed with the result)</param>
|
|
/// <returns>The read value</returns>
|
|
public static ulong ReadDataULong<T>(this T d, ulong bitOffset, ulong defaultValue = 0)
|
|
where T : IStructDeserializer
|
|
{
|
|
return d.StructReadData(bitOffset, 64) ^ defaultValue;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Writes a ulong field.
|
|
/// </summary>
|
|
/// <typeparam name="T">Type implementing <see cref="IStructSerializer"/></typeparam>
|
|
/// <param name="d">"this" instance</param>
|
|
/// <param name="bitOffset">Start bit</param>
|
|
/// <param name="value">Value to write</param>
|
|
/// <param name="defaultValue">Field default value (will be XORed with the value to write)</param>
|
|
public static void WriteData<T>(this T d, ulong bitOffset, ulong value, ulong defaultValue = 0)
|
|
where T : IStructSerializer
|
|
{
|
|
d.StructWriteData(bitOffset, 64, value ^ defaultValue);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Reads a long field.
|
|
/// </summary>
|
|
/// <typeparam name="T">Type implementing <see cref="IStructDeserializer"/></typeparam>
|
|
/// <param name="d">"this" instance</param>
|
|
/// <param name="bitOffset">Start bit</param>
|
|
/// <param name="defaultValue">Field default value (will be XORed with the result)</param>
|
|
/// <returns>The read value</returns>
|
|
public static long ReadDataLong<T>(this T d, ulong bitOffset, long defaultValue = 0)
|
|
where T : IStructDeserializer
|
|
{
|
|
return (long)d.StructReadData(bitOffset, 64) ^ defaultValue;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Writes a long field.
|
|
/// </summary>
|
|
/// <typeparam name="T">Type implementing <see cref="IStructSerializer"/></typeparam>
|
|
/// <param name="d">"this" instance</param>
|
|
/// <param name="bitOffset">Start bit</param>
|
|
/// <param name="value">Value to write</param>
|
|
/// <param name="defaultValue">Field default value (will be XORed with the value to write)</param>
|
|
public static void WriteData<T>(this T d, ulong bitOffset, long value, long defaultValue = 0)
|
|
where T : IStructSerializer
|
|
{
|
|
d.StructWriteData(bitOffset, 64, unchecked((ulong)(value ^ defaultValue)));
|
|
}
|
|
|
|
/// <summary>
|
|
/// Reads a float field.
|
|
/// </summary>
|
|
/// <typeparam name="T">Type implementing <see cref="IStructDeserializer"/></typeparam>
|
|
/// <param name="d">"this" instance</param>
|
|
/// <param name="bitOffset">Start bit</param>
|
|
/// <param name="defaultValue">Field default value (raw bits will be XORed with the result)</param>
|
|
/// <returns>The read value</returns>
|
|
public static float ReadDataFloat<T>(this T d, ulong bitOffset, float defaultValue = 0)
|
|
where T : IStructDeserializer
|
|
{
|
|
int defaultBits = BitConverter.SingleToInt32Bits(defaultValue);
|
|
int bits = (int)d.StructReadData(bitOffset, 32) ^ defaultBits;
|
|
return BitConverter.Int32BitsToSingle(bits);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Writes a float field.
|
|
/// </summary>
|
|
/// <typeparam name="T">Type implementing <see cref="IStructSerializer"/></typeparam>
|
|
/// <param name="d">"this" instance</param>
|
|
/// <param name="bitOffset">Start bit</param>
|
|
/// <param name="value">Value to write</param>
|
|
/// <param name="defaultValue">Field default value (raw bits will be XORed with the value to write)</param>
|
|
public static void WriteData<T>(this T d, ulong bitOffset, float value, float defaultValue = 0.0f)
|
|
where T : IStructSerializer
|
|
{
|
|
int bits = BitConverter.SingleToInt32Bits(value);
|
|
int defaultBits = BitConverter.SingleToInt32Bits(defaultValue);
|
|
WriteData(d, bitOffset, bits, defaultBits);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Reads a double field.
|
|
/// </summary>
|
|
/// <typeparam name="T">Type implementing <see cref="IStructDeserializer"/></typeparam>
|
|
/// <param name="d">"this" instance</param>
|
|
/// <param name="bitOffset">Start bit</param>
|
|
/// <param name="defaultValue">Field default value (raw bits will be XORed with the result)</param>
|
|
/// <returns>The read value</returns>
|
|
public static double ReadDataDouble<T>(this T d, ulong bitOffset, double defaultValue = 0)
|
|
where T : IStructDeserializer
|
|
{
|
|
long defaultBits = BitConverter.DoubleToInt64Bits(defaultValue);
|
|
long bits = (long)d.StructReadData(bitOffset, 64) ^ defaultBits;
|
|
return BitConverter.Int64BitsToDouble(bits);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Writes a double field.
|
|
/// </summary>
|
|
/// <typeparam name="T">Type implementing <see cref="IStructSerializer"/></typeparam>
|
|
/// <param name="d">"this" instance</param>
|
|
/// <param name="bitOffset">Start bit</param>
|
|
/// <param name="value">Value to write</param>
|
|
/// <param name="defaultValue">Field default value (raw bits will be XORed with the value to write)</param>
|
|
public static void WriteData<T>(this T d, ulong bitOffset, double value, double defaultValue = 0.0)
|
|
where T : IStructSerializer
|
|
{
|
|
long bits = BitConverter.DoubleToInt64Bits(value);
|
|
long defaultBits = BitConverter.DoubleToInt64Bits(defaultValue);
|
|
WriteData(d, bitOffset, bits, defaultBits);
|
|
}
|
|
}
|
|
}
|