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); }
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); }
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); }
public override bool TryWrite(ref ResizableMemory <byte> writer, T[] value, PropertyMap propMap = null) { if (value == null) { return(EtfWriter.TryWriteNull(ref writer)); } var start = writer.Length; writer.Push((byte)EtfTokenType.List); writer.Advance(4); uint count = 0; for (int i = 0; i < value.Length; i++) { if (!_innerConverter.CanWrite(value[i], propMap)) { continue; } if (!_innerConverter.TryWrite(ref writer, value[i], propMap)) { return(false); } count++; } writer.Array[start + 1] = (byte)(count >> 24); writer.Array[start + 2] = (byte)(count >> 16); writer.Array[start + 3] = (byte)(count >> 8); writer.Array[start + 4] = (byte)count; writer.Push((byte)EtfTokenType.Nil); // Tail return(true); }
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); }
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, 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, 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, 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, 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); }
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, 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, 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, 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, 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, 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 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); }
public override async Task <InputFormatterResult> ReadRequestBodyAsync(InputFormatterContext context, Encoding encoding) { if (context == null) { throw new ArgumentNullException(nameof(context)); } if (encoding == null) { throw new ArgumentNullException(nameof(encoding)); } var request = context.HttpContext.Request; var buffer = new ResizableMemory <byte>(1024 * 4); try { var read = await request.Body.ReadAsync(buffer.RequestMemory(1024 * 4)); while (read > 0) { buffer.Advance(read); read = await request.Body.ReadAsync(buffer.RequestMemory(1024 * 4)); } if (encoding == Encoding.UTF8) { var obj = _serializer.ReadUtf8(context.ModelType, buffer.AsReadOnlySpan()); return(InputFormatterResult.Success(obj)); } else if (encoding == Encoding.Unicode) { var obj = _serializer.ReadUtf16(context.ModelType, buffer.AsReadOnlySpan()); return(InputFormatterResult.Success(obj)); } else { throw new ArgumentOutOfRangeException(nameof(encoding)); } } catch (SerializationException) { return(InputFormatterResult.Failure()); } catch (Exception ex) { throw new InputFormatterException($"Failed to deserialize {context.ModelType}", ex); } finally { buffer.Return(); } }
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); }
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); }
public static bool TryWrite(ref ResizableMemory <byte> writer, DateTime value, StandardFormat standardFormat) { 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); }
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 override bool TryWrite(ref ResizableMemory <byte> writer, T value, PropertyMap propMap = null) { if (value == null) { return(EtfWriter.TryWriteNull(ref writer)); } var start = writer.Length; writer.Push((byte)EtfTokenType.Map); writer.Advance(4); uint count = 0; var properties = _map.Properties; for (int i = 0; i < properties.Count; i++) { var key = properties[i].Key; var innerPropMap = properties[i].Value as PropertyMap <T>; if (!innerPropMap.CanWrite(value)) { continue; } if (!EtfWriter.TryWriteUtf8Key(ref writer, key.Span)) { return(false); } if (!innerPropMap.TryWrite(value, ref writer)) { return(false); } count++; } writer.Array[start + 1] = (byte)(count >> 24); writer.Array[start + 2] = (byte)(count >> 16); writer.Array[start + 3] = (byte)(count >> 8); writer.Array[start + 4] = (byte)count; return(true); }
public override bool TryWrite(ref ResizableMemory <byte> writer, Dictionary <string, T> value, PropertyMap propMap = null) { if (value == null) { return(EtfWriter.TryWriteNull(ref writer)); } var start = writer.Length; writer.Push((byte)EtfTokenType.Map); writer.Advance(4); uint count = 0; foreach (var pair in value) { if (!_innerConverter.CanWrite(pair.Value, propMap)) { continue; } if (!EtfWriter.TryWriteUtf16Key(ref writer, pair.Key)) { return(false); } if (!_innerConverter.TryWrite(ref writer, pair.Value, propMap)) { return(false); } count++; } writer.Array[start + 1] = (byte)(count >> 24); writer.Array[start + 2] = (byte)(count >> 16); writer.Array[start + 3] = (byte)(count >> 8); writer.Array[start + 4] = (byte)count; return(true); }
public static bool TryWriteNull(ref ResizableMemory <byte> writer) { _nilValue.Span.CopyTo(writer.RequestSpan(5)); writer.Advance(5); return(true); }
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); }
public override HttpContent SerializeBody <T>(T body, RequestBodySerializerInfo info) { if (body == null) { return(null); } if (body is IFormData form) { var pairs = form.GetFormData(); var content = new MultipartFormDataContent(); foreach (var pair in pairs) { if (pair.Value is MultipartFile file) { var stream = file.Stream; if (stream.CanSeek) { long remaining = stream.Length - stream.Position; if (remaining > int.MaxValue) { throw new InvalidOperationException("Uploading files larger than Int32.MaxValue bytes is unsupported"); } else if (remaining <= 0) { content.Add(new ByteArrayContent(Array.Empty <byte>()), pair.Key, (string)file.Filename); continue; } var arr = new byte[remaining]; stream.Read(arr, 0, arr.Length); content.Add(new ByteArrayContent(arr), pair.Key, (string)file.Filename); } else { var buffer = new ResizableMemory <byte>(4096); // 4 KB while (true) { var segment = buffer.RequestSegment(4096); int bytesCopied = file.Stream.Read(segment.Array, segment.Offset, segment.Count); if (bytesCopied == 0) { break; } buffer.Advance(bytesCopied); } content.Add(new ByteArrayContent(buffer.ToArray()), pair.Key, (string)file.Filename); } } else { content.Add(new StringContent(_serializer.WriteUtf16String(pair.Value), Encoding.UTF8, "application/json"), pair.Key); } } return(content); } else { var arr = _serializer.Write(body).AsSegment(); var content = new ByteArrayContent(arr.Array, arr.Offset, arr.Count); content.Headers.ContentType = new MediaTypeHeaderValue("application/json"); return(content); } }