Skip to content

Commit

Permalink
Start implementing serializer
Browse files Browse the repository at this point in the history
  • Loading branch information
halgari committed Jan 8, 2024
1 parent de00849 commit c14793c
Show file tree
Hide file tree
Showing 6 changed files with 204 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
using System.Linq.Expressions;

namespace NexusMods.EventSourcing.Abstractions.Serialization;


/// <summary>
/// A typed value serializer for a dynamic size value.
/// </summary>
/// <typeparam name="T"></typeparam>
public interface IDynamicValueSerializer<T> : IValueSerializer
{
/// <summary>
/// Given an expression of type Span byte deserialize the value and return an expression of type T. The span
/// will be the size originally returned by GetSizeExpression, when the value was serialized.
/// </summary>
/// <param name="span"></param>
/// <returns></returns>
public Expression<T> CreateDeserializationExpression(Expression span);

/// <summary>
/// Serialize the value into the given span and return the expression for the code, GetSizeExpression will be
/// called first to get the size of the serialized value, and make sure the span is large enough.
/// </summary>
/// <param name="span"></param>
/// <param name="value"></param>
/// <returns></returns>
public Expression CreateSerializationExpression(Expression span, Expression<T> value);

/// <summary>
/// Since the size is dynamic, this gets the expression for the size of the serialized value.
/// </summary>
/// <returns></returns>
public Expression GetSizeExpression(Expression<T> value);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
using System;
using System.Linq.Expressions;

namespace NexusMods.EventSourcing.Abstractions.Serialization;

/// <summary>
/// A typed value serializer for a static size value.
/// </summary>
/// <typeparam name="T"></typeparam>
public interface IStaticValueSerializer<T> : IValueSerializer
{
/// <summary>
/// Deserialize the value from the given span and return the value.
/// </summary>
/// <param name="span"></param>
/// <param name="value"></param>
public void Deserialize(ref Span<byte> span, ref T value);

/// <summary>
/// Serialize the value into the given span.
/// </summary>
/// <param name="span"></param>
/// <param name="value"></param>
public void Serialize(ref Span<byte> span, ref T value);

/// <summary>
/// Since the size is static, this gets the fixed size of the serialized value.
/// </summary>
/// <returns></returns>
public int GetSize();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
using System;
using System.Linq.Expressions;

namespace NexusMods.EventSourcing.Abstractions.Serialization;

/// <summary>
/// A value serializer.
/// </summary>
public interface IValueSerializer
{
/// <summary>
/// The type this serializer is for.
/// </summary>
public Type ForType { get; }

/// <summary>
/// True if the size of the serialized value is dynamic (changes based on the value).
/// </summary>
public bool IsDynamicSize { get; }

}
39 changes: 39 additions & 0 deletions src/NexusMods.EventSourcing/Serializers/Int8Serializer.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
using System;
using System.Buffers.Binary;
using System.Linq.Expressions;
using NexusMods.EventSourcing.Abstractions.Serialization;

namespace NexusMods.EventSourcing.Serializers;

/// <summary>
/// Int8Serializer
/// </summary>
public sealed class Int8Serializer : IStaticValueSerializer<byte>
{
/// <inheritdoc />
public Type ForType => typeof(byte);

/// <inheritdoc />
public bool IsDynamicSize => false;

/// <inheritdoc />
public void Deserialize(ref Span<byte> span, ref byte value)
{
value = span[0];
}

/// <inheritdoc />
public void Serialize(ref Span<byte> span, ref byte value)
{
span[0] = value;
}

/// <inheritdoc />
public int GetSize()
{
return sizeof(byte);
}
}



33 changes: 33 additions & 0 deletions src/NexusMods.EventSourcing/Serializers/UInt32Serializer.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
using System;
using System.Buffers.Binary;
using NexusMods.EventSourcing.Abstractions.Serialization;

namespace NexusMods.EventSourcing.Serializers;

/// <inheritdoc />
public sealed class UInt32Serializer : IStaticValueSerializer<uint>
{
/// <inheritdoc />
public Type ForType => typeof(uint);

/// <inheritdoc />
public bool IsDynamicSize => false;

/// <inheritdoc />
public void Deserialize(ref Span<byte> span, ref uint value)
{
value = BinaryPrimitives.ReadUInt32BigEndian(span);
}

/// <inheritdoc />
public void Serialize(ref Span<byte> span, ref uint value)
{
BinaryPrimitives.WriteUInt32BigEndian(span, value);
}

/// <inheritdoc />
public int GetSize()
{
return 4;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
using System.Buffers.Binary;
using System.Linq.Expressions;
using System.Reflection;
using NexusMods.EventSourcing.Serializers;

namespace NexusMods.EventSourcing.Tests.SerializerTests;

public class IntSerializerTests
{

[Theory]
[InlineData(byte.MaxValue)]
[InlineData(42)]
[InlineData(byte.MinValue)]
public void CanHandleInt8(byte val)
{
var serializer = new Int8Serializer();
var span = new Span<byte>(new byte[1]);
serializer.Serialize(ref span, ref val);
span[0].Should().Be(val);

var val2 = byte.MinValue;
serializer.Deserialize(ref span, ref val2);
val2.Should().Be(val);

}

[Theory]
[InlineData(uint.MaxValue)]
[InlineData(int.MaxValue)]
[InlineData(short.MaxValue)]
[InlineData(byte.MaxValue)]
[InlineData(0)]
public void CanHandleUInt32(uint val)
{
var serializer = new UInt32Serializer();
var span = new Span<byte>(new byte[4]);
serializer.Serialize(ref span, ref val);
BinaryPrimitives.ReadUInt32BigEndian(span).Should().Be(val);

var val2 = uint.MinValue;
serializer.Deserialize(ref span, ref val2);
val2.Should().Be(val);
}

}

0 comments on commit c14793c

Please sign in to comment.