Exemple #1
0
 public static bool TryWrite(ref ResizableMemory <byte> writer, bool value, StandardFormat standardFormat)
 {
     if (standardFormat.IsDefault)
     {
         if (value)
         {
             _trueValue.Span.CopyTo(writer.RequestSpan(6));
             writer.Advance(6);
         }
         else
         {
             _falseValue.Span.CopyTo(writer.RequestSpan(7));
             writer.Advance(7);
         }
     }
     else
     {
         int start = writer.Length;
         writer.Push((byte)EtfTokenType.Binary);
         writer.Advance(4);
         if (!Utf8Writer.TryWrite(ref writer, value, standardFormat))
         {
             return(false);
         }
         int length = writer.Length - start - 5;
         writer.Array[start + 1] = (byte)(length >> 24);
         writer.Array[start + 2] = (byte)(length >> 16);
         writer.Array[start + 3] = (byte)(length >> 8);
         writer.Array[start + 4] = (byte)length;
     }
     return(true);
 }
Exemple #2
0
        public static bool TryWrite(ref ResizableMemory <byte> writer, long value, StandardFormat standardFormat)
        {
            if (standardFormat.IsDefault)
            {
                if (value <= byte.MaxValue && value >= byte.MinValue)
                {
                    return(TryWrite(ref writer, (byte)value, standardFormat));
                }
                if (value <= int.MaxValue && value >= int.MinValue)
                {
                    return(TryWrite(ref writer, (int)value, standardFormat));
                }

                writer.Push((byte)EtfTokenType.SmallBig);
                writer.Push(8);
                if (value >= 0)
                {
                    writer.Push(0);
                    BinaryPrimitives.WriteUInt64LittleEndian(writer.RequestSpan(8), (ulong)value);
                }
                else
                {
                    writer.Push(1);
                    if (value == long.MinValue)
                    {
                        BinaryPrimitives.WriteUInt64LittleEndian(writer.RequestSpan(8), 9223372036854775808);
                    }
                    else
                    {
                        BinaryPrimitives.WriteUInt64LittleEndian(writer.RequestSpan(8), (ulong)-value);
                    }
                }
                writer.Advance(8);
            }
            else
            {
                int start = writer.Length;
                writer.Push((byte)EtfTokenType.Binary);
                writer.Advance(4);
                if (!Utf8Writer.TryWrite(ref writer, value, standardFormat))
                {
                    return(false);
                }
                int length = writer.Length - start - 5;
                writer.Array[start + 1] = (byte)(length >> 24);
                writer.Array[start + 2] = (byte)(length >> 16);
                writer.Array[start + 3] = (byte)(length >> 8);
                writer.Array[start + 4] = (byte)length;
            }
            return(true);
        }
Exemple #3
0
        public static bool TryWrite(ref ResizableMemory <byte> writer, int value, StandardFormat standardFormat)
        {
            if (standardFormat.IsDefault)
            {
                if (value <= byte.MaxValue && value >= byte.MinValue)
                {
                    return(TryWrite(ref writer, (byte)value, standardFormat));
                }

                writer.Push((byte)EtfTokenType.Integer);
                BinaryPrimitives.WriteInt32BigEndian(writer.RequestSpan(4), value);
                writer.Advance(4);
            }
            else
            {
                int start = writer.Length;
                writer.Push((byte)EtfTokenType.Binary);
                writer.Advance(4);
                if (!Utf8Writer.TryWrite(ref writer, value, standardFormat))
                {
                    return(false);
                }
                int length = writer.Length - start - 5;
                writer.Array[start + 1] = (byte)(length >> 24);
                writer.Array[start + 2] = (byte)(length >> 16);
                writer.Array[start + 3] = (byte)(length >> 8);
                writer.Array[start + 4] = (byte)length;
            }
            return(true);
        }
Exemple #4
0
        public static bool TryWriteString(ref ResizableMemory <byte> writer, ReadOnlySpan <byte> value)
        {
            var dstSpan = writer.RequestSpan(value.Length);

            value.CopyTo(dstSpan);
            writer.Advance(value.Length);
            return(true);
        }
Exemple #5
0
        public static bool TryWriteNull(ref ResizableMemory <byte> writer)
        {
            var        data      = writer.RequestSpan(4); // null
            const uint nullValue = ('n' << 24) + ('u' << 16) + ('l' << 8) + ('l' << 0);

            BinaryPrimitives.WriteUInt32BigEndian(data, nullValue);
            writer.Advance(4);
            return(true);
        }
        public static bool TryWrite(ref ResizableMemory <byte> writer, ulong value, StandardFormat standardFormat)
        {
            var data = writer.RequestSpan(29); // 18,446,744,073,709,551,615.00

            if (!Utf8Formatter.TryFormat(value, data, out int bytesWritten, standardFormat))
            {
                return(false);
            }
            writer.Advance(bytesWritten);
            return(true);
        }
        public static bool TryWrite(ref ResizableMemory <byte> writer, uint value, StandardFormat standardFormat)
        {
            var data = writer.RequestSpan(16); // 4,294,967,295.00

            if (!Utf8Formatter.TryFormat(value, data, out int bytesWritten, standardFormat))
            {
                return(false);
            }
            writer.Advance(bytesWritten);
            return(true);
        }
Exemple #8
0
        public static bool TryWrite(ref ResizableMemory <byte> writer, long value, StandardFormat standardFormat)
        {
            var data = writer.RequestSpan(29); // -9,223,372,036,854,775,808.00

            if (!Utf8Formatter.TryFormat(value, data, out int bytesWritten, standardFormat))
            {
                return(false);
            }
            writer.Advance(bytesWritten);
            return(true);
        }
        public static bool TryWrite(ref ResizableMemory <byte> writer, Guid value, StandardFormat standardFormat)
        {
            var data = writer.RequestSpan(38); // {ABCDEFGH-ABCD-ABCD-ABCD-ABCDEFGHIJKL}

            if (!Utf8Formatter.TryFormat(value, data, out int bytesWritten, standardFormat))
            {
                return(false);
            }
            writer.Advance(bytesWritten);
            return(true);
        }
        public static bool TryWrite(ref ResizableMemory <byte> writer, DateTimeOffset value, StandardFormat standardFormat)
        {
            var data = writer.RequestSpan(33); // 9999-12-31T11:59:59.999999+00:00

            if (!Utf8Formatter.TryFormat(value, data, out int bytesWritten, standardFormat))
            {
                return(false);
            }
            writer.Advance(bytesWritten);
            return(true);
        }
        public static bool TryWrite(ref ResizableMemory <byte> writer, TimeSpan value, StandardFormat standardFormat)
        {
            var data = writer.RequestSpan(26); // -10675199.02:48:05.4775808

            if (!Utf8Formatter.TryFormat(value, data, out int bytesWritten, standardFormat))
            {
                return(false);
            }
            writer.Advance(bytesWritten);
            return(true);
        }
        public static bool TryWrite(ref ResizableMemory <byte> writer, float value, StandardFormat standardFormat)
        {
            var data = writer.RequestSpan(14); // -3.402823E+038

            if (!Utf8Formatter.TryFormat(value, data, out int bytesWritten, standardFormat))
            {
                return(false);
            }
            writer.Advance(bytesWritten);
            return(true);
        }
        public static bool TryWrite(ref ResizableMemory <byte> writer, double value, StandardFormat standardFormat)
        {
            var data = writer.RequestSpan(22); // -1.79769313486232E+308

            if (!Utf8Formatter.TryFormat(value, data, out int bytesWritten, standardFormat))
            {
                return(false);
            }
            writer.Advance(bytesWritten);
            return(true);
        }
        public static bool TryWrite(ref ResizableMemory <byte> writer, decimal value, StandardFormat standardFormat)
        {
            var data = writer.RequestSpan(30); // -79228162514264337593543950336

            if (!Utf8Formatter.TryFormat(value, data, out int bytesWritten, standardFormat))
            {
                return(false);
            }
            writer.Advance(bytesWritten);
            return(true);
        }
        public static bool TryWrite(ref ResizableMemory <byte> writer, DateTime value, StandardFormat standardFormat)
        {
            // TODO: Will this break in other locales?
            var data = writer.RequestSpan(31); // Fri, 31 Dec 9999 11:59:59 ACWST

            if (!Utf8Formatter.TryFormat(value, data, out int bytesWritten, standardFormat))
            {
                return(false);
            }
            writer.Advance(bytesWritten);
            return(true);
        }
        public static bool TryWriteUtf8Bytes(ref ResizableMemory <byte> writer, ReadOnlySpan <byte> value)
        {
            if (value.Length > ushort.MaxValue)
            {
                return(false);
            }

            writer.Push((byte)EtfTokenType.Binary);
            BinaryPrimitives.WriteUInt32BigEndian(writer.RequestSpan(4), (uint)value.Length);
            writer.Advance(4);
            if (!Utf8Writer.TryWriteString(ref writer, value))
            {
                return(false);
            }
            return(true);
        }
Exemple #17
0
        public static bool TryWrite(ref ResizableMemory <byte> writer, string value)
        {
            var valueBytes = MemoryMarshal.AsBytes(value.AsSpan());

            if (Encodings.Utf16.ToUtf8Length(valueBytes, out var length) != OperationStatus.Done)
            {
                return(false);
            }
            var data = writer.RequestSpan(length);

            if (Encodings.Utf16.ToUtf8(valueBytes, data, out _, out _) != OperationStatus.Done)
            {
                return(false);
            }
            writer.Advance(length);
            return(true);
        }
Exemple #18
0
        public static bool TryWrite(ref ResizableMemory <byte> writer, char value)
        {
            ReadOnlySpan <char> chars = stackalloc char[] { value };
            var valueBytes            = MemoryMarshal.AsBytes(chars);

            if (Encodings.Utf16.ToUtf8Length(valueBytes, out var length) != OperationStatus.Done)
            {
                return(false);
            }
            var data = writer.RequestSpan(length);

            if (Encodings.Utf16.ToUtf8(valueBytes, data, out _, out _) != OperationStatus.Done)
            {
                return(false);
            }
            writer.Advance(length);
            return(true);
        }
        public static bool TryWrite(ref ResizableMemory <byte> writer, float value, StandardFormat standardFormat)
        {
            // TODO: Untested, does Discord have any endpoints that accept floats?
            if (standardFormat.IsDefault)
            {
                writer.Push((byte)EtfTokenType.NewFloat);

                // Swap endian
                Span <double> src      = stackalloc double[] { value };
                var           srcBytes = MemoryMarshal.AsBytes(src);
                var           dst      = writer.RequestSpan(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
            {
                int start = writer.Length;
                writer.Push((byte)EtfTokenType.Binary);
                writer.Advance(4);
                if (!Utf8Writer.TryWrite(ref writer, value, standardFormat))
                {
                    return(false);
                }
                int length = writer.Length - start - 5;
                writer.Array[start + 1] = (byte)(length >> 24);
                writer.Array[start + 2] = (byte)(length >> 16);
                writer.Array[start + 3] = (byte)(length >> 8);
                writer.Array[start + 4] = (byte)length;
            }
            return(true);
        }
Exemple #20
0
 public static bool TryWriteNull(ref ResizableMemory <byte> writer)
 {
     _nilValue.Span.CopyTo(writer.RequestSpan(5));
     writer.Advance(5);
     return(true);
 }
Exemple #21
0
        public static bool TryWriteUtf8Bytes(ref ResizableMemory <byte> writer, ReadOnlySpan <byte> value)
        {
            int i     = 0;
            int start = 0;

            for (; i < value.Length; i++)
            {
                byte b = value[i];

                // Special chars
                switch (b)
                {
                case (byte)'"':
                case (byte)'\\':
                    //case (byte)'/':
                    if (i != start)
                    {
                        int bytes  = i - start;
                        var buffer = writer.RequestSpan(bytes);
                        value.Slice(start, bytes).CopyTo(buffer);
                        writer.Advance(bytes);
                    }
                    writer.Push((byte)'\\');
                    writer.Push(b);

                    start = i + 1;
                    continue;
                }


                if (b < 32) // Control codes
                {
                    if (i != start)
                    {
                        int bytes  = i - start;
                        var buffer = writer.RequestSpan(bytes);
                        value.Slice(start, bytes).CopyTo(buffer);
                        writer.Advance(bytes);
                    }
                    switch (b)
                    {
                    case (byte)'\b':
                        writer.Push((byte)'\\');
                        writer.Push((byte)'b');
                        break;

                    case (byte)'\f':
                        writer.Push((byte)'\\');
                        writer.Push((byte)'f');
                        break;

                    case (byte)'\n':
                        writer.Push((byte)'\\');
                        writer.Push((byte)'n');
                        break;

                    case (byte)'\r':
                        writer.Push((byte)'\\');
                        writer.Push((byte)'r');
                        break;

                    case (byte)'\t':
                        writer.Push((byte)'\\');
                        writer.Push((byte)'t');
                        break;

                    default:
                        var escape = writer.RequestSpan(6);
                        escape[0] = (byte)'\\';
                        escape[1] = (byte)'u';
                        escape[2] = (byte)'0';
                        escape[3] = (byte)'0';
                        escape[4] = ToHex((byte)(b >> 4));
                        escape[5] = ToHex((byte)(b & 0xF));
                        writer.Advance(6);
                        break;
                    }
                    start = i + 1;
                }
                else if (b >= 192) // Multi-byte chars
                {
                    if (i != start)
                    {
                        int bytes  = i - start;
                        var buffer = writer.RequestSpan(bytes);
                        value.Slice(start, i - start).CopyTo(buffer);
                        writer.Advance(bytes);
                    }
                    int seqStart = i;
                    int length   = 1;
                    for (; length < 4 && i < value.Length - 1 && value[i + 1] >= 128; length++, i++)
                    {
                    }

                    Span <ushort> utf16Value = stackalloc ushort[2];
                    if (Encodings.Utf8.ToUtf16(value.Slice(seqStart, length), MemoryMarshal.AsBytes(utf16Value), out _, out int bytesWritten) != OperationStatus.Done)
                    {
                        return(false);
                    }

                    for (int j = 0; j < bytesWritten / 2; j++)
                    {
                        var buffer2 = writer.RequestSpan(6);
                        buffer2[0] = (byte)'\\';
                        buffer2[1] = (byte)'u';
                        buffer2[2] = ToHex((byte)((utf16Value[j] >> 12) & 0xF));
                        buffer2[3] = ToHex((byte)((utf16Value[j] >> 8) & 0xF));
                        buffer2[4] = ToHex((byte)((utf16Value[j] >> 4) & 0xF));
                        buffer2[5] = ToHex((byte)(utf16Value[j] & 0xF));
                        writer.Advance(6);
                    }

                    start = i + 1;
                }
                else if (b >= 128) // Multi-byte chars out of sequence
                {
                    return(false);
                }
            }
            // Append last part to builder
            if (i != start)
            {
                int bytes  = i - start;
                var buffer = writer.RequestSpan(bytes);
                value.Slice(start, bytes).CopyTo(buffer);
                writer.Advance(bytes);
            }
            return(true);
        }