| File: System\Text\Json\Writer\Utf8JsonWriter.WriteValues.Bytes.cs | Web Access |
| Project: src\runtime\src\libraries\System.Text.Json\src\System.Text.Json.csproj (System.Text.Json) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System.Buffers.Text; using System.Diagnostics; namespace System.Text.Json { public sealed partial class Utf8JsonWriter { /// <summary> /// Writes the raw bytes value as a Base64 encoded JSON string as an element of a JSON array. /// </summary> /// <param name="bytes">The binary data to write as Base64 encoded text.</param> /// <exception cref="ArgumentException"> /// Thrown when the specified value is too large. /// </exception> /// <exception cref="InvalidOperationException"> /// Thrown if this would result in invalid JSON being written (while validation is enabled). /// </exception> /// <remarks> /// The bytes are encoded before writing. /// </remarks> public void WriteBase64StringValue(ReadOnlySpan<byte> bytes) { WriteBase64ByOptions(bytes); SetFlagToAddListSeparatorBeforeNextItem(); _tokenType = JsonTokenType.String; } private void WriteBase64ByOptions(ReadOnlySpan<byte> bytes) { if (!_options.SkipValidation) { ValidateWritingValue(); } if (_options.Indented) { WriteBase64Indented(bytes); } else { WriteBase64Minimized(bytes); } } // TODO: https://github.com/dotnet/runtime/issues/29293 private void WriteBase64Minimized(ReadOnlySpan<byte> bytes) { // Base64.GetMaxEncodedToUtf8Length checks to make sure the length is <= int.MaxValue / 4 * 3, // as a length longer than that would overflow int.MaxValue when Base64 encoded. To ensure we // throw an appropriate exception, we check the same condition here first. const int MaxLengthAllowed = int.MaxValue / 4 * 3; if (bytes.Length > MaxLengthAllowed) { ThrowHelper.ThrowArgumentException_ValueTooLarge(bytes.Length); } int encodingLength = Base64.GetMaxEncodedToUtf8Length(bytes.Length); Debug.Assert(encodingLength <= int.MaxValue - 3); // 2 quotes to surround the base-64 encoded string value. // Optionally, 1 list separator int maxRequired = encodingLength + 3; Debug.Assert((uint)maxRequired <= int.MaxValue); if (_memory.Length - BytesPending < maxRequired) { Grow(maxRequired); } Span<byte> output = _memory.Span; if (_currentDepth < 0) { output[BytesPending++] = JsonConstants.ListSeparator; } output[BytesPending++] = JsonConstants.Quote; Base64EncodeAndWrite(bytes, output); output[BytesPending++] = JsonConstants.Quote; } // TODO: https://github.com/dotnet/runtime/issues/29293 private void WriteBase64Indented(ReadOnlySpan<byte> bytes) { int indent = Indentation; Debug.Assert(indent <= _indentLength * _options.MaxDepth); // Base64.GetMaxEncodedToUtf8Length checks to make sure the length is <= int.MaxValue / 4 * 3, // as a length longer than that would overflow int.MaxValue when Base64 encoded. However, we // also need the indentation + 2 quotes, and optionally a list separate and 1-2 bytes for a new line. // Validate the encoded bytes length won't overflow with all of the length. int extraSpaceRequired = indent + 3 + _newLineLength; int maxLengthAllowed = int.MaxValue / 4 * 3 - extraSpaceRequired; if (bytes.Length > maxLengthAllowed) { ThrowHelper.ThrowArgumentException_ValueTooLarge(bytes.Length); } int encodingLength = Base64.GetMaxEncodedToUtf8Length(bytes.Length); int maxRequired = encodingLength + extraSpaceRequired; Debug.Assert((uint)maxRequired <= int.MaxValue - 3); if (_memory.Length - BytesPending < maxRequired) { Grow(maxRequired); } Span<byte> output = _memory.Span; if (_currentDepth < 0) { output[BytesPending++] = JsonConstants.ListSeparator; } if (_tokenType != JsonTokenType.PropertyName) { if (_tokenType != JsonTokenType.None) { WriteNewLine(output); } WriteIndentation(output.Slice(BytesPending), indent); BytesPending += indent; } output[BytesPending++] = JsonConstants.Quote; Base64EncodeAndWrite(bytes, output); output[BytesPending++] = JsonConstants.Quote; } } }