diff --git a/src/Voltaic.Serialization.Etf/Readers/EtfReader.Float.cs b/src/Voltaic.Serialization.Etf/Readers/EtfReader.Float.cs index cfd2cc3..2ed60b2 100644 --- a/src/Voltaic.Serialization.Etf/Readers/EtfReader.Float.cs +++ b/src/Voltaic.Serialization.Etf/Readers/EtfReader.Float.cs @@ -21,11 +21,25 @@ public static bool TryReadSingle(ref ReadOnlySpan remaining, out float res { case EtfTokenType.NewFloat: { + // TODO: Untested, does Discord have any endpoints that accept floats? if (remaining.Length < 8) return false; - //remaining = remaining.Slice(1) - result = MemoryMarshal.Cast(remaining.Slice(1, 8))[0]; - remaining = remaining.Slice(9); + remaining = remaining.Slice(1); + Span dst = stackalloc double[1]; + var dstBytes = MemoryMarshal.AsBytes(dst); + + // Swap endian + dstBytes[0] = remaining[7]; + dstBytes[1] = remaining[6]; + dstBytes[2] = remaining[5]; + dstBytes[3] = remaining[4]; + dstBytes[4] = remaining[3]; + dstBytes[5] = remaining[2]; + dstBytes[6] = remaining[1]; + dstBytes[7] = remaining[0]; + + result = (float)dst[0]; + remaining = remaining.Slice(8); return true; } default: @@ -48,11 +62,25 @@ public static bool TryReadDouble(ref ReadOnlySpan remaining, out double re { case EtfTokenType.NewFloat: { + // TODO: Untested, does Discord have any endpoints that accept floats? if (remaining.Length < 8) return false; - //remaining = remaining.Slice(1) - result = MemoryMarshal.Cast(remaining.Slice(1, 8))[0]; - remaining = remaining.Slice(9); + remaining = remaining.Slice(1); + Span dst = stackalloc double[1]; + var dstBytes = MemoryMarshal.AsBytes(dst); + + // Swap endian + dstBytes[0] = remaining[7]; + dstBytes[1] = remaining[6]; + dstBytes[2] = remaining[5]; + dstBytes[3] = remaining[4]; + dstBytes[4] = remaining[3]; + dstBytes[5] = remaining[2]; + dstBytes[6] = remaining[1]; + dstBytes[7] = remaining[0]; + + result = dst[0]; + remaining = remaining.Slice(8); return true; } default: diff --git a/src/Voltaic.Serialization.Etf/Writers/EtfWriter.Float.cs b/src/Voltaic.Serialization.Etf/Writers/EtfWriter.Float.cs index da383f1..e120bd4 100644 --- a/src/Voltaic.Serialization.Etf/Writers/EtfWriter.Float.cs +++ b/src/Voltaic.Serialization.Etf/Writers/EtfWriter.Float.cs @@ -9,11 +9,24 @@ public static partial class EtfWriter { public static bool TryWrite(ref ResizableMemory writer, float value, StandardFormat standardFormat) { + // TODO: Untested, does Discord have any endpoints that accept floats? if (standardFormat.IsDefault) { - Span arr = stackalloc float[] { value }; writer.Push((byte)EtfTokenType.NewFloat); - MemoryMarshal.AsBytes(arr).CopyTo(writer.GetSpan(8)); + + // Swap endian + Span src = stackalloc double[] { value }; + var srcBytes = MemoryMarshal.AsBytes(src); + var dst = writer.GetSpan(8); + + dst[0] = srcBytes[7]; + dst[1] = srcBytes[6]; + dst[2] = srcBytes[5]; + dst[3] = srcBytes[4]; + dst[4] = srcBytes[3]; + dst[5] = srcBytes[2]; + dst[6] = srcBytes[1]; + dst[7] = srcBytes[0]; writer.Advance(8); } else @@ -34,11 +47,24 @@ public static bool TryWrite(ref ResizableMemory writer, float value, Stand public static bool TryWrite(ref ResizableMemory writer, double value, StandardFormat standardFormat) { + // TODO: Untested, does Discord have any endpoints that accept floats? if (standardFormat.IsDefault) { - Span arr = stackalloc float[] { (float)value }; writer.Push((byte)EtfTokenType.NewFloat); - MemoryMarshal.AsBytes(arr).CopyTo(writer.GetSpan(8)); + + // Swap endian + Span src = stackalloc double[] { value }; + var srcBytes = MemoryMarshal.AsBytes(src); + var dst = writer.GetSpan(8); + + dst[0] = srcBytes[7]; + dst[1] = srcBytes[6]; + dst[2] = srcBytes[5]; + dst[3] = srcBytes[4]; + dst[4] = srcBytes[3]; + dst[5] = srcBytes[2]; + dst[6] = srcBytes[1]; + dst[7] = srcBytes[0]; writer.Advance(8); } else diff --git a/test/Voltaic.Serialization.Etf.Tests/Float.cs b/test/Voltaic.Serialization.Etf.Tests/Float.cs index 9eca803..a99ee33 100644 --- a/test/Voltaic.Serialization.Etf.Tests/Float.cs +++ b/test/Voltaic.Serialization.Etf.Tests/Float.cs @@ -8,7 +8,13 @@ public class SingleTests : BaseTest { public static IEnumerable GetNumberData() { - throw new NotImplementedException(); + yield return ReadWrite(EtfTokenType.NewFloat, new byte[] { 0xC7, 0xEF, 0xFF, 0xFF, 0xA0, 0x00, 0x00, 0x00 }, -3.402823e38f); // Min + yield return ReadWrite(EtfTokenType.NewFloat, new byte[] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, 0); + yield return ReadWrite(EtfTokenType.NewFloat, new byte[] { 0x47, 0xEF, 0xFF, 0xFF, 0xA0, 0x00, 0x00, 0x00 }, 3.402823e38f); // Max + + yield return ReadWrite(EtfTokenType.NewFloat, new byte[] { 0x7F, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, float.PositiveInfinity); + yield return ReadWrite(EtfTokenType.NewFloat, new byte[] { 0xFF, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, float.NegativeInfinity); + yield return ReadWrite(EtfTokenType.NewFloat, new byte[] { 0xFF, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, float.NaN); } public static IEnumerable GetGData() => TextToBinary(Utf8.Tests.SingleTests.GetGData()); public static IEnumerable GetLittleGData() => TextToBinary(Utf8.Tests.SingleTests.GetLittleGData()); @@ -40,7 +46,13 @@ public class DoubleTests : BaseTest { public static IEnumerable GetNumberData() { - throw new NotImplementedException(); + yield return ReadWrite(EtfTokenType.NewFloat, new byte[] { 0xFF, 0xEF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, -1.7976931348623157e308d); // Min + yield return ReadWrite(EtfTokenType.NewFloat, new byte[] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, 0d); + yield return ReadWrite(EtfTokenType.NewFloat, new byte[] { 0x7F, 0xEF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, 1.7976931348623157e308d); // Max + + yield return ReadWrite(EtfTokenType.NewFloat, new byte[] { 0x7F, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, double.PositiveInfinity); + yield return ReadWrite(EtfTokenType.NewFloat, new byte[] { 0xFF, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, double.NegativeInfinity); + yield return ReadWrite(EtfTokenType.NewFloat, new byte[] { 0xFF, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, double.NaN); } public static IEnumerable GetGData() => TextToBinary(Utf8.Tests.DoubleTests.GetGData()); public static IEnumerable GetLittleGData() => TextToBinary(Utf8.Tests.DoubleTests.GetLittleGData());