Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Roundtrip short and ushort serialization #127

Merged
merged 1 commit into from
Jul 1, 2024
Merged
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
55 changes: 55 additions & 0 deletions Fauna.Test/Serialization/RoundTrip.Tests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
using Fauna.Mapping;
using Fauna.Serialization;
using Fauna.Types;
using NUnit.Framework;
using System.Text;
using System.Text.RegularExpressions;

namespace Fauna.Test.Serialization;

[TestFixture]
public class RoundTripTests
{
private static readonly MappingContext ctx = new();

public static string Serialize(object? obj)
{
using var stream = new MemoryStream();
using var writer = new Utf8FaunaWriter(stream);
Serializer.Serialize(ctx, writer, obj);
writer.Flush();
return Encoding.UTF8.GetString(stream.ToArray());
}

public static T Deserialize<T>(string str) where T : notnull
{
var reader = new Utf8FaunaReader(str);
reader.Read();
var obj = Deserializer.Generate<T>(ctx).Deserialize(ctx, ref reader);
if (reader.Read())
{
throw new SerializationException($"Token stream is not exhausted but should be: {reader.CurrentTokenType}");
}

return obj;
}

[Test]
public void RoundTripShort()
{
const short test = 40;
var serialized = Serialize(test);
var deserialized = Deserialize<short>(serialized);
Assert.AreEqual(test, deserialized);
}

[Test]
public void RoundTripUShort()
{
const ushort test = 40;
var serialized = Serialize(test);
var deserialized = Deserialize<ushort>(serialized);
Assert.AreEqual(test, deserialized);
}

}
4 changes: 4 additions & 0 deletions Fauna/Serialization/Deserializer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ public static class Deserializer
private static readonly CheckedDeserializer<string> _string = new();
private static readonly CheckedDeserializer<int> _int = new();
private static readonly LongDeserializer _long = new();
private static readonly ShortDeserializer _short = new();
private static readonly UShortDeserializer _ushort = new();
private static readonly CheckedDeserializer<double> _double = new();
private static readonly CheckedDeserializer<DateOnly> _dateOnly = new();
private static readonly CheckedDeserializer<DateTime> _dateTime = new();
Expand Down Expand Up @@ -50,6 +52,8 @@ public static IDeserializer Generate(MappingContext context, Type targetType)
{
if (targetType == typeof(object)) return _object;
if (targetType == typeof(string)) return _string;
if (targetType == typeof(short)) return _short;
if (targetType == typeof(ushort)) return _ushort;
if (targetType == typeof(int)) return _int;
if (targetType == typeof(long)) return _long;
if (targetType == typeof(double)) return _double;
Expand Down
24 changes: 24 additions & 0 deletions Fauna/Serialization/NumberDeserializers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,27 @@ public override long Deserialize(MappingContext context, ref Utf8FaunaReader rea
$"Unexpected token while deserializing: {reader.CurrentTokenType}"),
};
}

internal class ShortDeserializer : BaseDeserializer<short>
{
public override short Deserialize(MappingContext context, ref Utf8FaunaReader reader) =>
reader.CurrentTokenType switch
{
TokenType.Int => reader.GetShort(),
TokenType.Long => reader.GetShort(),
_ => throw new SerializationException(
$"Unexpected token while deserializing: {reader.CurrentTokenType}"),
};
}

internal class UShortDeserializer : BaseDeserializer<ushort>
{
public override ushort Deserialize(MappingContext context, ref Utf8FaunaReader reader) =>
reader.CurrentTokenType switch
{
TokenType.Int => reader.GetUnsignedShort(),
TokenType.Long => reader.GetUnsignedShort(),
_ => throw new SerializationException(
$"Unexpected token while deserializing: {reader.CurrentTokenType}"),
};
}
43 changes: 43 additions & 0 deletions Fauna/Serialization/Utf8FaunaReader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,40 @@ public int GetInt()
}
}

/// <summary>
/// Retrieves an short value from the current token.
/// </summary>
/// <returns>An short representation of the current token's value.</returns>
public short GetShort()
{
ValidateTaggedTypes(TokenType.Int, TokenType.Long);
try
{
return short.Parse(_taggedTokenValue!);
}
catch (Exception e)
{
throw new SerializationException($"Failed to get short from {_taggedTokenValue}", e);
}
}

/// <summary>
/// Retrieves an unsigned short value from the current token.
/// </summary>
/// <returns>An unsigned short representation of the current token's value.</returns>
public ushort GetUnsignedShort()
{
ValidateTaggedTypes(TokenType.Int, TokenType.Long);
try
{
return ushort.Parse(_taggedTokenValue!);
}
catch (Exception e)
{
throw new SerializationException($"Failed to get ushort from {_taggedTokenValue}", e);
}
}

/// <summary>
/// Retrieves a long value from the current token.
/// </summary>
Expand Down Expand Up @@ -406,6 +440,15 @@ private void ValidateTaggedType(TokenType type)
}
}

private void ValidateTaggedTypes(params TokenType[] types)
{
if (!types.Contains(CurrentTokenType) || _taggedTokenValue == null || _taggedTokenValue.GetType() != typeof(string))
{
throw new InvalidOperationException($"CurrentTokenType is a {CurrentTokenType.ToString()}, not in {types}.");
}
}


private void HandleStartObject()
{
AdvanceTrue();
Expand Down
Loading